这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战
接上篇文章,本文讲解 url-loader。
url-loader和file-loader的工作方式是相似的,但是可以将较小的文件转成base64 的 URI(这意味着到时候可以和网页内容一起被请求下来)。- 安装
url-loader:npm install url-loader -D - 使用
url-loader:我们只需要将上篇文章中在{ test: /.(png|jpe?g|gif|svg)$/, use: [ { // loader: 'file-loader', loader: 'url-loader', options: { name: 'img/[name].[hash:6].[ext]', // outputPath: 'img' } } ] }webpack配置文件中配置的file-loader改成url-loader即可。
配置完成后我们先把之前打包出来的文件夹(build 文件夹)删掉,再来运行 npm run build,然后去浏览器中查看效果:
可以看到,图片都能正常显示。再来看打包出来的 build 文件夹下的内容:
啊叻,之前使用 file-loader 处理最后生成的图片文件怎么不见了?原因很简单,当我们使用 url-loader 处理文件时,它会通过 base64 编码将原来的文件转成 base64 data,然后将其直接嵌入到 webpack 打包后的输出文件(这里即 bundle.js)中去了。而浏览器是可以解析 base64 的数据的,所以这里就能正常显示图片啦。
在此,我们需要知道 file-loader 和 url-loader 的区别:
file-loader相当于将图片复制一份到输出目录中;- 而
url-loader默认情况下会将所有的图片文件转成base64编码;
那在开发中,对于这两种 loader,我们该如何选择呢?
- 如果所有图片都进行转换(即使用
url-loader的默认配置),就意味着最后打包出来的js文件会变得很大,那么网页就需要花更多时间来加载这一js文件,下载下来之后网页才能把图片等内容渲染出来,这个速度就比较慢了。 - 而如果所有图片都直接使用(即使用
file-loader),虽然减小了最后打包出来的js文件的大小,网页可以快速地将其加载下来,意味着网页可以快速地显示一部分内容(当然,图片的标签已经有了,图片还没有显示)。但弊端在于,每张图片都需要进行一次http请求,这意味着这种方式需要更多的http请求,那么对于前端和服务器的压力都会变大。 - 开发中,我们往往是将比较大的图片放到单独的图片文件中,到时发送单独的
http请求来获取该图片;而对于比较小的图片,为了减少http请求次数,我们一般会将其编码成base64的数据,而后直接嵌入到最后打包出来的js文件中或html中。简单来说,就是小的图片需要转换,而大的图片直接使用即可;- 这是因为小的图片转换为
base64之后可以和页面一起被请求,减少不必要的请求过程; - 而大的图片也进行转换,反而会影响页面的请求速度;
- 这是因为小的图片转换为
所以呢,我们现在希望把前面两张图片中较小的那张转换成 base64,较大的那张依然以图片的形式展示。那该怎么做呢?很简单,只需要在 url-loader 对应的 options 中对 limit 属性进行设置就可以了,limit 属性对应的值可以是一个数值,以字节为单位指定文件的最大大小。如果文件大小等于或大于限制,将使用 file-loader(默认情况下)。比如我们这里希望大小在 100kb 以下的图片到时候被转化成 base64,而 100kb 以上(包括 100kb)的图片到时候以单独的图片格式进行打包,那就可以这样配置:
{
test: /.(png|jpe?g|gif|svg)$/,
use: [
{
// loader: 'file-loader',
loader: 'url-loader',
options: {
name: 'img/[name].[hash:6].[ext]',
limit: 100 * 1024
}
}
]
}
修改完配置后,再来运行 npm run build 查看打包效果:
可以看到,输出目录中的 img 文件夹下只有那张大于 100KB 的图片文件了,而另一张小于 100KB 大小的图片已经被打包到 bundle.js 中了。我们再来到浏览器页面查看效果:
以上就是关于 url-loader 的使用说明。如果我们设置了 limit,url-loader 就会根据我们设置的 limit 决定要不要将对应的资源转成 base64 了。
补充:有了
url-loader就没有必要用file-loader了吗?是的,直接使用url-loader就可以了。