「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
上一节内容主要讲了 webpack 如何打包样式文件,这一节将对 webpack 如何打包其它资源(比如图片、字体)做讲解。
准备工作:
-
删除
webpack_css目录下的build和node_modules文件夹; -
拷贝一份
webpack_css目录,并重命名为webpack_资源; -
打开
VS Code的终端,切换目录到webpack_资源下,运行npm install安装当前项目(webpack_资源)所需依赖,安装完成后,项目目录如下:
1. webpack 打包图片资源
在真实开发中,src 目录下除了 css、js 等文件,还会有很多其它的资源,比如图片。所以我们在 src 目录下新建 img 目录,用来存放图片资源。这里,我准备了两张图片(其中一张的大小小于 100KB,另一张的大小大于 100KB),把它们放在这个 img 目录下。
那么假如现在执行 npm run build 命令,会对这个 img 目录下的两张图片进行打包吗?答案是不会的。因为项目中都还没有用到这两张图片。所以,下面我们先在项目中使用它们,一般情况下,在项目中使用图片有两种方式:
- 通过设置
CSS的background-image属性使用图片(为一个元素设置一个或者多个背景图像); - 通过使用
HTML的<img>元素,并指定其src属性的值使用图片(src属性的值就是你想嵌入的图片的文件路径);
我们先来通过第 1 种方式使用图片,在 ./src/js/element.js 中添加相关代码,添加后文件内容如下:
import '../css/style.css';
import '../css/title.less';
const divEl = document.createElement('div');
divEl.className = 'title';
divEl.innerHTML = "你好,同志!";
// 创建一个 div,后续给它设置背景图片
const bgDivEl = document.createElement('div');
bgDivEl.className = 'image-bg';
document.body.appendChild(divEl);
document.body.appendChild(bgDivEl);
现在再来执行 npm run build 命令,我们就能在 DOM 中看到这个 class="image-bg" 的 <div> 元素了:
下面,我们就来给这个 <div> 元素设置背景图片。我们在 ./src/css/ 目录下新建 image.css 文件,文件内容如下:
.image-bg {
width: 200px;
height: 200px;
background-image: url('../img/xxm.jpg');
}
注意,这里需要设置 <div> 的高度(height),不然会看不到背景图片。
现在,我们已经添加了背景图片,但是还没有将这个 image.css 文件加入到依赖图中,所以如果现在进行打包,是不会对这个 image.css 文件进行打包的。为了让这个文件被打包,我们可以来到 element.js 中,引用这个文件:
import '../css/style.css';
import '../css/title.less';
import '../css/image.css'; // 导入 image.css 文件,以将其加入 webpack 的依赖图中
...
为了便于下面讲解有关 loader,我们先重新安装一下较低版本(6.x.x 版本以下的)的 css-loader:
npm install css-loader@5.2.7
然后再来执行 npm run build 命令打包:
你会发现,打包报错了,错误信息告诉我们,./src/img/xxm.jpg 这个模块解析失败了,你可能需要一个合适的 loader 来处理这种文件类型,但当前没有配置 loader 去处理这种文件。这个错误与之前我们遇到过的错误基本上是一样的。
那么,加载图片文件,我们一般使用什么 loader 来进行处理呢?答案是 file-loader:
file-loader的作用就是帮助我们处理import/require()方式引入的一个文件资源,并且会将它放到我们输出的文件夹中;- 当然,我们待会还会学习如何修改它的名字和所在文件夹;
当然,我们这里在通过 background-image 属性设置背景图片时没有使用 import/require() 方式对图片文件进行引入,而是使用 url() 的方式引入图片文件,但其实是一样的,webpack 在遇到 url() 时也会将其当成一个模块进行解析,如果解析不了,就会报上面的错误。
也就是说,当前,我们如果想要使用 url() 引入图片文件,就需要使用 file-loader 了(你可能会觉得我们用到的 loader 好多呀,记不住怎么办,其实,我们可以去 webpack 的官网查看文档(Webpack4 的:v4.webpack.js.org/loaders/ ,Webpack5 的:webpack.js.org/loaders/ ),文档中都有列出的,而且我们常用的可能也就这几个:babel-loader、css-loader、less-loader、postcss-loader、sass-loader、style-loader、stylus-loader)。当然,你会发现,最新的 Webpack5 的文档中,已经没有 file-loader 了,这是为什么?加载图片资源不应该是很常见的吗?这是因为 Webpack5 中已经不推荐使用 file-loader 和 url-loader 了,我们待会会讲到。那为什么我们还要讲它们呢?因为目前,Vue 的脚手架和 React 的脚手架都还没有升级到 Webpack5,它们依然用的 Webpack4,所以我们这里先来讲一下 Webpack4 中的 file-loader 和 url-loader。
我们先来安装 file-loader:
npm install file-loader -D
安装完成后,我们就可以去修改 webpack 的配置了。我们已经知道,当我们想要处理某种类型的文件(模块)时,就需要在 module.rules 中配置相应的 rule。所以我们更新 webpack.config.js 文件中的内容:
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.(jpe?g|png|gif|svg)$/, // 对 jpg/jpeg/png/gif/svg 类型的图片都进行匹配
use: 'file-loader'
}
]
}
}
然后再来执行 npm run build 命令打包:
可以看到,打包成功了(warning 我们暂且不管它),并且在打包输出的 build 文件夹下除了 bundle.js 文件,还多出了一个 .jpg 文件,这个文件的文件名是一个很长的十六进制数值,如果你打开这张图片,就会发现,它对应的就是我们打包前在 ./src/css/image.css 文件中用到的那张图片(./src/img/xxm.jpg),也就意味着,我们在项目中用到哪张图片,哪张图片到时候就会被打包了,而我们之前的另外一张图片没有用到,所以没有在依赖图中,因此就没有被打包。那么之后在部署时,就可以把 build 文件夹(当然,目前里面还缺少其它很多东西,后面我们都会讲到的)直接做一个部署了。
这个时候,你可能会有疑问:之前我们使用图片的路径是 '../img/xxm.jpg',现在打包后,这个图片文件所在的路径(打包后是 ./build/)和名字(打包后是 7f0c9fd9312ad5130670f66ef1f1acb4.jpg)不是都变了吗?那不还得去代码中再给它修改掉吗?事实上,这个东西不需要我们手动来修改,webpack 会自动帮我们将原来的路径修改为打包后的所在路径(当前,上面代码中的图片路径也就变成了 ./build/7f0c9fd9312ad5130670f66ef1f1acb4.jpg,待会,我们可能会觉得打包后的图片全部放在 ./build/ 目录下太乱了,我们想给它生成一个 img 文件夹,把打包后的图片放在 ./build/img 文件夹下,那么到时候图片的路径也会变成在这个 img 文件夹下的路径)。
现在,我们来看页面效果:
可以看到,已经能看到对应的图片了,但因为这张图片比较大而我们的 <div> 元素大小又只有 200px x 200px,所以没有显示完整,我们可以改下 image.css 文件中的样式代码:
.image-bg {
width: 200px;
height: 200px;
background-image: url('../img/xxm.jpg');
/* 让图片完整显示在容器中 */
background-size: contain;
}
我们新增了 background-size: contain 样式,让图片适配所在的容器大小。修改代码后,重新运行 npm run build 命令打包代码(因为修改完源代码就需要重新进行打包,你可能会觉得这太麻烦了,不用担心,我们后面会讲到 webpack 的 devServer,通过在本地搭建一个服务,到时候一旦代码发生了修改,它就能自动进行热更新),再来看页面效果:
现在就可以看见可爱的小熊猫啦~那么我们从图片的引入到打包再到最后的显示就都没有问题啦。
以上,就是 file-loader 的基本使用。它主要用来帮助我们对一些资源(包括 jpg、png 等图片资源以及下面要讲的字体资源)进行打包。