webpack-代碼拆分模式詳解

看了官方文檔以後發現splitChunks.chunks能夠接收initial、async、all,很困惑這三種分割代碼模式的區別,如今咱們引入例子來探索一下:node

下面有兩個腳本文件a.js、b.js,兩個文件有一些相同的引入,包括動態加載,咱們使用Webpack Bundle Analyzer Plugin插件來分析模塊是如何進行拆分的。react

一、chunks:'async'優化動態加載模塊

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  entry: {
    a: './code_split_mode/a.js',
    b: './code_split_mode/b.js'
  },
  output: {
    path: path.resolve(__dirname, 'build'), // 打包文件的輸出目錄
    filename: '[name].bundle.js', // 代碼打包後的文件名
    publicPath: __dirname + '/build/', // 引用的路徑或者 CDN 地址
    chunkFilename: '[name].js' // 代碼拆分後的文件名
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  // 拆分代碼配置項
  optimization: {
    splitChunks: {
      cacheGroups: {
        node_vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'async',
          priority: 1
        }
      }
    }
  },
  plugins: [
    new CleanWebpackPlugin(), // 會刪除上次構建的文件,而後從新構建
    new BundleAnalyzerPlugin()
  ]
}

執行效果:
1.pngjquery

2.png!webpack

async 模式下的輸出git

  • a,b 中均同步引入的 jquery 被打包進了各自的 bundle 中沒有拆分出來共用,由於這種模式下只會優化動態加載的代碼。
  • react 打了兩份github

    • 一份在a 本身的 bundle 中,由於它同步引入了 react,而咱們只優化動態加載的代碼,因此這裏的 react 不會被優化拆分出去。
    • 一份在單獨的文件中,它是從 b 裏面拆出來的,由於 b 中動態加載了 react
  • lodash 由於在 a,b 中都是動態加載,造成了單獨的 chunka, b 共用。

二、chunks:'initial'優化同步加載模塊

webpack.config.js配置中將chunks: 'async'改爲'initial'
3.png
initial模式下的輸出web

initial即原始的拆分,原則就是有共用的狀況即發生拆分。動態引入的代碼不受影響,它是不管如何都會走拆分邏輯的(畢竟你要動態引入嘛,不拆分紅單獨的文件怎麼動態引入?!)。而對於同步引入的代碼,若是有多處都在使用,則拆分出來共用。安全

  • jquery 在這種模式下發生了變化。造成了單獨的 chunka,b 共用。
  • react 沒有變,由於它在 a,b 中引用的方式不一樣,因此不會被當成同一個模塊拆分出來共用,而是走各自的打包邏輯。在 a 中同步引用,被打入了 abundle。在 b 中動態引入因此拆分紅了單獨的文件供 b 使用。
  • lodash 沒變,造成單獨一份二者共用。

三、chunks:'all'優化同步和動態加載模塊

5.png
從上面initial模式下咱們彷佛看出了問題,即 在 a 中同步引入在 b 中動態引入的 react,它其實能夠被抽成文件供二者共用的,只是由於引入方式不一樣而沒有這樣作。babel

因此all這種模式下,就會智能地進行判斷以解決這個問題。此時不關心引入的模塊是動態方式仍是同步方式,只要能正確判斷這段代碼確實能夠安全地進行拆分共用,那就幹吧。async

須要注意的是這裏須要設置minSize以使react可以正確被拆分,由於它小於 30k,在同步方式下,默認不會被拆分出來(聯想文章開頭提到的那些條件)。

cacheGroups: {
 vendor: {
    chunks: "all",
    test: /[\\/]node_modules[\\/]/,
    minSize: 0,
 }
}

四、結論

看起來彷佛all是最好的模式,由於它最大限度地生成了複用的代碼,Webpack 默認就走這個模式打包不就得了。

參考連接:
https://github.com/wayou/wayou.github.io/issues/40
https://medium.com/dailyjs/webpack-4-splitchunks-plugin-d9fbbe091fd0

相關文章
相關標籤/搜索