前言
hash一般是结合CDN缓存来使用,通过webpack构建之后,生成对应文件名自动带上对应的MD5值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的HTML引用的URL地址也会改变,触发CDN服务器从源服务器上拉取对应数据,进而更新本地缓存。但是在实际使用的时候,这几种hash计算还是有一定区别。
一、使用步骤
1.Hash
webpack在实例化的时候会在全局创建一 个Tapable子类Compiler, complier实例对象掌握了初始化配置信息,运行编译入口函数,注册和调用插件,该对象掌控webpack 的声明周期,不执行具体的任务,只是进行一些调度任务;
每次编译的时候都会实例化一个对象compilation(单次编译管理器),比如watch =true 时候,运行过程中只有一个complier , 但每次文件变更触发重新编译时,都会重新创建一个新的compilation, 它掌控着从编译开始到编译结束文件,模块的加载,封闭,优化,分块,哈希,重建等等,hash 是根据 compilation 内容 生成 ,也就是说每次文件改动,编译都会创建一个新的hash值, 并且所有文件的hash都是一样的,因为是同一个compilation生成;(当文件未改动,重复编译hash值不变);
output: {
path: path.join(__dirname, "./dist"),
filename: "js/[name].[hash].js",
},
第一次 编译的内容 (当没有设置chunkhash ,异步加载的chunk也会以hash值结尾)
js/app.01335939ddbfa3269ed7.js 43.1 KiB 0 [emitted] [immutable] app
js/app.01335939ddbfa3269ed7.js.map 143 bytes 0 [emitted] [dev] app
js/counter.01335939ddbfa3269ed7.js 13.1 KiB 1 [emitted] [immutable] counter
js/counter.01335939ddbfa3269ed7.js.map 151 bytes 1 [emitted] [dev] counter
js/page1.01335939ddbfa3269ed7.js 5.59 KiB 2 [emitted] [immutable] page1
js/page1.01335939ddbfa3269ed7.js.map 147 bytes 2 [emitted] [dev] page1
js/userInfo.01335939ddbfa3269ed7.js 7.37 KiB 3 [emitted] [immutable] userInfo
js/userInfo.01335939ddbfa3269ed7.js.map 153 bytes 3 [emitted] [dev]
更改文件后再次编译
js/app.e4014597229004c4ce1a.js 43.1 KiB 0 [emitted] [immutable] app
js/app.e4014597229004c4ce1a.js.map 143 bytes 0 [emitted] [dev] app
js/counter.e4014597229004c4ce1a.js 13.1 KiB 1 [emitted] [immutable] counter
js/counter.e4014597229004c4ce1a.js.map 151 bytes 1 [emitted] [dev] counter
js/page1.e4014597229004c4ce1a.js 5.59 KiB 2 [emitted] [immutable] page1
js/page1.e4014597229004c4ce1a.js.map 147 bytes 2 [emitted] [dev] page1
js/userInfo.e4014597229004c4ce1a.js 7.37 KiB 3 [emitted] [immutable] userInfo
js/userInfo.e4014597229004c4ce1a.js.map 153 bytes 3 [emitted] [dev]
2.chunkhash
webpack 打包过程中,每个入口文件都是一个chunk,每个chunk是由入口文件与其依赖所构成,异步加载的文件也被视为是一个chunk, chunkhash是由每次编译模块以及当前chunk 的依赖内容是否生成的hash 值,每个chunk的chunkhash值都不一样, 也就是说每个chunk都是独立开来的,互不影响,每个chunk的更新不会影响其他chunk的编译构建,
配置:
output: {
path: path.join(__dirname, "./dist"),
filename: "js/[name].[chunkhash].js",
chunkFilename: 'js/[name].[chunkhash].js'
},
第一次编译
js/app.b4b996bfbd4844213537.js 43.2 KiB 0 [emitted] [immutable] app
js/app.b4b996bfbd4844213537.js.map 143 bytes 0 [emitted] [dev] app
js/counter.8b8584c9c3f8693c9df1.js 13.1 KiB 1 [emitted] [immutable] counter
js/counter.8b8584c9c3f8693c9df1.js.map 151 bytes 1 [emitted] [dev] counter
js/page1.aac3bf1c56f893d78983.js 5.59 KiB 2 [emitted] [immutable] page1
js/page1.aac3bf1c56f893d78983.js.map 147 bytes 2 [emitted] [dev] page1
js/userInfo.7921db5837ecd0019589.js 7.37 KiB 3 [emitted] [immutable] userInfo
js/userInfo.7921db5837ecd0019589.js.map 153 bytes 3 [emitted] [dev] userInfo
更改其中counter 文件后编译
js/app.d40322c78ae94ac1dfb7.js 43.2 KiB 0 [emitted] [immutable] app
js/app.d40322c78ae94ac1dfb7.js.map 143 bytes 0 [emitted] [dev] app
js/counter.3b42b510a34bc7496a34.js 13.1 KiB 1 [emitted] [immutable] counter
js/counter.3b42b510a34bc7496a34.js.map 151 bytes 1 [emitted] [dev] counter
js/page1.aac3bf1c56f893d78983.js 5.59 KiB 2 [emitted] [immutable] page1
js/page1.aac3bf1c56f893d78983.js.map 147 bytes 2 [emitted] [dev] page1
js/userInfo.7921db5837ecd0019589.js 7.37 KiB 3 [emitted] [immutable] userInfo
js/userInfo.7921db5837ecd0019589.js.map 153 bytes 3 [emitted] [dev] userInfo
app 是入口文件的chunk 对应 hash 或者chunkhash 所依赖的 内容发生变化 ,hash 就会变化
每个chunk都是有css与js组成, 也就是说当其中一个文件发生变化,这个chunk都会重新编译,此时contenthash就出来了。
3.contenthash
缓存优化过程中, 我们希望 各自css 文件和js 文件各自变化,不影响hash 同一chunk内其他模块的hash 值,而是针对文件内容生成不同的hash, 只有当文件内容发生变化此hash才会重新生成,此时需要利用mini-css-extract-plugin插件取提取出每个chunk的css文件,将css与js隔离开}
output: {
path: path.join(__dirname, "./dist"),
filename: "js/[name].[contenthash].js",
chunkFilename: 'js/[name].[contenthash].js'
},
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "css/[name].[contenthash:7].css",
chunkFilename: "css/[id].[contenthash:7].css"
}),
总结:
- 输出js必须也是contenthash结尾, 如果是chunkhash,由于css已经发生变化了,整个chunk在编译时还是会生成新的hash,即使打包出的js内容没有发生变化
- 如果入口文件没有依赖异步chunk,入口文件以contenthash输出不会重新编译,如果入口文件有依赖异步chunk, 那么不管入口文件以哪种hash形式输出,都会重新编译,因为css contenthash已经发生变化了, 通过异步插入的link标签所指定的css文件也发生了变化,代表入口文件的内容就发生了变化, 所以不管哪个hash都会重新编译, 但是异步chunk不会发生变化