Webpack長效緩存實踐

前言

如何使Webpack生成穩定的Chunkid問題解決了,特來反哺社區css

先總結一下。HashedModuleIdsPlugin用於穩定 ModuleId 的,我問的問題核心是 **生成穩
定的ChunkId**,這二者是不同的。webpack

問題描述

有人對Webpack比較瞭解的嗎?git

我這裏有個問題想要請教一下:當咱們新增模塊(也就是entry加了新東西)的時候,怎麼保證ChunkId保持穩定github

好比我在entry下新增長了三個模塊,可是帶動了許多構建後的文件Hash也跟着變更,查看構建後的代碼發現是由於ChunkId發生了遞增致使的。項目已經配置了HashedModuleIdsPlugin,而且生效。web

指望效果 : entry新增模塊後,其餘模塊的構建後的文件Hash沒有變化,提升緩存命中率。json

下面是添加新模塊並打包的先後文件Hash對比segmentfault

添加新模塊先後對比截圖

添加新模塊以前

添加新模塊以後

clipboard.png

如何生成穩定ModuleId

表現:

只修改了 home/index.js 的代碼,但在最終的構建結果中,vendor.js 的文件指紋也被修改了緩存

緣由有兩個:

  1. webpack runtime (運行時) 中包含 chunks ID 及其對應 chunkhash 的對象,但 runtime 被集成到 vendor.js 中。
  2. entry 內容修改後,因爲 webpack 的依賴收集規則致使構建產生的 entry chunk 對應的 ID 發生變化,webpack runtime 也所以被改變。

解決辦法:

  1. 使用CommonsChunkPlugin 繼續將webpack runtime抽離出來
    image
  2. 使用HashedModuleIdsPlugin代替原有的ModuleId根據依賴的收集順序遞增的正整數生成規則。

順便一提,生成穩定的ModuleId在官方文檔 - 緩存中有說起app

早前通過合理的配置(能夠參考用 webpack 實現持久化緩存,實現了其餘模塊變更後,vendor.js的文件指紋不會發生變化的效果)異步

效果以下:

其餘模塊發生變更時,抽離的公共代碼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

官方文檔 - 緩存

相關文章
相關標籤/搜索