webpack 提供了三种生成 hash 类型的配置,都是用来生成文件 hash 值,可以方便前端开发利用缓存策略来实现静态资源缓存,我们将根据实例来分析三者的区别
前期准备
新建一个空项目,目录结构如下
然后配置下 webpack.config.js
文件
module.exports = {
entry: {
index: "./src/index.js",
index2: "./src/index2.js",
},
};
这里有两个入口文件,分别是 index.js ,index2.js,分别引入 util.js 模块,代码分别如下
// index.js
const util = require("./util");
console.log(util.add(1, 2));
// index2.js
const util = require("./util");
util.add(2, 3);
// util.js
module.exports = {
add(a, b) {
return a + b;
},
};
hash
我们修改 webpack.config.js
文件,新增 output.filename
配置为 [name].[hash].js
module.exports = {
entry: {
index: "./src/index.js",
index2: "./src/index2.js",
},
output: {
filename: "[name].[hash].js",
},
};
命令行输入 webpack --watch
,可以看到首次输出的文件的 hash 值是一致的
接下来改变 index2.js 代码,查看输出文件名,hash 还是一致的
可以得出结论,hash 是项目级的 hash,只要项目的任意一个文件改动,所有的文件 hash 值也会跟着改变,一般项目不使用这种 hash 类型,因为项目庞大的情况下,改动一个文件会导致其他文件 hash 也改动,无法合理利用缓存
chunkhash
我们修改 filename
的配置为 [name].[chunkhash].js
module.exports = {
entry: {
index: "./src/index.js",
index2: "./src/index2.js",
},
output: {
filename: "[name].[chunkhash].js",
},
};
命令行输入 webpack --watch
,可以看到首次输出的文件的 hash 值是不一致的
通过修改 index2.js 代码,查看结果,发现只有 index2.js 文件重新生成了并附带新的 hash 值
可以得出结论,chunkhash 是对应局部关联文件生成的 chunk,例如模块引用了其他模块,则当前模块更新,相关的文件 hash 值也会更新,不过这也会导致另一个问题,不同文件类型虽然有引用的情况,但是关联文件改动我自身不想要更新。例如 js 文件引用 css 文件,js 改变了,css 我不想要更新。
contenthash
为了延时不同类型的文件打包,我们引入 css-loader,在 src 目录下新建 index.css,在 index.js 引入 index.css
// webpack.config.js
module.exports = {
entry: {
index: "./src/index.js",
index2: "./src/index2.js",
},
output: {
filename: "[name].[chunkhash].js",
},
module: {
rules: [
{
test: /\.css$/i,
use: ["css-loader"],
},
],
},
};
const util = require("./util");
const css = require("./index.css");
console.log(util.add(1, 2));
命令行输入 webpack --watch
,可以看到首次输出的文件都是 js 类型,结果同 chunkhash 行为一致
这时候修改 index.css 文件,结果如下
发现 index.css 改变,index.js 也会重新生成,这并不是我们想要的结果
我们再引入 mini-css-extract-plugin
module.exports = {
entry: {
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
},
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
}),
],
};
单独修改 index.css 文件,发现 js 不会重新生成,只有 css 重新生成
可以得出结论,contenthash 是根据文件内容生成的 hash,只有当文件内容改动了才会更新,这很好解上述 chunkhash 带来的问题,利用 mini-css-extract-plugin 来把 css 拆分出来,再配置 contenthash ,就可以把 js 和 css 区分出来
总结
- hash 一般项目不使用
- chunkhash 关联模块改动,不影响无关模块文件的 hash,能合理利用缓存,但是有弊端
- contenthash 使用在 mini-css-ectract-text-plugin 的配置上,能避免不同类型之间(例如 css,js)的依赖