webpack3.x升級4.x以後打包大小優化

前言

上一篇咱們講到,webpack3.x 升級 4.x 時遇到的問題、緣由和解決方案,今天講一下 webpack 4.x 的打包優化。node

打包分析

在優化以前咱們須要清楚項目的打包狀況,npm run buildwebpack 會將打包信息打印到終端,像這樣:webpack

可以看到有好幾個文件比較大,可是並不清楚具體包含哪些模塊,哪些模塊適合單獨提取,哪些模塊不適合提取,這個時候就須要用到打包分析的工具。nginx

如下摘自 webpack 文檔git

Bundle Anlysis - 打包分析github

一旦開始分割代碼,分析輸出以檢查模塊在哪裏結束將頗有用。official analyze tool 是一個很好的起點。 還有一些其餘社區支持的選項:web

  • webpack-chart: 用於 webpack 統計信息的交互式餅圖
  • webpack-visualizer: 可視化和分析您的包,以查看哪些模塊正在佔用空間,哪些多是重複的。
  • webpack-bundle-analyzer: 一個插件和 CLI 實用程序,將包內容表示爲方便的交互式可縮放樹形圖。
  • webpack bundle optimize helper: 此工具將分析您的捆綁包,併爲您提供切實可行的建議,以進行改進以減少捆綁包的大小。
  • bundle-stats: 生成捆綁報告(捆綁大小,資產,模塊),並比較不一樣版本之間的結果。

這裏咱們使用的是 webpack-bundle-analyzer,交互式可縮放樹形圖,便於咱們對打包狀況有一個比較直觀的瞭解。npm

安裝插件element-ui

npm i -D webpack-bundle-analyzer
複製代碼

引入插件瀏覽器

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

module.exports = {
  plugins: [new BundleAnalyzerPlugin()],
};
複製代碼

而後咱們再試着構建如下,看會怎麼樣緩存

npm run build
複製代碼

插件會自動在瀏覽器中打開連接:http://127.0.0.1:8888/ ,以交互式可縮放樹形圖展現了當前項目的打包狀況,能夠清楚的看到各個文件包含的模塊,針對性的處理:

代碼拆分

分析上面 👆 的樹形圖,概括瞭如下幾個能夠優化的點:

  • 將兩個入口公共的依賴,提取出來,如:Element-UI、Vue 全家桶、Lodash 等
  • 將僅某一個組件使用的依賴,提取出來,如:Swiper
  • 其餘的依賴,做爲單獨的一部分

optimization.splitChunks 屬性的默認值刪除,而後在 cacheGroups 中配置以下:

webpack.prod.js

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  optimization: {
    splitChunks: {
- chunks: "async",
- minSize: 30000,
- maxSize: 0,
- minChunks: 1,
- maxAsyncRequests: 5,
- maxInitialRequests: 3,
- automaticNameDelimiter: "~",
- automaticNameMaxLength: 30,
- name: true,
      cacheGroups: {
+ common: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-common',
+ minSize: 0,
+ minChunks: 2, // 最少被2個chunk引用
+ chunks: 'initial',
+ priority: 1 // 優先級,默認是0,能夠爲負數
+ },
+ other: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-other',
+ chunks: 'initial',
+ priority: -10
+ },
- defaultVendors: {
- test: /[\\/]node_modules[\\/]/,
- priority: -10
- },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // ..
});

// ..
module.exports = webpackConfig;
複製代碼

咱們再次構建,看看

npm run build
複製代碼

能夠看到拆分出了幾個包含 node_modules 的大文件:

  • vendors-common.***.js(兩個入口公共的依賴,被引用兩次以上)
  • vendors-other.***.js(其餘依賴,單個入口中使用,做爲全局使用的)
  • 5.***.js(swiper,單個組件中引入的依賴,webpack 會自動提取)
  • 其餘項目中使用到並自動拆分出的依賴,文件較小在上圖中沒體現出來

比較一下代碼拆分先後的兩個入口加載文件大小的不一樣:

  • 拆分前:app(2.5MB) qi(1.04MB)
  • 拆分後:app(1.88MB)qi(1.04MB)

入口 2 沒有變化,入口 1 的加載文件大小減小的 0.62MB,縮小將近 25%,固然這是沒有進行 gzip 壓縮的狀況,在 nginx 服務器上啓用 gzip 壓縮總體大小會更小,這裏就不展開了

若是你想單獨將某些依賴,單獨提取出來,能夠看看官方的這個例子,若是你的項目依賴較少,你徹底能夠按你喜歡的組合,手動拆分你的項目依賴到多個文件中。

緩存(快取)

當訪問網頁時,請求的文件會存儲在瀏覽器的緩存中,當下次再訪問時,若是知足HTTP 緩存機制,瀏覽器能夠從緩存中讀取文件,而沒必要從服務器讀取,甚至不用發起請求,能夠顯著提高加載速度並減小流量消耗。

可是若是項目從新構建,而用戶瀏覽器中的緩存還未過時,想要快速更新並繼續保留部分緩存,該怎麼作呢?

更多細節請看,HTTP 緩存-廢棄和更新緩存的響應

對此 webpack 打包須要優化一下幾點:

  • 控制輸出文件的名稱 - contentHash
  • 提取運行時代碼 - runtimeChunk
  • 指定模塊標識符 - moduleId

webpack.prod.js

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  output: {
    // ..
- filename: utils.assetsPath('js/[name].[chunkhash].js')
+ // 根據文件內容生成的 hash,文件內容改變時 hash 也隨之改變
+ filename: utils.assetsPath('js/[name].[contenthash].js')
  },
  optimization: {
+ // 運行時塊包含模塊間的引用關係,將它提取出來做爲單獨的文件,引用關係發生改變時,不會致使無關的文件內容發生改變
+ runtimeChunk: 'single',
+ // 由於使用 hashed,當本地新增或減小依賴時,不會影響其餘模塊的 ID(默認狀況下 ID 的值是根據解析順序遞增的)
+ moduleIds: 'hashed'
    // ...
  }
});

// ..
module.exports = webpackConfig;
複製代碼

更多細節請看,webpack 文檔-緩存(快取)

總結

代碼拆分的過程當中,有嘗試過基於現有配置的基礎上,單獨拆分出指定依賴(如 Element-UI,由於不常改動且文件較大),可是會破壞現有的拆分,屢次嘗試以後無果,最接近的時候是這樣的,入口 1 會將其包含在文件中,可是入口 2 不會,當前項目有兩個入口:

採用以下配置:

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  optimization: {
    splitChunks: {
      cacheGroups: {
        common: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
          name: 'vendors-common',
          minSize: 0,
          minChunks: 2, // 最少被2個chunk引用
          chunks: 'initial',
          priority: 1 // 優先級,默認是0,能夠爲負數
        },
        other: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
          name: 'vendors-other',
          chunks: 'initial',
          priority: -10
        },
+ 'element-ui': {
+ test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
+ name: 'vendor-element-ui',
+ chunks: 'initial',
+ priority: -15
+ },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // ..
});

// ..
module.exports = webpackConfig;
複製代碼

後續有處理方案後會更新,到這裏打包大小優化就告一段了,下一篇會講講如何對打包速度進行優化。

相關文章
相關標籤/搜索