webpack分離第三方庫(CommonsChunkPlugin並不是分離第三方庫的好辦法DllPlugin科學利用瀏覽器緩存)


webpack算是個磨人的小妖精了。之前一直站在glup陣營,使用browserify打包,發現webpack已經火到爆炸,深怕被社區遺落,趕緊拿起來把玩一下。本來只想玩一下的。嘗試打包了以后,就想啟個webpack服務器,之后就想添加熱替換,什么css文件單獨拆分,各種 loader 處理優化打包結果,各種 source-map 有什么不同,一個都不能少。其中添加熱替換時候,因為應用的服務器和webpack服務器沒有使用同一個,產生了一點波折。然后就到了今天這個主題了。
逐步展開今天的主題:
為什么要分離第三方庫?
這個好處顯而易見,第三方庫是比較穩定的,不會輕易改變,利用瀏覽器緩存后,用戶再次加載頁面會減少服務器請求,提高速度優化體驗。提取多個應用(入口)公共模塊的作用和他類似,公共部分會被緩存,所有應用都可以利用緩存內容從而提高性能。
分離第三方庫就能利用瀏覽器換緩存了么?
同樣顯而易見是否定的,導致無法利用緩存的因素有很多,比如最明顯的有可能你每次分離的庫文件重新打包都會得到不同的名稱,這個比較容易發現,再比如說后台的同事給js文件設置的緩存過期時間為0,這就尷尬了,但0就不能利用緩存了么?並不是,只要文件是完全不變的,注意是完全不變,包括修改時間,依然會利用緩存,性能飛起。想利用緩存必須先了解緩存,這里簡單提一下:
瀏覽器緩存機制是什么樣的?
HTTP1.1給的策略是使用Cache-control配合Etag,
Cache-control設置舉例:
'Cache-Control': 'public, max-age=600',
max-age即過期時間,如果已過期的話,還會查看Etag,
ETag的值:
Apache中,ETag的值默認是對文件的索引節(INode),大小(Size)和最后修改時間(MTime)進行Hash后得到的。
如果Etag相同,依然不會請求新資源,而會使用以前的文件。
CommonsChunkPlugin 到底是用來干什么的?
字面理解,提取公共包,公共包那就是不只一個地方使用嘍,單頁應用(單入口)的庫只有他自己使用,不能算公共包吧?這個插件提取的公共包,每次是會重新打包的(Etag會不同),無論是節約打包時間,(雖然微不足道的時間但畢竟是無用功:庫根本沒變么),還是對瀏覽器緩存的利用(萬一 max-age 過期了你就放棄緩存了么?)都不是好的方案。最佳方案浮出水面:DllPlugin
DllPlugin有什么優勢?
只對庫文件打包一次。也就是說,只要庫文件不變,只需要打包一次,以后再打包業務代碼和庫文件沒關系啦,這樣一來真正做到了庫文件永遠是那個庫文件,只要庫文件不變,緩存永遠有效(Etag不變),打起包來把庫丟到腦后,神清氣爽。介紹一下最簡單的使用方式:
首先另寫一個 webpack 配置文件,畢竟是單獨打包庫了,假設 webpack.config.dll.js

const path = require('path')
const webpack = require('webpack');

module.exports = {
  entry: {
    vendor: ['react', 'react-dom', 'react-hot-loader', 'immutable', 'redux', 'react-redux', 'react-router-dom', 'redux-logger',
      'redux-persist', 'redux-persist-transform-immutable', 'redux-thunk'],
  },
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, 'public'),
    library: '[name]', // 當前Dll的所有內容都會存放在這個參數指定變量名的一個全局變量下,注意與DllPlugin的name參數保持一致
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.resolve(__dirname, 'public/manifest.json'), // 本Dll文件中各模塊的索引,供DllReferencePlugin讀取使用
      name: '[name]',
    }),
  ],
}

在原來的配置文件中添加 DllReferencePlugin 插件

new webpack.DllReferencePlugin({
      manifest: require('./public/manifest.json'), // 指定manifest.json
      name: 'vendor',  // 當前Dll的所有內容都會存放在這個參數指定變量名的一個全局變量下,注意與DllPlugin的name參數保持一致
    }),

終端先運行:
webpack -p --progress --config ./webpack.config.dll.js
把庫文件先打個包,只要庫不變,以后就用這個包了,再打包業務代碼,完活。
推薦策略:
各行其是。
如果是單頁應用,那只用DllPlugin打包庫文件即可,業務代碼一個包搞定。
如果是多頁應用,DllPlugin打包完庫文件,開發時可能會用很多公共的業務代碼而且可能隨時變動,這就要利用CommonsChunkPlugin來做他本該做的事,再把公共業務提取出來,至於緩存,起碼在頁面間切換時,公共部分還是會被緩存的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM