webpack5中处理图片和字体资源,新版css-loader中的坑

870 阅读3分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战

处理图片资源

file-loader

安装:

 npm install file-loader -D

为了保留原来的名字或扩展名,我们可以使用PlaceHolders进行配置。并且为了防止命名冲突,我们还会使用hash值。

我们这里介绍几个最常用的placeholder:

[ext]: 处理文件的扩展名;

[name]: 处理文件的名称;

[hash]: 文件的内容,使用MD4的散列函数处理,生成的一个128位的hash值(32个十六进制);

[contentHash]: 在file-loader中和[hash]结果是一致的(在webpack的一些其他地方不一样,后面会讲到);

[hash:]: 截图hash的长度,默认32个字符太长了;

[path]: 文件相对于webpack配置文件的路径;

配置:

 {
         test: /.(png|jpg|svg|gif)$/i,
         use: [
           {
             loader: "file-loader",
             options: {
               name: "img/[name]_[hash:6].[ext]",
             },
           },
         ],
       },

我们除了可以直接在name中添加目标文件夹,还有一个属性,专门用于是指文件的存放路径。outputPath

   {
         test: /.(png|jpg|svg|gif)$/i,
         use: [
           {
             loader: "file-loader",
             options: {
               outputPath: "img",
               name: "[name]_[hash:6].[ext]",
             },
           },
         ],
       },

url-loader

url-loader和file-loader的工作方式是相似的,但是url-laoder可以将较小的文件,转成base64的URI。

默认情况下,是将所有的图片都进行base64编码。

安装:

 npm install url-loader -D

我们可以通过limit属性,来设置只有小的图片进行base64编码,大的图片不进行编码。

这是因为小的图片转换base64之后可以和页面一起被请求,减少不必要的请求过程;

而大的图片也进行转换,反而会影响页面的请求速度

配置:

 {
         test: /.(png|jpg|svg|gif)$/i,
         use: [
           {
             loader: "url-loader",
             options: {
               outputPath: "img",
               name: "[name]_[hash:6].[ext]",
               limit: 50 * 1024, //小于50kb的进行编码
             },
           },
         ],
       },

asset module type

webpack5之前,我们使用laoder来处理资源文件。webpack5中,我们可以使用资源模块类型,来替代之前的loader。

资源模块类型(asset module type) ,通过添加 4 种新的模块类型,来替换所有这些 loader:

asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现;

asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现;

asset/source 导出资源的源代码。之前通过使用 raw-loader 实现;

asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现;

自定义文件输出路径:

一、通过generator属性进行配置

  {
         test: /.(png|jpg|svg|gif)$/,
         type: "asset/resource",
         generator: {
           filename: "img/[name]_[hash:6][ext]",
         },
       },

二、在output中添加assetModuleFilename属性;

  output: {
     filename: "bundle.js",
     path: path.resolve(__dirname, "./dist"),
     assetModuleFilename: "img/[name]_[hash:6][ext]",
   },
限制文件编码的大小

实现通过url-loader的limit的效果。

步骤:

  1. 将type改为asset
  2. 添加一个parser属性,并且制定dataUrl的条件,添加maxSize属性;
 {
         test: /.(png|jpg|svg|gif)$/,
         type: "asset",
         generator: {
           filename: "img/[name]_[hash:6][ext]",
         },
         parser: {
           dataUrlCondition: {
             maxSize: 50 * 1024,//小于50kb进行编码,转为base64
           },
         },
       },

处理字体文件

  1. 在css-loader的6版本中,可以处理url()中的资源,因此我们不需要单独处理字体文件资源。
  2. 如果在低版本中,我们可以通过file-loader来处理字体资源。
  3. 在webpack5中可以使用asset modul type来处理字体资源。
     //使用资源模块类型进行处理 
 {
         test: /.(eot|ttf|woff2?)$/,
         type: "asset/resource",
         generator: {
           filename: "font/[name]_[hash:6][ext]",
         },
       },

新版本css-loader中遇到的坑(6.XX版本)

由于要打包图片资源等,所以引入了file-loader或url-loader,这两个loader都可以对图片资源进行打包。

但是由于最新版本(6之后)中可以对css文件中的url进行解析打包,因此如果是在css文件中通过url()引入了图片资源,css-loader是可以处理图片资源的。不需要引入其他的loader。

除了在css中使用图片资源,我们还会在js文件中使用图片资源,因此我们还是需要引入file-laoder或者是url-loader的。但是这里出问题了,这两个loader也会处理css中url()引入的图片资源,最终对同一张图片打包出了两张,并且引发了冲突,最终使用了css-loader打包出来的图片,但是由于冲突,导致图片异常,无法正常的在浏览器中显示。

解决方案:

使用webpack5中的asset module type 来处理资源文件,就可以解决问题了。

切记:使用css-loader(6.XX)就不要使用file-laoder和url-loader,只能使用webpack5为我们提供的asset module type。