url-loader

url-loader是上一节讲的 file-loader 的增强版,它支持file-loader的所有功能,另外还有一个特殊的功能。

一、url-loader的base64编码

url-loader的特殊功能是可以计算出文件的base64编码,在文件体积小于我们指定的值(单位 byte)的时候,可以返回一个base64编码的DataURL来代替访问地址。

使用base64编码的好处是可以减少一次网络请求,提升页面加载速度。

举个例子,正常img引入图片地址是

  <img src="be735c18be4066a1df0e48a1173b538e.jpg">

使用base64编码后,引入图片地址是"data:image/jpg;base64,iVBORw0KGgoA…"这种格式的,这样就不用去请求存储在服务器上的图片了,而是使用图片资源的base64编码。

  <img src="data:image/jpg;base64,iVBORw0KGgoA...">  <!-- 省略号...表示省略了剩下的base64编码数据 -->

在CSS中引入图片也是同样的道理。

这也是url-loader起这个名字的原因,因为它可以使用base64编码的URL来加载图片。

我们来改造一下 https://github.com/jruit/webpack-tutorial 的webpack3-4例子,除了安装file-loader外,我们还安装url-loader,新的例子是webpack3-6。

我们来看一下webpack的配置文件

  // webpack.config.js
  const path = require('path');

  module.exports = {
    entry: './a.js',
    output: {
      path: path.resolve(__dirname, ''),
      filename: 'bundle.js'
    },
    module: {
      rules: [{
        test: /\.(jpg|png)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 1024 * 8,
          }
        }
      }]
    },
    mode: 'none'
  };

这个配置里,我们使用url-loader处理jpg和png格式的图片,另外设置了参数limit,对于图片体积小于8KB(1024 * 8)的,我们转成base64编码的URL直接写入打包后的JS文件里。

这个例子里,我们引入了两张图片,分别是24KB的sky.jpg和4KB的chrome.png,经过url-loader处理后插入html文档里。

  // a.js
  import img1 from './sky.jpg';
  import img2 from './chrome.png';
  console.log(img1);
  console.log(img2);

  var dom1 = `<img src='${img1}' />`;
  var dom2 = `<img src='${img2}' />`;

  window.onload = function () {
    document.getElementById('img1').innerHTML = dom1;
    document.getElementById('img2').innerHTML = dom2;
  }
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <script src="bundle.js"></script>
  </head>
  <body >
    <div id="img1"></div>
    <div id="img2"></div>
  </body>
  </html>

我们来看一下npx webpack打包后的工程目录

url-loader目录 Webpack教程 姜瑞涛的官方网站

我们用浏览器打开html并开启开发者工具,页面如下

url-loader图片 Webpack教程 姜瑞涛的官方网站

可以看到,因为chrome.png小于8KB,被转成base64编码直接在打包在JS文件里,而24KB的sky.jpg仍然通过file-loader来处理。

二、file-loader与url-loader处理后的资源名称

因为url-loader处理体积大于limit值的时候,本质是使用file-loader来进行处理的,接下来包括第三小节的内容对file-loader与url-loader都适用。

之前例子里file-loader与url-loader处理后的图片是类似于be735c18be4066a1df0e48a1173b538e.jpg的格式,如果你看过本教程之前的 https://www.jiangruitao.com/webpack/hash-chunkhash-contenthash/ 一节,大概可以猜测这是一个hash值。

file-loader生成的文件默认的文件名是"[contenthash].[ext]",contenthash是资源内容hash值,ext是文件扩展名。我们可以通过设置name项来修改生成文件的名字。

file-loader除了[contenthash]和[ext]这两个常用的占位符,还有[hash]和[name],[hash]也是根据内容计算出的hash值,[name]是文件的原始名称。

三、file-loader与url-loader处理后的资源路径

file-loader默认使用output.publicPath作为资源访问地址,output.publicPath的相关内容可以参阅 https://www.jiangruitao.com/webpack/output/ 一节。

当然,也可以在file-loader的配置项options里配置publicPath参数,它会覆盖output.publicPath。

下面我们看一个例子,该例子同时包含了第二和第三小节的知识点,配套代码是 https://github.com/jruit/webpack-tutorial 的webpack3-7

  // webpack.config.js
  const path = require('path');

  module.exports = {
    entry: './a.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'bundle.js'
    },
    module: {
      rules: [{
        test: /\.(jpg|png)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 1024 * 8,
            name: '[name]-[contenthash:8].[ext]',
            publicPath: './dist/'

          }
        }
      }]
    },
    mode: 'none'
  };

注意,这里我们的output.path是path.resolve(__dirname, 'dist'),打包后的图片也会打到工程根目录下的dist文件夹。如果这个时候不设置publicPath,图片的访问路径就是默认的根目录,运行项目时就会发生找不到图片资源的故障。因此,我们设置图片的publicPath是'./dist/',这样就能正常在本地运行项目了。

另外,可以观察项目打包后的图片名称,现在变成了sky-be735c18.jpg,与我们在url-loader里设置的一致。

url-loader打包 Webpack教程 姜瑞涛的官方网站

小结

通过设置limit大小,当资源体积大于limit的时候,url-loader使用file-loader来处理多媒体资源,当资源体积小于limit的时候,url-loader会计算出图片等多媒体资源的base64编码,直接打包到生成的JS或CSS文件里。我们要合理设置limit的值,不使打包后的JS或CSS文件过大,也不要设置地过小,小于1KB的资源没必要再去单独请求一次网络资源。通常会在3KB-20KB选择一个适合当前项目使用。

笔记与思考

发表评论

邮箱地址不会被公开。 必填项已用*标注