webpack的hash、chunkhash、contenthash

  对于webpack的hash,常用于cdn缓存。我理解的是文件不变的情况下,最后打包出来的hash串也不会变。最近被问到了这是三个hash的区别,就查了一下,发现还很有讲究。

  先看一下三个hash的解释:

  [hash] is a "unique hash generated for every build"[chunkhash] is "based on each chunks' content"[contenthash] is "generated for extracted content"这里有两次代码变更

  原代码:

  // file1.js

  console.log('file1')

  // file2.js

  console.log('file2')

  // file3.js

  console.log('file3')

  // index.js

  require('./file2')

  console.log('index')

  // file1.js

  require('./file1')

  console.log('detail')

  // webpack.config.js

  const path=require('path')

  const webpack=require('webpack')

  module.exports={

  // mode: 'development',

  // mode: 'production',

  entry: {

  index: './src/index.js',

  detail: './src/detail.js',

  },

  output: {

  filename: '[name].[hash].js',

  path: path.resolve(__dirname, 'dist')

  },

  }

  第一次变更:

  // file2.js

  require('./file22')

  第二次变更:

  // index.js

  require('./file2')

  require('./file3')

  console.log('index')

  下面我会以我理解的顺序比较一下三个hash

  hash

  每次构建的生成唯一的一个hash,且所有的文件hash串是一样的。 源代码构建:

  

  第一次变更:

  

  是不是看到非预期的地方了?我只改了file2.js,index.js的hash串变了,但是为什么detail.js为什么也变了?这还怎么有缓存的作用!不行,升级!

  chunkhash

  每一个文件最后的hash根据它引入的chunk决定

  源代码构建:

  

  第一次变更:

  

  这次文件的hash变化符合预期,index的变了,detail的没变

  第二次变更:

  

  你会发现这次变更也是基于index的变更,但是实际上detail的文件内容没有变,那为什么它的hash也跟着变了?

  原因是 module identifier,因为 index 新引入的模块改变了以后所有模块的 id 值,所以 detail 文件中引入的模块 id 值发生了改变,于是 detail 的 chunkhash 也随着发生改变。

  不用怕,webpack已经提供方案了,解决方案是将默认的数字 id 命名规则换成证书路径的方式。webpack 4 中当 mode 为 development 会默认启动,但是production环境还是默认的id方式,webpack也提供了相应的plugin来解决这个问题

  plugins: [

  new webpack.HashedModuleIdsPlugin(),

  ],

  加上这个plugin后,再走一遍上述代码的变更,你会发现第一次、第二次的变更后,detail的hash串仍然没有变化,符合预期。

  在webpack中,有css的情况下,每个entry file会打包出来一个js文件和css文件,在使用chunkhash的情况下,js和css的文件的hash会是一样的,这个时候暴露出来的一个问题:你修一个react的bug,但是并没有改样式,最后更新后,js和css的文件的hash都变了。这个还是不太好,css文件的hash串不变最好,再继续升级!

  contenthash

  contenthash是根据抽取到的内容来生成hash。

  生产环境是不是会使用一个 MiniCssExtractPlugin 来进行css的压缩,这个时候我们在这个plugin里面指定hash为 contenthash ,你会发现修改js文件后,js文件的hash串变了,css的hash串没变!完美。

  new MiniCssExtractPlugin({

  // Options similar to the same options in webpackOptions.output

  // both options are optional

  filename: '[name].[contenthash:8].css',

  chunkFilename: '[name].[contenthash:8].chunk.css'

  })其他

  我查了两个流行的脚手架:create-react-app和umi,发现它们的entry file的配置都是contenthash

  output: {

  filename: '[name].[contenthash].js',

  chunkFilename: 'cfn_[name].[contenthash].js',

  },

  umi使用了 HashedModuleIdsPlugin 来进行稳定的hash构建,但是cra没有,我看有人已经提issue了: github/facebook/cr… ,作者说 optimization.moduleIds: "hashed" 这个也能满足需求,查了 webpack5中optimization.moduleIds 是可以的

  所以目前最佳实践是 contenthash + HashedModuleIdsPlugin/optimization.moduleIds: "hashed"

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值