Webpack
中文:
缓存 | webpack 中文文档
缓存的场景
import _ from "lodash";
import $ from "jquery";
const dom = $("<div>");
dom.html(_.join(["dell", "less"], ","));
$("body").append(dom)
// ...
module.exports = {
// ...
optimization: {
// TreeShaking 的配置
usedExports: true,
// SplittingCode 的配置
splitChunks: {
// 分割引入代码库的方式,默认为 async 异步,可选 all:同步和异步
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: "chunk"
}
}
},
},
// ...
}
当前npm run build
打包生成的文件:
假设现在把dist
文件放到了服务器中,页面加载了三个文件,就在此时可恶的产品经理提需求了说:给我把字符串用~拼接并且加上Hello Word
。
接着我们去修改源代码代码:
import _ from "lodash";
import $ from "jquery";
const dom = $("<div>");
dom.html(_.join(["dell", "less","Hello Word"], "~"));
$("body").append(dom)
这个时候我们将修改后的代码部署到了服务器,然后用户继续访问页面且进行刷新看到的内容可能还是dell,less
,这是因为我们生成的新的js
文件名没有更改,浏览器的缓存机制认为我们的文件没有更新内容,则直接从缓存中读取js
文件,用户刷新页面依然请求的是缓存的js
文件,这样就会导致内容不同步的问题。
如何解决
只需要给生产环境的配置文件的产生文件名加上contenthash
值就可以了:
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.common.js");
const prodConfig = module.exports = {
output: {
// 当文件内容发生改变后 contenthash 会产生一个新的 hash 值,否则不会改变。
filename: "[name].[contenthash].js",
},
// ...
}
module.exports = merge(commonConfig, prodConfig);
到现在我们可以使用contenthash
的方式去设置文件名重新命名,当src/index.js
文件内容方式了变化就会重新命名main.contenthash.js
当用户浏览网站时,index.html
发现mian.contenthash.js
文件发生了变化就会重新到服务器请求新的内容,而chunk.contenthash.js
文件因为是第三方代码库我们没有更改所以浏览器则可以继续使用缓存的chunk.contenthash.js
文件。
补充
假设老版本的Webpack
配置了filename: "[name].[contenthash].js"
没有改变js
文件内容依然产生了不同的hash
值的时候需要额外添加一个配置
// ...
module.exports = {
optimization: {
runtimeChunk: {
name: 'runtime'
},
// CSS代码压缩
minimizer: [
new CssMinimizerPlugin(),
],
}
}
此时就可以实现老版本 filename: "[name].[contenthash].js"
,但是你会发现dist
目录下多了一个runtime.[contenthash].js
的文件,这是因为runtime
将src/index.js
和loadsh
的关联到这个文件中。