关于 webpack hash值的总结

前言: webpack的hash值是持续缓存和版本控制重要的一部分,webpack中常见到的hash有[hash], chunkhash,contenthash,下面会详细解读下这个三个hash值及如何实现较成熟的打包策略

一.hash-chunkhash-contenthash

[hash]: 根据所有chunk 生成的hash值,也就是每次打包的时候会生成统一唯一的[hash]值,并且某个chunk修改后,hash值都会变,不利于持续缓存

一般的配置:

字体文件,图像文件用file-loader或者url-loader生成的[hash](url-loader是file-loader的加强版,可以通过设置limit的大小,把小图标转化成base64)
css 用extract-text-webpack-plugin插件根据样式文件生成的contenthash
js 用webpack生成的chunkhash

二.持续缓存和版本控制的实现

webpack需要根据chunk的有更改内容才生成新的hash值,并且css,js,图片,字体各自的更改都不会相互影响。

1.合理划分chunk
  • ui.js
    存放一些第三方ui库;
  • vendor.js
    基础库和工具,如:
    'babel-polyfill',
    'core-js',
    'react',
    'react-dom',
    'react-router',
    'react-router-dom',
    'whatwg-fetch'
  • 业务.js
    业务模块代码
2.合理选取webpack插件

提取公共模块后,我们需要保证每次业务模块修改后,生成的新的hash的js文件引用公用模块时不会出错,比如找不到对应模块的代码。

  • CommonsChunkPlugin插件
    提取公共代码最原始的方式是用webpack的CommonsChunkPlugin插件
    new webpack.optimize.CommonsChunkPlugin({
    name: vendor,
    minChunks: Infinity
    }),
    但是这样存在很严重的问题就是每次业务模块更改时,vendor的hash值都会变化,这样造成的结果就是浏览器无法使用缓存的vendor,因此我们还得进一步改造

为解决这个问题曾经有人推荐使用webpack-md5-hash, 但是这个插件有坑,会出现这种问题github.com/erm0l0v/web…
原因:webpack-md5-hash 的原意是为了解决vendor不随业务代码修改而改变hash值,但是结果确实是hash不变了,但是vendor.js里面的模块id却变了,比如业务模块修改前引用了vendor中id为1的模块,修改后打包的vendor原来id为1的模块,现在id变成了2,由于hash值没有变,所以浏览器引用的vendor是来自缓存,导致在vendor里找不到id为2的模块

其实我们最终的目的就是保证vendor的hash值不随业务代码变更而变更,并且正确记录模块之间的引用映射。下面有三种主流的解决方式:

  • NamedModulesPlugin插件

    plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity
    })]

    这个插件是根据chunk在项目的相对路径命名模块id,只要vendor中的模块在根目录下的路径不变,但是路径字符会导致文件大小剧增

  • DllPlugin 插件
    这种方式是把vendor和业务模块分开编译,先编译vendor,然后会生成一个映射表(相对路径对应的id),然后在编译业务模块的时候通过DllReferencePlugin 插件引入这个映射表,从而实现到vendor的映射。

    new webpack.DllReferencePlugin({
    context: '',
    manifest: require('./dist/vendor.json')
    })

    这种方式存在的问题主要是需要分开打包,步骤较繁琐

  • HashedModuleIdsPlugin 插件
    这种方式是对NamedModulesPlugin插件的一种改进,模块的id不再是以相对路径命名,而是根据相对路径生成一个长度小于4的字符串。打包会生成3个文件,manifest,vendor,业务代码,其中manifest主要是记录vendor和业务代码的id和hash值,它的大小只有几kb,小到微不足道。当业务代码变更时,vendor的hash值不会变,变得只有manifest和业务模块的hash,而mainifest中对vendor的id和hash的记录并未更改,从而达到我们的最终目的

    new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor', 'manifest'],
    minChunks: Infinity
    }),
    new webpack.HashedModuleIdsPlugin(),

但是这个插件有个问题:但vendor内容变化是,vendor的hash并未改变,这种情况可能就会在项目更换第三方依赖库的时候导致bug,不过一般开发过程中更换第三方库的情况较少,所以目前没造成什么大的问题

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值