前端小誌(轉型中)

一個用來記錄人老會忘記的地方

webpack production part 下(chunk & manifest)

2018年10月14日
此篇為雜記,我想到啥就記啥。主要的話會跟js caching有關 此篇webpack為4.x version

在前端領域中,bundle是很重要的,dev build跟production build大小,我舉例手上的專案,9mb -> 3xx kb(gzip)。

關於檔案大小的部份不在此介紹中。這應該是比較簡單的part,只要你mode有開prodction應該就差很多了。 (好吧 我想寫caching 上集晚點補)

靜態檔案cache是一個很重要的機制,cache的好,使用者不用每次進網頁都載一次檔案。這點在前端蠻容易被忽略的(至少對於我本人)。在本地端開發的時候很少會感受到file size的影響,上了production習慣開dev tool + disable cached。

cache通常會提到server設定,不過我們這邊要提的如何讓webpack做long term cache

首先要知道的就是一般使用webpack output file會長這樣

output: {
  filename: '[name].[chunkhash].js',
  path: path.resolve(__dirname, '../dist'),
},

為什麼要加hash

基於正常使用者不會每次進入頁面都clean cached,若是今天線上版的foo.js要更新

client端看到foo.js名稱一樣使用舊的cache,後果不堪設想。(頁面極度容易掛掉)

所以每次build的時候依據檔案的內容產生不一樣的的md5加在後面,client端看到不一樣的檔案名稱就會抓取新的檔案

為啥不用 static.file?v=xx.xx.xx 可以看參考

好解法=使用hash file name 先佈static file再佈頁面

這是如果有使用cdn之類的功能的話,如果是docker一起丟file+html是沒差的

請視狀況而定

long term caching講的是如何在每次佈版的時候,只針對最少的js改動(其他保留不變)


hash && chunkhash

了解這兩個的差異是開始的第一步

不過自行了解一下code splitting(我好像沒介紹)

對於hash,計算所有chunks的hash,也就是所有檔案後面接的hash會一樣

對於chunkhash,每個chunk單獨計算hash

不用在dev放上hash,會增加build的時間

我們希望當只有一個檔案更新的時候使用者只需要抓一個檔案,想當然要用chunkhash

至於有使用ExtractTextPlugin的人可以google一下content-hash

因為我們在新的專案使用styled components所以沒有這個問題



這麼簡單的結束了嗎(X)

實際在做旳時候,就算是某檔案完全沒更動也是換了hash value。

上網查了後,我們還需要了解manifest與runtime

runtime

webpack在連接所有的code與module相依時(js load完了沒,這module需要啥其他module),會需要一段code來做這些事情,而這段code就稱之runtime

manifest

當你寫著import, require,compile之後會變成webpack的module,在code裡面常常看到樣的code

__webpack_require__(id) // <<< id

而什麼module對應什麼id這些就是manifest做的

當你新增或刪除module, module排列的id會變動,這些東西寫在chunk裡面每次就需要rebuild。

在webpack4中,可以設置runChunk: true,會將runtime與manifest拉出來(each entry has a runtime)

這樣可以確保剩下的code之中不會挾雜其他的module id

webpack 4.x 沒有 CommonsChunkPlugin


另外對於manifest,拉出來還不夠看。

webpack預設module是name by id(integer)

假設現在有 1 , 2 , 3, ,4 ,5 module

插入了新的module被歸類在3

1不變, 2不變, 3 new, 4 -> original 3, 5 -> original 4, 6, -> original 5

這樣子就rebuild了original 3, 4, 5

所以我們還會引入NamedModulesPlugin, HashedModuleIdsPlugin

一樣是用內容轉成hash,就算上述的事情發生,只需要build new or modified module and rebuild runtimeChunk使用者也不用重新loading file


最後的配置(簡單的)

output: {
  filename: '[name].[chunkhash].js',
  path: path.resolve(__dirname, '../dist'),
},
optimization: {
  runtimeChunk: true,  // this line
  splitChunks: {
    chunks: 'async',
    name: true,
    cacheGroups: { // can do more if you have complex SPA
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      },
      components: {
        test: /[\\/]components[\\/]/,
        name: 'components',
        chunks: 'all'
      }
    }
  }
},
plugins: [
  new webpack.HashedModuleIdsPlugin(), // this line
],

想知道更深的進去參考挖吧

參考1 非常有用

參考2 非常有用


展開Disqus
分類
最近文章
友站連結
© 2019 Ernie Yang