記一次 webpack 打包體積優化

手頭作的項目開發得差很少了,而打包配置是一開始粗略配置的,不大的項目打包出來得6MB+,因此如今必須進行優化。javascript

打包結果分析

執行命令 webpack --profile --json > stats.json ,能夠將打包過程的詳細信息以 json 格式記錄到文件中。依據該文件,webpack-bundle-analyzerWebpack Chart 等分析工具會以可視化的形式展現打包過程和結果。css

webpack-bundle-analyzer

若是不想用這些額外工具,經過命令 webpack --display-modules --sort-modules-by size ,webpack 會在日誌中按大小排序顯示全部模塊。java

我在項目中,將第三方庫基本都集中打包到一個 chunk (vendors),業務邏輯單獨一個 chunk (app)。打包整體積的大頭來自 vendors,其中antd佔據大頭(3MB+)、moment佔據約500KB、提取的 css 約300KB、react-dom也是500KB+,出乎意料的是 lodash 也是500KB+。react

逐個擊破

設置環境變量 NODE_ENVproduction

很多庫會按開發環境(development)和生產環境(production)提供不一樣的文件,主要是爲了開發模式下的調試,也會所以有文件體積上的差異。用於生產環境的打包,設置其爲production後,這些庫會提供最小體積的文件。webpack

plugins: [
    // ...
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    // ...
]

css-loader

css-loader 在 webpack 默認不開啓壓縮,須要設置 css-loader?minimizegit

module: {
    // ...
    {
      test: /\.css$/,
      use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: 'css-loader?minimize'
      })
    }
    // ...
}

大頭——antd (ant design)

由於並無使用 antd 的全部組件,因此按需加載是必需的。根據其文檔(按需加載 - Ant Design),須要安裝 bable 插件 babel-plugin-import ,並在 babel 配置中添加:es6

{
    // ...
    "plugins": [
        ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }],
        // ...
    ]
}

在我配置過程當中,libraryDirectory 配置的不一樣也會有較大影響,但按目前文檔來看貌似沒有影響,待我確認後再作記錄。github

=== 2018-02-23 更新 ===web

看來bable-plugin-import這幾天有更新,如今配置項 libraryDirectory 的默認值時 lib,即便用經過 require (commonjs) 引用模塊的文件。而先前我在配置的時候並無默認值,若是沒有顯示配置 libraryDirectory,打包結果會出現重複的內容。json

採用了 es6 module 的項目建議配置 libraryDirectoryes,即便用經過 import (es6 module) 引用模塊的文件。這種狀況打包後的體積要更小一些。

=== end ===

這裏還有很重要一點,babel-plugin-import 要求 antd 不能被提取爲公共模塊 vendors,不然就沒法實現按需加載。尚不清楚是 babel 插件的緣由,仍是這個插件單獨的緣由。

moment

moment 庫的體積開銷主要是 i18n 文件,配置 webpack 將用不到 i18n 文件不打包便可。

plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn/),
]

看上去很輕量的 lodash

lodash看上去就是一些工具函數,應該是很輕量的,然而一次所有加載下來要達到500KB,所以也須要按需加載。它的按需加載還比較麻煩。

lodash爲每一個方法單獨提供了庫,但這種方式在實際使用中並不靈活,因此這種最「乾淨」的方法不建議使用。

像 antd 同樣,lodash 也有 babel 插件用於按需加載——babel-plugin-lodash

{
    // ...
    "plugins": [
        "lodash",
        // ...
    ]
}

一樣,lodash 就不能提取到公共模塊了。

最後

打包結果的體積開銷主要就是以上幾項。通過優化後,體積降低至1.5MB之內,仍是很客觀的。不過 antd 依然佔據大頭,後續會考慮把 antd 替換掉,畢竟用到的組件很少。

相關文章
相關標籤/搜索