聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

作者 | vayne
转载请注明出处

前两篇文章我们基本清楚了在两种不同情况下,webpack 如何处理拆包后的代码:

1、库代码与业务代码分离

2、import() 与 code spliting

默认情况下 chunks 与 modules 都以顺序的数字作为其唯一 id。由于 chunk 中的 module 需要缓存到入口文件的 modules 变量中,为了保证 id 的唯一,多个 chunk 之间的 module id 也是连续的

Chunk 0:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

Chunk 1:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

这种方式有一个缺点,一个 chunk 增删 module,会导致其他 chunk 中的 moduleId 发生改变,增删 chunk,更会导致其他 chunk 的 chunkId 和 包含的 moduleId 同时改变,也就是说一个 chunk 文件无法使用稳定的 hash 作为标识,也就没法使用稳定的浏览器文件缓存了。

第一次打包:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

某个文件增加了一个模块:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

不出所料,全部的 hash 都改变了,现在知道了原因,解决起来就容易了,webpack 官方(https://webpack.docschina.org/configuration/optimization/#optimization-moduleids)提供了优化选项:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

顾名思义,namedChunks 就是为 chunk 命名,moduleIds 可以为 module 取 hash 值(看打包出来的代码,只是按照模块顺序设置了一个不会变的 hash 值,跟内容没有关系),除了固定 chunkId 和 moduleId,还需要做这些配置:

  • output 配置 chunkFileName: '[name].[contenthash:8].js',推荐阅读这篇文章(https://juejin.im/post/5cede821f265da1bbd4b5630)来了解为什么需要使用 contenthash 以及 webpack 中容易混淆的知识点
聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

  • import() 时,使用 /* webpackChunkName: "admin-manage" */ 为 chunk 命名,可以阅读 webpack文档(https://webpack.docschina.org/api/module-methods/#magic-comments)来了解 Magic Comment 的作用。也可以使用 webpack 提供的插件 webpack.NamedChunksPlugin 自己配置 chunkName。
聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

看下打包后的文件

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

某个文件增加了一个模块:

聊聊 webpack 异步加载(三):webpack 如何做到持久化缓存

成为优秀的前端工程师之前不得不成为优秀的 webpack 配置工程师。(我太难了。。。)

实践中发现,上面的方法也不是稳定的。通常我们可能还要把各个 chunk 中的 common 部分单独拆出来,这样 chunk 改来改去,可能会形成新的 common 部分,一个 chunk 改动也可能会引起别的 chunk 更改。另外,webpack 还提供了 optimization.usedExports 选项,用来标识模块中哪些部分没有被别的模块使用,压缩代码时会根据标识来去除没有用的部分,其实也就是 tree-shake。这种情况下,一个 chunk 改动也可能会引起别的 chunk 更改。希望 webpack5 可以解决这个问题,不过想想感觉难度还是不小的,牵扯的部分有点多。

(本系列完)


分享到:


相關文章: