webpack打包優化以外部擴展externals的實際應用

前言

使用vue-cli建立項目,使用webpack打包。其中,有一個webpack優化webpack.optimize.CommonsChunkPlugin,它會將node_modules中的必需模塊提取到vendor文件中,項目開發中,增長第三方模塊,好比element-uivue-echarts等,vendor的包都會增大。這個時候,就須要考慮減輕vendor包的大小,增長構建速度。咱們可使用webpack的外部擴展(externals)功能。vue

externals定義

externals配置選項,將指定的內容排除在構建的vendor中,可是,指定的內容須要出如今用戶環境中。
以上是個人理解。node

官方解釋是:
The externals configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment.
externals配置選項提供了「從輸出的 bundle 中排除依賴」的方法。相反,所建立的 bundle 依賴於那些存在於用戶環境(consumer's environment)中的依賴。jquery

用法

防止將某些 import的包打包到bundle中,而是在運行時(runtime)再去外部獲取這些擴展依賴(external dependencies)
能夠經過多種編寫方式實現:string,array,object,function,regex。這裏,我只說一些簡單的內容,詳細講解,我以爲這個解釋不錯。webpack

module.exports = {
  // ...
  externals: [ // array形式
    { // object形式
      './a', 'a', // string形式
      jquery: 'jQuery', 
      vue: 'Vue',
    },
    function(context, request, callback) { // function形式
      if(request.substr(0, 1) !== '.') callback(null, 'commonjs ' + request)
      callback()
    },
    /^[a-z\-0-9]+$/, // regex形式
  ]
}

除了function形式,必須在array形式中,其餘形式,均可以提高,直接做爲externals屬性使用。好比string形式:git

externals: {
    './a': 'a',
    jquery: 'jQuery'
}

string

屬性名稱是jquery,表示應該排除import $ from 'jquery'中的 jquery模塊。爲了替換這個模塊,jquery的值將被用來檢索一個全局的$變量。換句話說,當設置爲一個字符串時,它將被視爲全局的,咱們須要在全局變量中,找到$,才能使程序正確運行。github

array

數組內的每個元素均可以是多種形式,包括object, regex, function, string四種:web

object

object形式,能夠直接做爲externals的值,這種形式是絕大部分項目中的配置形式。它裏面必定是鍵值對(key: value)的形式。正則表達式

function

function的使用,只能在array形式中做爲一個元素傳入。vue-cli

regex

正則匹配的形式,經過傳入正則表達式來實現匹配。這個能夠放在數組形式中,也能夠直接做爲externals的屬性。

實際案例

案例地址
以上說了如何配置的問題,在工做中,具體會是一個怎樣的表現呢。我挑選了一個經常使用的配置object形式,作了一些操做,對比下。

  • 第一種狀況,徹底不使用externals配置。
    第一種狀況的截圖
    first build
    first browser load

  • 第二種狀況,經過npm run build --report得出的報告,將一些不常修改的大包做爲外部擴展。
    這須要作兩步操做:第一步修改webpack.base.conf.js文件,第二步,將外部擴展的內容經過其餘方式加載到window環境,這裏,咱們經過<script>標籤,並使用cdn來完成。
    配置的文件:webpack.base.conf.js
externals: {
  vue : 'Vue',
  "echarts": 'echarts',
  "element-ui": 'ELEMENT'
}

在模板文件index.html中,添加<script>標籤

<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
<script src="https://unpkg.com/element-ui@2.4.11/lib/index.js"></script>
<script src="https://unpkg.com/echarts@4.1.0/dist/echarts.min.js"></script>

第二種狀況的截圖:
second build
second browser load

這兩種狀況,咱們主要從打包的時間,打包以後包的大小,實際瀏覽器中加載時長三個方面來作比較。

打包時間

打包時間,由原來的38s縮短至18s,大大減小了打包時間。

打包以後包的大小

主要看vendor包的大小,由原來的1.45M縮小至41.3k,縮小的內容,咱們使用cdn,使其存在於外部環境。
因爲externals屬性,是將依賴排除,本該將node_modules中依賴包打入到vendor bundle中,變成外部擴展。

瀏覽器加載

使用externals屬性,外部擴展,會增長請求數,由原來的6個請求變成了9個請求。因爲是使用CDN,非首次請求,會使用緩存中的數據,因此加載時間不受太大影響。
截圖所示時間不一樣,這個和多方面因素有關。你在相同的環境,每次刷新獲得的結果都不同。

須要注意

若是發現問題,能夠經過如下幾個方向查找:

  1. script的前後順序
  2. cdn的地址路徑是否正確
  3. 瀏覽器的window屬性值,是否和你的externals屬性的value相對應。能夠在console控制檯輸出看看。
  4. externals的打包支持什麼類型的,就和output.libraryTargetoutput.library 這兩個屬性有關係了。唐霜講的清楚點,能夠看看

參考

  1. 外部擴展Externals
  2. webpack externals詳解
  3. 本案例地址
相關文章
相關標籤/搜索