基於webpack工程化的思考

本文章是在基於webpack多入口配置工程而且項目須要持續迭代做爲基礎去討論的,單頁面不做討論。文章適合對webpack有必定了解的人看,主要討論工程化中關於緩存利用率的問題。css

1、如何打包文件讓緩存利用率增高

在webpack中,咱們一般會打包一個vendor和一個common文件做爲基礎包,vendor一般是將npm中的依賴打包、而common則是讓達到必定引用次數的模塊進行打包。具體配置以下:html

vendor

common

以上的配置,在持續迭代中,是不利於持久性緩存的,由於須要持續迭代,不可避免的是業務文件的修改,前端作緩存主要依靠的是經過給文件名加上hash值去控制文件緩存,而webpack1中一旦修改了某個文件,會致使總體的文件hash值的變化,包括vendor和common的hash值,可是這一個缺點在webpack2之後就被處理得比較好了,能夠用HashedModuleIdsPlugin穩定模塊的id,以保證vendor在單個業務文件修改時,其餘文件的hash值保持穩定。前端

可是在持續增加的業務中,這樣的方式對持久化就是可靠的嗎?若是你在增量迭代時,忽然須要引入某一些npm包呢?致使vendor的hash值在這個時候也會發生變化,全部的用戶不得不從新下載一個龐大的vendor文件。vue

根據這種場景咱們能夠如何去優化這個緩存呢?這裏我採用的方案是,將整個項目依賴的基礎包,單獨放在vendor中進行手動配置打包,在入口配置中加入本身手動配置的vendor列表,這一個列表是整個項目最基礎依賴的包。webpack

例如:在一個多入口vue創建的項目中,咱們項目幾乎每一個入口頁面都要引入vue,那麼咱們的vendor列表中就能夠配置上vueios

webpack入口配置中加上這一個鍵值對

讓模塊抽取經過入口名爲vendor的列表進行打包

那麼vendor包中就只會將vue打包進vendor,而其他的模塊則按照引用次數將包打包進common中,這麼作的好處是什麼?在項目迭代中,vendor的打包是咱們能夠控制的,也就是這個列表咱們不修改,則vendor的hash值不變,也就是說在用戶不清除緩存的狀況下,咱們的vendor包能夠一直在緩存中,對於頁面的性能來講是有保證的,變化的模塊也僅僅在common模塊和其餘的業務文件。git

好比,在vue的項目中,咱們集成了vuex、rxjs、axios等庫,在多頁面開發中這些庫基本在每個入口中都會有引用到,那麼咱們是否是能夠將vendor的列表配置成[ 'vue', 'vuex', 'rxjs', 'axios' ],經過commonPlugin則能夠將列表中的模塊打包成vendor,在迭代中,其餘npm包的引入並不會影響到vendor hash值的改變,等到你須要更新vendor時,則能夠手動往列表中添加依賴。程序員

2、dll文件構建自動化

dll文件是在開發時,先對全部的npm包預先打包,每個入口都會引入,以後根據manifest去對npm包資源進行引用,這樣作,在開發時就不須要對npm包進行打包構建,節省一部分時間,具體可google。github

dll

這裏就會涉及到一個問題,每一次npm依賴更新了,都須要從新進行dll文件的打包。做爲一個程序員,很顯然,這麼作不夠偷懶。那咱們能夠如何去作dll文件構建的自動化呢?這裏提供一下個人思路。web

通常咱們在開始時,一般使用npm script進行項目構建、而dll文件須要單獨運行命令,以後再構建項目

webpack --config dll.config.js

webpack-dev-server --config dev.config.js
複製代碼

由於涉及到兩條命令,因此我選擇了使用shell對兩個命令合併

// npm run start命令行執行dev.sh腳本
sh bin/dev.sh
複製代碼
#!/bin/bash
### 思路
###一、在首次構建時,須要生成依賴的數量,並將數據重定向到文件中,用於二次構建時依賴數量的匹配
###二、二次構建時,會先判斷記錄了依賴數量的文件是否存在,存在則讀取數量進行現有依賴數量的匹配,若依賴數量無變化,則認爲dll文件不須要構建,直接運行項目的構建,若依賴數量變化,則從新構建dll文件

### 用於本地開發時自動維護dll文件
rootPath=`pwd`
packagePath=${rootPath}'/package.json'
dllValidatePath=${rootPath}'/build/vendor.dll.validate.txt'

### 讀取package.json的dependencies與devDependencies對應的行數
dependenciesRow=`grep -n "dependencies" $packagePath | cut  -d  ":"  -f  1`
devDependenciesRow=`grep -n "devDependencies" $packagePath | cut  -d  ":"  -f  1`

### 依賴行數(以此判斷依賴是否增減)
rows=$[$devDependenciesRow-$dependenciesRow]

### 判斷vendor.dll.validate.txt文件是否存在
if [ -e $dllValidatePath ]; then

  ### 獲取以前的依賴行數
  oldRows=`cat $dllValidatePath`

  if [ $oldRows == $rows ]; then
    ### 依賴數量相等則直接構建
    npm run dev
  else
    echo $rows > $dllValidatePath
    ### 不等,從新建立vendor.dll.js,並將新的行數寫到vendor.dll.validate.txt
    npm run dll
    npm run dev
  fi

else
  rm -rf build
  mkdir build
  touch $dllValidatePath
  echo $rows > $dllValidatePath
  npm run dll
  npm run dev
fi

複製代碼

上面是經過依賴數量的變化來作實際上是有點bug的,若是依賴增長了以後再減小到相同數量,dll文件並不會從新構建,這時須要本身手動構建一次,因此,嚴謹一些應該是要對依賴列表進行先後對比才能夠肯定dll是否須要變化shell相應的也會更復雜一些吧,之後有時間優化一下這裏的邏輯。

注意:dll文件,最好不要壓縮,由於壓縮插件會將console打印的語句去除,會致使開發時框架或者庫的錯誤提示或者警告丟失。

3、庫的引用

不知道你們有沒一種狀況,就是某一些庫,只是那麼兩三個入口須要使用,可是卻被打包進common中。好比一些即時聊天服務,一般須要引入一些script或者css,而你的common配置中,超過兩個引用次數就會將包打進common中,致使common過大,而每個入口一般都須要引入common,而且這些外部引用的庫會隨着common的打包變化而從新下載,這就會致使用戶沒法持久緩存這部分這種庫。

固然,咱們能夠經過增長common的模塊引用次數下限去將這種庫排除在外,的確能夠,可是這樣對common的控制就會受限,這不是我想的,我想common的配置,與這種業務性很是強的庫抽離出來。

先看一下HtmlWebpackPlugin的配置

html-webpack-plugin配置

scriptComponents

目錄

標記

構建後

這裏咱們經過這個插件的自定義配置,在html中經過標記將script或者css文件以絕對路徑的方式輸出到結果中,這樣咱們就不須要經過webpack對這種稍微大一些又不想打包進common的包進行引用了,直接經過全局script標籤的方式進行引入,以必定的規範放置文件,根據文件的版本作緩存的控制。

4、總結

以上是我對於webpack多入口配置的一些思考以及建議,若有錯誤,歡迎及時指正。下面是github項目地址webpack3-vue-cli

相關文章
相關標籤/搜索