3-19 加载图片

在网页中不可避免的会依赖图片资源,例如 PNG、JPG、GIF,下面来教你如何用 Webpack 加载图片资源。

使用 file-loader

file-loader 可以把 JavaScript 和 CSS 中导入图片的语句替换成正确的地址,并同时把文件输出到对应的位置。

例如 CSS 源码是这样写的:

#app {
  background-image: url(./imgs/a.png);
}

被 file-loader 转换后输出的 CSS 会变成这样:

#app {
  background-image: url(5556e1251a78c5afda9ee7dd06ad109b.png);
}

并且在输出目录 dist 中也多出 ./imgs/a.png 对应的图片文件 5556e1251a78c5afda9ee7dd06ad109b.png, 输出的文件名是根据文件内容的计算出的 Hash 值。

同理在 JavaScript 中导入图片的源码如下:

import imgB from './imgs/b.png';

window.document.getElementById('app').innerHTML = `
<img src="${imgB}"/>
`;

经过 file-loader 处理后输出的 JavaScript 代码如下:

module.exports = __webpack_require__.p + "0bcc1f8d385f78e1271ebfca50668429.png";

也就是说 imgB 的值就是图片对应的 URL 地址。

在 Webpack 中使用 file-loader 非常简单,相关配置如下:

module.exports = {
  module: {
    rules: [
      {
        test: /\.png$/,
        use: ['file-loader']
      }
    ]
  }
};

本实例 提供项目完整代码

使用 url-loader

url-loader 可以把文件的内容经过 base64 编码后注入到 JavaScript 或者 CSS 中去。

例如 CSS 源码是这样写的:

#app {
  background-image: url(./imgs/a.png);
}

被 url-loader 转换后输出的 CSS 会变成这样:

#app {
  background-image: url(data:image/png;base64,iVBORw01afer...); /* 结尾省略了剩下的 base64 编码后的数据 */
}

同理在 JavaScript 中效果也类似。

从上面的例子中可以看出 url-loader 会把根据图片内容计算出的 base64 编码的字符串直接注入到代码中,由于一般的图片数据量巨大, 这会导致 JavaScript、CSS 文件也跟着变大。 所以在使用 url-loader 时一定要注意图片体积不能太大,不然会导致 JavaScript、CSS 文件过大而带来的网页加载缓慢问题。

一般利用 url-loader 把网页需要用到的小图片资源注入到代码中去,以减少加载次数。因为在 HTTP/1 协议中,每加载一个资源都需要建立一次 HTTP 链接, 为了一个很小的图片而新建一次 HTTP 连接是不划算的。

url-loader 考虑到了以上问题,并提供了一个方便的选择 limit,该选项用于控制当文件大小小于 limit 时才使用 url-loader,否则使用 fallback 选项中配置的 loader。 相关 Webpack 配置如下:

module.exports = {
  module: {
    rules: [
      {
        test: /\.png$/,
        use: [{
          loader: 'url-loader',
          options: {
            // 30KB 以下的文件采用 url-loader
            limit: 1024 * 30,
            // 否则采用 file-loader,默认值就是 file-loader 
            fallback: 'file-loader',
          }
        }]
      }
    ]
  },
};

除此之外,你还可以做以下优化:

以上加载图片的方法同样适用于其它二进制类型的资源,例如 PDF、SWF 等等。

本实例 提供项目完整代码

results matching ""

    No results matching ""