资讯专栏INFORMATION COLUMN

Webpack长效缓存实践

weapon / 3056人阅读

摘要:项目已经配置了,并且生效。期望效果新增模块后其他模块的构建后的文件没有变化,提高缓存命中率。新增这个模块后打包结果结构如下至此,通过实现长效缓存实践完美收官。

前言

如何使Webpack生成稳定的Chunkid问题解决了,特来反哺社区

先总结一下。HashedModuleIdsPlugin用于稳定 ModuleId 的,我问的问题核心是 **生成稳
定的ChunkId**,这两者是不一样的。

问题描述

有人对Webpack比较了解的吗?

我这里有个问题想要请教一下:当我们新增模块(也就是entry加了新东西)的时候,怎么保证ChunkId保持稳定

比如我在entry下新增加了三个模块,但是带动了许多构建后的文件Hash也跟着变动,查看构建后的代码发现是因为ChunkId发生了递增导致的。项目已经配置了HashedModuleIdsPlugin,并且生效。

期望效果 : entry新增模块后,其他模块的构建后的文件Hash没有变化,提高缓存命中率。

下面是添加新模块并打包的前后文件Hash对比

添加新模块前后对比截图

如何生成稳定ModuleId 表现:

只修改了 home/index.js 的代码,但在最终的构建结果中,vendor.js 的文件指纹也被修改了

原因有两个:

webpack runtime (运行时) 中包含 chunks ID 及其对应 chunkhash 的对象,但 runtime 被集成到 vendor.js 中。

entry 内容修改后,由于 webpack 的依赖收集规则导致构建产生的 entry chunk 对应的 ID 发生变化,webpack runtime 也因此被改变。

解决办法:

使用CommonsChunkPlugin 继续将webpack runtime抽离出来

使用HashedModuleIdsPlugin代替原有的ModuleId根据依赖的收集顺序递增的正整数生成规则。

顺便一提,生成稳定的ModuleId在官方文档 - 缓存中有提及

早前经过合理的配置(可以参考用 webpack 实现持久化缓存,实现了其他模块变动后,vendor.js的文件指纹不会发生变化的效果)

效果如下:

如何生成稳定的ChunkId

很多文章都只介绍到如何生成稳定的ModuleId,没有提到生成稳定的ChunkId

后来经过 @dahoshaw的提醒

可以看下Webpack的源码,Webpack是根据模块的顺序递增chunkid,源代码中的applyChunkIds函数,所以官方有提供NamedChunksPlugin插件来根据文件名来稳定你的chunkid

webpackJsonp有三个参数,每次有新的entry加入说明资源数增加了,Chunk数量也会跟着增加。ChunkId也会递增

这有点类似ModuleId递增变动导致的文件指纹变化而导致的长效缓存失效

他推荐的文章 Predictable long term caching with Webpack确实写的不错!

解决办法:

在生产环境中的Webpack配置添加plugin: NamedChunksPlugin

// 使用模块名称作为chunkid,替换掉原本的使用递增id来作为chunkid导致的[新增entry模块,其他模块的hash发生抖动,导致客户端长效缓存失效]
config.plugins.push(new webpack.NamedChunksPlugin((chunk) => {
  // 解决异步模块打包的问题
  if (chunk.name) {
    return chunk.name;
  }
  return chunk.modules.map(m => path.relative(m.context, m.request)).join("_");
}));

最后验证一下,我们先打包一下项目,打包结果结构如下:

dist
├── home
│   ├── haha.dc494f13ed558999751e.js
│   ├── index.2266d24e04004acaa5a6.css
│   └── index.2b15fbd2daa6c833f5d5.js
├── manifest.json
├── runtime.1de86da7006780a96879.js
├── static
│   └── images
│       ├── logo-ea7f33f9bddceac362c1d7f378043187.png
│       └── share-icon-881a5a400142ab60684b3cec860611b4.png
├── sub-home
│   ├── haha.141284e7095f605726ac.js
│   ├── index.7039775e1ba458814d14.js
│   └── index.efd6d51187ec8a058fe6.css
└── vendor.dee373a1cd36f461d200.js

