定义
首先看一下官方的定义
-
hash
: 代表的是根据*compilation
*过程计算的hash
,其中compilation代表整个webpack的compiler编译过程,这些过程包括(打包文件内容、webpack配置等) -
chunkhash
: 代表的是根据chunk
内容计算的hash
,chunk在webpack中表示最终打包的输出文件 -
contenthash
:指根据文件内容
计算得来的hash
示例
后面的示例都会根据下面的项目结构和webpack配置进行修改和演示
- 代码结构
--demo4//项目入口文件
--index.js
--style.css
--package.json
--dist-demo4//打包目录
--webpack.config.js
复制代码
- webpack.config.js
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');// 用于抽离css文件,暂时可不管
module.exports = {
entry: {
index1: './demo4/index.js',
},
output: {
filename: '[name].[hash:8].js',
path: path.resolve(__dirname, 'dist-demo4')
},
module: {
rules: [
{test: /\.css$/,
use: [{loader: MiniCssExtractPlugin.loader},'css-loader']}// 用于抽离css文件,暂时可不管
]
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[id].css'
}),
]
}
复制代码
- index.js
console.log('chunk')
复制代码
- style.css
a {font-size: 12px;}
复制代码
hash
根据上述定义,当在整个编译过程中一切都没改变时,所已算的hash是不会变的;但是代码变动或者webpack配置变动都会引起hash的计算变动
代码改变
- 首先我们执行编译
npm start
记录第一次计算的hash,得到hash值为d768a965
Asset Size Chunks Chunk Names
index1.d768a965.js 1.02 KiB 0 [emitted] index1
复制代码
- 修改
index.js
代码并执行npm start查看新的hash值f070105d
// index.js
console.log('chunk changed')
// 编译
index1.f070105d.css 43 bytes 0 [emitted] index1
复制代码
配置更改
- 首先将webpack.config.js的配置做一点修改,编译之后得到hash值
e43fce73
// webpack.config.js:修改插件MiniCssExtractPlugin.chunkFilename
chunkFilename: '[name].[id].css'//增加了[name].
//编译
index1.e43fce73.js 1.01 KiB 0 [emitted] index1
复制代码
注意: 配置更改必须要影响到整个编译过程其hash才会变动,单纯的在webpack.config.js中修改一些无意义代码的话hash是不会变动的
- 简单修改webpack.config.js并执行编译得到hash仍为
e43fce73
// 在webpack.config.js中增加一个console
console.log('the compiler will not change')
// 编译
index1.e43fce73.js 1.01 KiB 0 [emitted] index1
复制代码
chunkhash
根据定义得知chunkhash是根据打包的整个chunk内容计算hash,当整个chunk引入任意一个文件发生变动时,编译的chunk都会修改;
- 首先修改对应的webpack.config.js配置文件,将output的filename修改为
filename: '[name].[chunkhash:8].js',*
;然后在index.js中引入style.css
// wwebpack.config.js修改
output: {
filename: '[name].[chunkhash:8].js',
path: path.resolve(__dirname, 'dist-demo4'),
}
// index.js
import './style.css'
console.log('chunk changed')
复制代码
- 编译打包得到第一次参考的chunkhash为
87319c9f
index1.87319c9f.css 43 bytes 0 [emitted] index1
index1.87319c9f.js 1.01 KiB 0 [emitted] index1
复制代码
- 修改
index.js
的到chunkhash为:266332c3
index1.266332c3.css 21 bytes 0 [emitted] index1
index1.266332c3.js 1.01 KiB 0 [emitted] index1
复制代码
- 修改
style.css
为a {font-size: 14px;}
得到chunkhash为:e84f56fd
index1.e84f56fd.css 21 bytes 0 [emitted] index1
index1.e84f56fd.js 1.01 KiB 0 [emitted] index1
复制代码
注意到上面打包的js和css的chunkhash值都是一样的,但是这里我们的css文件已经通过插件mini-css-extract-plugin
从chunk中抽离出来了,因此我们可能希望打包的css拥有和chunk不一样的hash;此时我们就可以使用contenthash了
contenthash
根据定义contenthash时根据文件内容计算具体的hash值
因此当我们使用mini-css-extract-plugin
将css抽离成一个单独文件时,可将该css的名称配置为filename: '[name].[contenthash:8].css'
,同时也将output打包出的chunk配置成contenthash,这样当css内容变动时,chunk的contenthash不会变动;chunk中非css文件的修改也不会影响到css的contenthash计算
webpack.config.js修改
output: {
filename: '[name].[contenthash:8].js',
path: path.resolve(__dirname, 'dist-demo4'),
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[name].[id].css'
}),
]
复制代码
- 首先拿到第一次编译的contenthash值,
js: ae51424c
css: d8b9fd9f
index1.ae51424c.js 1.01 KiB 0 [emitted] index1
index1.d8b9fd9f.css 21 bytes 0 [emitted] index1
复制代码
- 修改index.js不修改style.css得到,
js: 7a941304
css: d8b9fd9f
;可以看到css的contenthash并没有变动
index1.7a941304.js 1.01 KiB 0 [emitted] index1
index1.d8b9fd9f.css 21 bytes 0 [emitted] index1
复制代码
- 修改style.css不修改index.js得到,
js: 7a941304
css: 00583d11
;可以看到此时js的contenthash没有变动,只有css文件的contenthash变动
index1.00583d11.css 21 bytes 0 [emitted] index1
index1.7a941304.js 1.01 KiB 0 [emitted] index1
复制代码
webpack官方文档
应用场景
当你的网站需要考虑长效缓存,可以使用不同的hash
- 当没有将css从chunk中抽离时直接
使用chunkhash
- 当使用
mini-css-extract-plugin
插件抽离css时[1],可将chunk和css块都使用contenthash
替换达到互不影响的作用 - 不要使用hash,这可能因为webpack的修改导致hash值变动而使缓存失效
关于hash的使用场景,可考虑将其作为版本控制;如将webpack.config.js的output.path更改为path.resolve(__dirname, 'dist-demo4', '[hash:6]')
,这样就会将每次编译的版本保存为一个新目录;其他的场景暂时也想不到,欢迎大家分享:cowboy_hat_face:
脚注
webpack官方文档推荐使用
extract-text-webpack-plugin
抽离css
,但是实际上在webpack4
中因为部分api的废除导致extract-text-webpack-plugin
不再支持了,可以参考该插件的github
介绍 ↩︎