阅读 252

webpack4 持久化缓存(长缓存)

关于缓存这里不多说,如果有点遗忘的,可以通过 一文读懂前端缓存 这篇文章补补课。本文要说的是,我们如何通过合理配置 webpack 去实现每次上线发布的静态资源 (CSS, JS, 图片) 的文件名称都是独一无二的。

 可能你会说,配 hash 咯,但是关于 hash,其实里面有不少小细节。本文主要回答两个问题:1)hash、chunkhash 和 contenthash 的区别;2)在 webpack 中如何固定 chunkhash。如果这两个问题你都已经能解答,那可以不用浪费时间往下读啦

hash

hash 模块识别码,用来处理模块之间的依赖关系。hash 是跟每一次 webpack 打包的过程有关,任意增添或删减一个模块的依赖,hash 值都会更改,并且全部文件都共用相同的 hash 值。

hash.png

为什么图片也是采用 hash 值却和别人不一样呢? 因为 file-loader 的 hash 字段是这个 loader 自己定义的占位符,和 webpack 的内置 hash 字段并不一致。

chunkhash

chunkhash 根据不同的入口文件进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。只要我们不改动代码,就可以保证其哈希值不会受影响。

但是要保证 chunkhash 值在相关代码不变动的情况下也不变,还要做以下的事情:

1. 提取运行时代码

默认情况下,每个分离出来的 chunk 会包含 webpack 的 runtime 代码(用来解析和加载模块之类的运行时代码),所以即使该 chunk 没有改变,其他 chunk 改变了,chunkhash 值也会改变,所以需要提取这部分代码即:


optimization: {

  runtimeChunk: {

    name'manifest'

  }

}

复制代码

2. 固定moduleId

模块 id 默认是按引入的顺序排序的,所以即使文件内容没有变动,引入文件的顺序变动了,chunkhash 可能也会变动,所以模块 id 的排序规则也要改变。development 下默认采用路径的方式:


optimization: {

  namedModulestrue

}

复制代码

生产环境使用全路径是有点太长所以可以使用 HashedModuleIdsPlugin 插件来根据路径生成 hash。

code.png

如上代码块,我们不改变 a.js 和 b.js 内的代码,只是调换两者引入的顺序,如果没有设置 namedModulesa.js 和 b.js的 chunkhash 值都会改变,打包效果对比如下图:

nameModules.png

3. 固定chunkId

默认情况,生产环境下 chunks ID 是以自增的数字命名,所以我们增加 chunk 或者减少 chunk 的时候,也会导致顺序乱掉。所以,我们要固定 chunkId:


optimization: {

  namedChunkstrue // 默认情况下,开发环境为 true,生产环境为 false

}

复制代码

chuckname.png

这里有点小困惑,为什么默认情况下,开发环境为 true,生产环境为 false 贴出git的解答

简单来说就是固定 chunkId 会导致:1)打包大小增加一点点;2)chuck 名暴露

Tips[chunkhash:8] 类似这种写法是截取 hash 值的前 8 位,在生产环境不要这么做!取完整值 [chunkhash]

webpack@3 中如果 JS 和 CSS 文件都采用 chunkhash,CSS 文件改变,chunkhash 值不会改变。只有 JS 文件改变,chunkhash 值才会改变。而在 webpack@4 中,不管是 CSS 文件还是 JS 文件改变,chunkhash 值都会改变。

但这都不是我们想要的结果,所以 CSS 文件的 hash 值应该采用 contenthash,以区分 CSS 文件和 JS 文件的更新。

contenthash

contenthash 根据当前文件的内容,来计算 hash 值。

那 JS 文件可以用 contenthash 吗? 可以,webpack 4.3+ 后。因为 contenthash 一开始只是被一些例如 extract-text-webpack-plugin 的插件使用,但是 webpack 4.3+ 后,webpack 自身也支持了。

总结

- 生成稳定的 hash 文件名(图片、字体等资源使用 hashcontenthash, js资源使用 chunkhash,css 资源使用 contenthash

- 提取 webpack 的 runtime 代码

- 固定 moduleIdchunkId


参考资料

Webpack 4 如何优雅打包缓存文件

webpack 学习笔记之十一 hash chunkhash contenthash

文章分类
前端
文章标签