4 directories, 11 files

假设我们打算新增sub-sub-home模块。新增这个模块后打包结果结构如下:

dist
├── home
│   ├── haha.dc494f13ed558999751e.js
│   ├── index.2266d24e04004acaa5a6.css
│   └── index.2b15fbd2daa6c833f5d5.js
├── manifest.json
├── runtime.1de86da7006780a96879.js
├── static
│   └── images
│       ├── logo-ea7f33f9bddceac362c1d7f378043187.png
│       └── share-icon-881a5a400142ab60684b3cec860611b4.png
├── sub-home
│   ├── haha.141284e7095f605726ac.js
│   ├── index.7039775e1ba458814d14.js
│   └── index.efd6d51187ec8a058fe6.css
├── sub-sub-home
│   ├── haha.6501ce2d3a138709282b.js
│   ├── index.c367ca84bd261f36f050.js
│   └── index.efd6d51187ec8a058fe6.css
└── vendor.dee373a1cd36f461d200.js

5 directories, 14 files

至此,通过Webpack实现长效缓存实践完美收官。

参考

项目演示地址

知乎 - webpack 每次打包公用vendor 每次hash都会变化,有办法解决吗?

用 webpack 实现持久化缓存

Predictable long term caching with Webpack

官方文档 - 缓存

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89026.html

相关文章

  • webpack 4.x学习使用总结

    摘要:最近一周一直都在折腾一些项目中常用的记录下来,以后免去简单的配置再去查文档。常规入口指示应该使用哪个模块,来作为构建其内部依赖图的开始。把代码转换成,在使用语言中有介绍。扩展语法,使用下一代,在使用中有介绍。用于忽略部分文件。 最近一周一直都在折腾webpack,一些项目中常用的记录下来,以后免去简单的配置再去查文档。 常规 1.入口 指示 webpack 应该使用哪个模块,来作为构建...

    ls0609 评论0 收藏0
  • Webpack 4.0 CommonsChunkPlugin 和 optimization spli

    摘要:可以通过配置属性进行修改,默认将会自动创建个库文件仅含有依然会创建个库文件仅含有假设所有的体积都大于将会创建一个库文件和一个通用组件文件仅含有当这些体积小于是,会故意将该模块复制到三个文件中。 该文章内容大致翻译自 webpack 4: Code Splitting, chunk graph and the splitChunks optimization 原有的问题 webpack...

    Caizhenhao 评论0 收藏0
  • 基于Mobx的多页面小程序的全局共享状态管理实践

    摘要:所以虽然是是用在小程序上,不过我想对于的状态管理,也有这么一丢丢启发。在目录下放入和这两个库,同时在目录下新建用于存放全局状态。建立由于小程序中不支持装饰器,所以采用了的写法。另外,小程序中不支持路径的省略。 what 名字很长很绕靠口,总的来说,本文是对开发小程序过程中使用mobx的一个总结。 状态管理,相比大家也很熟悉,顾名思义,是对前端页面繁复的状态进行管理,在此,我也不过多赘...

    SexySix 评论0 收藏0
  • Webpack 最佳实践总结(二)

    摘要:默认做法是告诉浏览器这个文件的缓存时间,然后当文件内容被修改,则需要重命名该文件告诉浏览器需要重新下载和缓存,例如也能做类似的工作。 上一篇介绍了 Webpack 优化项目的四种技巧,分别是通过 UglifyJS 插件实现对 JavaScript 文件的压缩,css-loader 提供的压缩功能,配置NODE_ENV可以进一步去掉无用代码,tree-shaking帮助找到更多无用代码 ...

    Stardustsky 评论0 收藏0

发表评论

0条评论

weapon

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<