webpack对输出文件名可以有三种hash值:
1. hash
2. chunkhash
3. contenthash
为什么需要hash?
浏览器会缓存我们的文件。
优点是浏览器读取缓存的文件,能带来更佳的用户体验(不需要额外流量,速度更快);
缺点是有时候我们修改了文件内容,但是浏览器依然读取缓存的文件(也就是旧文件),导致用户看到的文件不是最新的。
这也是为什么以前有时需要在js文件后面拼接上一个版本号
eg: https://xxx.cdn.cn/index.js?version=1.1
hash
hash是项目级别的,使用hash的缺点是假如我只改了其中一个文件,但是所有文件的文件名里面的hash都是一样的。
这样会导致本来应该被浏览器缓存的文件,强制要去服务器读取一遍,网络请求数变多了,页面加载有可能就变慢了,用户体验就差了。
module.exports = {
output: {
filename: 'js/[name]_[hash:8].js',
path: path.resolve(__dirname, '../dist'),
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name]_[hash:8].css',
}),
]
}
有没有可能做到只有改变了文件,hash值才变,而没有改变的文件,文件名里面的hash值就不变呢? chunkhash可以做到这一点
chunkhash
chunkhash根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值。
在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
// entry 加多一个入口
module.exports = {
entry: {
app: path.resolve(__dirname, '../src/index.js'),
test: path.resolve(__dirname, '../src/test/test.js'),
},
output: {
filename: 'js/[name]_[chunkhash:8].js',
path: path.resolve(__dirname, '../dist'),
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name]_[chunkhash:8].css',
}),
]
}
第一次打包
随便修改了index.js中的一点东西
第二次打包
第二次打包后发现打包出来的test.js的hash值并没有变化,app.js的hash和第一次的hash不一样了,说明chunkhash做到了,只改变修改的文件的hash。
但是为什么css文件的hash和app文件的hash是一样的,但是css文件并没有被修改,是因为css文件是被import到了index.js中的,css文件和index.js建立了依赖关系,所有它们的chunkhash是一样的,这样还是存在缓存没有被充分利用的问题。
contenthash
contenthash是针对文件内容级别的,只有你自己模块的内容变了,那么hash值才改变。
所以我们可以通过contenthash解决上面的问题。
第一次打包
修改index.js
第二次打包
两次的css文件的hash是一样的,app.js文件的hash发生了改变