如果每次构建输出的文件名称是一样的,会给在客户端做长缓存带来很大的麻烦。因此,我们需要在输出的文件名中添加一些 hash 值,使得每次构建输出的文件名称是不一样的。
从 Webpack 5 开始,Webpack 开始使用固定的方式来决定输出的文件名,我们可以通过
optimization.moduleIds
和optimization.chunkIds
这两个字段进行控制。
占位符(placeholder)
Webpack 提供了一些占位符:
[id]
返回 chunk id[path]
返回文件路径[name]
返回文件名[ext]
返回文件扩展名[fullhash]
返回本次构建的 hash,如果本次构建过程中有任何一部分发生变化,这个 hash 也会变化[chunkhash]
返回每一个 entry chunk 的 hash。Webpack 配置定义的每一个 entry 都有一个自己的 hash,当 entry 中任何一部分发生变化,这个 hash 也会发生变化。[chunkhash]
比[fullhash]
粒度更细一点。[contenthash]
返回模块内容的 hash。从 Webpack 5 开始,这个 hash 值被默认使用在生产模式构建中。
假设有如下配置:
const config = {
output: {
path: PATHS.build, filename: "[name].[contenthash].js", },};
Webpack 构建输出的文件名为:
main.d587bbd6e38337f5accd.jsvendor.dc746a5db4ed650296e1.js
此时,如果文件内容发生变化,则 [contenthash]
也会相应的变化,此时,浏览器缓存就会失效,浏览器就会重新发起一个请求来加载变化了的文件。即,如果仅仅只要 main.js
发生了变化,那么浏览器只会重新请求加载 main.js
。
我们还可以将 hash 值加载请求参数中,比如 main.js?d587bbd6e38337f5accd
, 这样的话,输出文件名不变,通过查询参数的变化来使缓存失效。
使用占位符
webpack.config.js
const productionConfig = merge([ {
output: {
chunkFilename: "[name].[contenthash].js", filename: "[name].[contenthash].js", assetModuleFilename: "[name].[contenthash][ext][query]", }, }, ...]);
同时,我们还要给 css 也加上 hash。
webpack.parts.js
exports.extractCSS = ({ options = {}, loaders = [] } = {}) => {
return {
... plugins: [ new MiniCssExtractPlugin({
// filename: "[name].css", filename: "[name].[contenthash].css", }), ], };};
执行 npm run build
,可以看到输出如下:
⬡ webpack: Build Finished⬡ webpack: assets by path *.js 129 KiB asset 935.a25ff4285adcf5d835fd.js 126 KiB [emitted] [immutable] [minimized] (id hint: vendors) 2 related assets asset main.fdae79f138a0e0cd6a30.js 3.38 KiB [emitted] [immutable] [minimized] (name: main) 1 related asset asset 958.1752e720e564a63a9d5f.js 204 bytes [emitted] [immutable] [minimized] 1 related asset asset main.dd02bdb46b234aa6a450.css 1.37 KiB [emitted] [immutable] [minimized] (name: main) asset index.html 322 bytes [emitted] Entrypoint main 131 KiB (182 KiB) = 935.a25ff4285adcf5d835fd.js 126 KiB main.dd02bdb46b234aa6a450.css 1.37 KiB main.fdae79f138a0e0cd6a30.js 3.38 KiB 2 auxiliary assets runtime modules 7.92 KiB 10 modules orphan modules 465 bytes [orphan] 2 modules code generated modules 133 KiB (javascript) 4.18 MiB (css/mini-extract) [code generated] modules by path ./node_modules/ 133 KiB modules by path ./node_modules/react/ 6.48 KiB 2 modules modules by path ./node_modules/react-dom/ 119 KiB 2 modules modules by path ./node_modules/scheduler/ 4.91 KiB ./node_modules/scheduler/index.js 198 bytes [built] [code generated] ./node_modules/scheduler/cjs/scheduler.production.min.js 4.72 KiB [built] [code generated] ./node_modules/object-assign/index.js 2.06 KiB [built] [code generated] modules by path ./src/ 633 bytes (javascript) 4.18 MiB (css/mini-extract) ./src/index.js + 2 modules 600 bytes [built] [code generated] css ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[0].use[2]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[0].use[3]!./src/main.css 4.18 MiB [code generated] ./src/lazy.js 33 bytes [built] [code generated] webpack 5.11.1 compiled successfully in 18695 ms
现在尝试编辑 main.css
,可以发现构建输出的文件名发生了变化。
总结
Webpack 提供的占位符可以帮助我们给输出文件名添加额外信息。
在这些占位符中,最有价值的是 [name]
, [contenthash]
和 [ext]
。 [contenthash]
基于文件内容生成 hash 值。
如果要导出 css 文件,即用了 MiniCssExtractPlugin
,那么也需要在 css 文件名中使用 [contenthash]
。