利用DllPlugin分割你的第三方庫

前言

小站利用React全家桶開發,在上線以後,發現第三方bundle(2Mb左右)下載用了近20秒。 最初發現的問題是nginx壓縮配置gzip沒有添加application/javascript這個MIME類型,可是仍然花了近5秒。javascript

解決過程

初始

起初,個人配置文件(webpack.dll.js)內容以下:html

這個配置文件獨立於你應用的webpack.dev.jswebpack.prod.js等配置文件java

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

const vendors = [
  'react',
  'antd',
  'lodash'
  ... // 其餘第三方庫
]

const config = {
  entry: { vendors },
  output: {
    filename: '[name].js',
    library: '[name]_library', // 與 DllPlugin 的 name 保持一致
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.resolve('dll', '[name].manifest.json'),
      name: '[name]_library', // 這裏的命名要遵循變量命名規範,它是最終的包變量名
    })
  ]
}
複製代碼

:只附關鍵代碼,項目根目錄爲project,更多配置參數請參見官網react

運行這個配置文件以後,這樣會在/project/dll目錄中生成兩個文件:webpack

  • vendors.js
  • vendors.manifest.json

咱們須要在inedx.html頁面(也在項目根目錄下)中將vendors.js引入nginx

<script src="/dll/vendors.js"></script>
複製代碼

在你的webpack.dev.jswebpack.prod.js配置的plugins屬性中添加對這些包的引用:web

const manifestFile = path.relove('dll, 'vendors.manifest.json'); // manifest.json 文件地址
const config = {
  plugins: [
    new webpack.DllReferencePlugin({
      manifest: manifestFile
    })
  ]
}
複製代碼

改進1

考慮到瀏覽器併發請求數默認爲6個,我開始拆分第三方包(webpack.dll.js):json

const Libs = {
  ui: [
    'antd'
  ],
  base: [
    'lodash'
  ],
  frame: [
    'react'
  ]
}
const config = {
  entry: { ...Libs },
  ... // 其餘配置,同上
}
複製代碼

運行以後,會生成三個.js.manifest.json文件,一樣你須要將.js引用加入到你的index.js頁面:瀏覽器

<script src="/dll/ui.js"></script>
<script src="/dll/base.js"></script>
<script src="/dll/frame.js"></script>
複製代碼

而在你的webpack.dev.jswebpack.prod.js中,你須要屢次調用DllReferencePlugin插件:bash

const manifestFileUi = path.relove('dll', 'ui.manifest.json');
const manifestFileBase = path.relove('dll', 'base.manifest.json');
const manifestFileFrame = path.relove('dll', 'frame.manifest.json');

const config = {
  ... // 其餘配置
  plugins: [
    new webpack.DllReferencePlugin({
      manifest: manifestFileUi
    }),
    new webpack.DllReferencePlugin({
      manifest: manifestFileBase
    }),
    new webpack.DllReferencePlugin({
      manifest: manifestFileFrame
    })
  ... // 其它 plugin
  ]
}
複製代碼

建議根據 Libs 變量寫個函數循環生成

改進2

我發現antdlodash打包出來仍然很大,那麼就按需加載(webpack.dll.js):

const Libs = {
  ui: [
    'antd/es/button',
    'antd/es/input',
    ... // 其餘你項目中用到的 UI 組件
  ],
  base: [
    'lodash/fp/get',
    'lodash/fp/set',
    ... // 其餘你項目中用到的函數
  ]
  ... // frame
}
複製代碼

最終的加載時間爲1秒左右。

問題

lodash按需加載的話,它使用方法改變以下:

// 以前
import _ from 'lodash';
_.get(...);

// 以後
import get from 'lodash/fp/get; get(...) 複製代碼

可是第二種方法老是返回undefined,因此我改回了第一種使用方法,可是仍然是按需打包,問題有待查找。

結束

謝謝閱讀,若有謬誤,懇請斧正。

相關文章
相關標籤/搜索