webpack图片资源处理

678 阅读2分钟

04-webpack加载图片资源

本系列文章是我在学习webpack时的总结与收获。本片文章为系列文章的第四篇,包含webpack4及webpack5中对图片资源打包的处理方法。

webpack 4

在 webpack 4 中,常常使用 url-loader 以及 file-loader 来处理图片资源。

file-loader

file-loader:The file-loaderresolves import/require()on a file into a url and emits the file into the output directory.

url-loader:A loader for webpack which transforms files into base64 URIs.

Usage

  1. 在 webpack.config.js 中添加 file-loader / url-loader

    module: {
    	{
    		test: /\.(jpge?|png|gif|svg)$/,
    		use: [
    			loader: "url-loader" // file-loader
    		]
    	}
    }
    
  2. 在文件中引入图片等资源

    import Iamge from '../img/DSC02820.jpg';
    const imgEl = new Image();
    imgEl.src = Iamge;
    //-------------------------------------------------
    const imgEl = new Image();
    imgEl.src = require("../img/DSC02820.jpg").default;
    

打包后图片的名字为:

Untitled.png

打包后图片资源的名字是经过md4 摘要算法计算出来的 128bit 的字符串,但是字符串不方便与源文件对应,所以希望可以更加有效的命名打包后的图片

webpack.config.js 中配置改为:

module: {
            {
                test: /\.(jpge?|png|gif|svg)$/,
                use: [
                        loader: "url-loader", // file-loader
                        options: {
                                name: "img/[name].[hash:6].[ext]"
                        }
                    ]
            }
        }

该配置表明:打包后,图片资源放在 img 文件下,name 表示图片原本的名字,[hash:6] 表示取 6 位hash值作为图片名字的一部分,ext 表示后缀名

Untitled 1.png

文件名称规则

有时我们处理后的文件名称按照一定的规则进行显示:

  • 比如保留原来的文件名、扩展名,同时为了防止重复,包含一个hash值等
  • 这时可以使用placeholders来完成

常用的placeholders

名称含义
[ext]处理文件的扩展名
[name]处理文件的名称
[hash]文件的内容,使用MD4散列函数处理,生成的一个128位的hash值
[hash:]截取hash的长度,默认32个字符太长了

url-loader 和 file-loader的区别

file-loader 会将文件复制到指定的打包目录,并返回 public URL

url-loader 功能与 file-loader 相似,但对于不同大小的文件有不同的做法。设定 limit 值,

  • 当文件大小(byte)< limit ,返回一个 DataURL,嵌入到 bundle.js 中
  • 当文件大小(byte)> limit,复制文件到指定打包目录

webpack 5

在webpack5之前,加载这些资源我们需要使用一些loader,比如raw-loader、url-loader、file-loader

从webpack5开始,可以直接使用资源模块类型asset module type,来替代上面的loader

资源模块类型,通过添加四种新的模块类型,来替换所有的loader

  • asset/resource:发送一个单独的文件并导出url,之前使用file-loader
  • asset/inline:导出一个资源的data URI,之前通过使用url-loader实现
  • asset/source:导出资源的源代码,之前通过使用raw-loader实现
  • asset:在导出一个data URI 和 发送一个单独的文件之间自动选择,之前通过url-loader,并且配置资源体积实现

asset/resource

{
        test: /\.(jpe?g|png|gif|svg)$/,
        type: "asset/resource"
}

当匹配到图片类型时,不再使用file-loader或url-loader,直接使用asset/resource类型,依然可以完成打包。

打包之后,如图所示:

Untitled.png

在没有设置路径的情况下,会直接放到 build 目录下。若想设置目录,需要在 output 中设置assetModuleFilename

output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, './build'),   // 出口必须是绝对路径
    assetModuleFilename: "img/[name].[hash:6][ext]"  // 同样可以设置placeholder
}

但是,这种设置方式会将所有针对 assetModule 打包的文件放在一起,不利于分类管理。

因此,针对每种匹配做不同的设置,是较好的方式:

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

asset/inline

这种方式会将资源转为base64编码,并l放入bundle.js

{
        test: /\.(jpe?g|png|gif|svg)$/,
        type: "asset/inline",
}

asset

这种类型会根据图片的大小分别对待,和url-loader种的limit一样

{
        test: /\.(jpe?g|png|gif|svg)$/,
        type: "asset",
        generator: {
          filename: "img/[name].[hash:6][ext]"
        },
				// 限制写在parser中
        parser: {
          dataUrlCondition: {
            maxSize: 100 * 1024
          }
        }
      }

References

1.webpack