webpack稳定moduleid和chunkid以实现静态资源强缓存

原创
2021/08/27 00:44
阅读数 2K
AI总结

webpack稳定moduleid和chunkid以实现静态资源强缓存

  • hash的种类:
    1. hash是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的hash值都会更改,并且全部文件都共用相同的hash值
    2. chunkhash它根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值, 比如一个js文件中引入css,但是会生成一个js文件,一个css文件,但是因为入口是一个,导致他们的hash(chunkhash)值也相同,所以当只有js修改时,关联输出的css、img等文件的hash值也会改变,但是入口js所引用的css、img的发生改变,整个chunkhash是不会发生变化
    3. contenthash主要是处理关联性,比如一个js文件中引入css,但是会生成一个js文件,一个css文件,但是因为入口是一个,导致他们的hash(chunkhash)值也相同,所以当只有js修改时,关联输出的css、img等文件的hash值也会改变,这种情况下就需要contenthash了

根据以上hash的特性,我们知道我可以使用contenthash来完成静态文件的强缓存,但是当把其中入口js中所引用的css、img等文件删除掉后,会发现打包后,所有的hash都发生变化了,至于是为什么,那是因为moduleId发生了变化,moduleId即对于胶水代码中的那个文件map的key,所以要保证静态文件的稳定moduleId, 最终的打包代码中通过__webpack_require__(moduleId)去加载对应的chunk, moduleId是一个数字

保持稳定的moduleId

  1. 改变moduleId的生成规则
  2. 何时去改变moduleId
  • 由于文件的路径是唯一的,所以这里采用文件的路径做为moduleID
  • 在整个webpack打包的过程中涉及到moduleId的钩子有三个:
    1. before-module-ids
    2. optimize-module-ids
    3. after-optimize-module-ids

我们在before-module-ids这个钩子里修改moduleId, 见插件代码:

class moduleIDsByFilePath {
    constructor(options) {}
    apply(compiler) {
        compiler.plugin('compilation', compilation => {
            compilation.plugin("before-module-ids", (modules) => {
                modules.forEach((module) => {
                    // 通过module.libIdent获取模块的路径
                    if(module.id === null && module.libIdent) {
                        module.id = module.libIdent({
                            context: this.options.context || compiler.options.context
                        })
                    }
                })
            })
        })
    }
}
module.exports = moduleIDsByFilePat

不过上述的插件已经被webpack官方抽成一个插件了,NamedModulesPlugin, 我们只需要在插件中使用new webpack.NamedModulesPlugin()即可,不过官方说 NamedModulesPlugin 适合在开发环境,而在生产环境下请使用 HashedModuleIdsPlugin

保持稳定的chunkId

在我们的entry chunk数量没有发生变化的时候,改变一个entry chunk的内容导致runtime内容发生变化的只有chunk id,这个时候问题就又来了。根据上面稳定module id的操作一样,数值型的chunk id不稳定性太大,我们要换,方式和上面一样。chunkId也是有相关的钩子

  1. before-chunk-ids
  2. optimize-chunk-ids
  3. after-optimize-chunk-ids

下面见修改chunkId的插件:

class chunkIDsByFilePath {
    constructor(options) {}
    apply(compiler) {
        compiler.plugin('compilation', compilation => {
            compilation.plugin('before-chunk-ids', chunks => {
                chunks.forEach(chunk => {
                    chunk.id = chunk.name
                })
            })
        })
    }
}

同样的webpack官方也是提供了插件,NamedChunksPlugin

综上所述,通过contentHash保证保证静态文件的hash稳定,而通过保证moduleId的稳定进一步保证在module发生变化的时候,contentHash能够不发生变化, 最后通过保持chunkId稳定,保持runtime.js不会发生变化,进而保证静态文件能够被浏览器强缓存,减少网络请求

对于webpack5缓存优化

moduleIds和chunkIds设置为natural时,每个module.id 和 chunk.id会默认地基于解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变

  1. webpack5对于生产模式下,moduleIds和chunkIds会默认设置为deterministic
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
AI总结
返回顶部
顶部