demo09 使用 SplitChunksPlugin 分離第三方依賴包以及異步包

1.爲何要代碼分離

在單頁面或多頁面應用中,經過代碼分離的方式,可以優化性能。javascript

好比把異步加載的代碼分離成一個單獨的chunk,等到須要調用的時候再按需加載(好比click時),這樣能夠減小首屏的代碼體積,從而提升首屏的加載速度。html

另外,在咱們的項目中,可能會用到不少的第三方庫(好比 lodash 、rxjs 等),而每每這些第三方依賴庫的代碼通常不多變化,所以,很適合把第三方依賴庫單獨分離成一個包,而且包名包含 hash( webpack 能夠輕鬆作到),這樣的好處在於,能夠配合瀏覽器http的緩存機制 (好比 max-age ),實現對相關資源包的長緩存,從而優化性能。java

通常須要代碼分割的場景有:node

  • 分離業務代碼和第三方依賴
  • 分離首次加載和異步加載的代碼
  • 分離業務代碼和業務的公用代碼

2.安裝相關依賴

經過 html-webpack-plugin 自動生成 index.htmlwebpack

npm install -D html-webpack-plugin
npm install -D webpack // html-webpack-plugin 依賴於 webpack
npm install --save axios lodash
複製代碼

3.目錄結構

// `--` 表明目錄, `-` 表明文件
  --demo09
    --src
      -app.js
      -async-module1.js
      -async-module2.js
      -module.js
    -index.html
    -webpack.config.js
複製代碼

src/async-module1.jsios

export const data = 'this is async module1';
複製代碼

src/async-module2.jsgit

export const data = 'this is async module2';
複製代碼

src/module.jsgithub

export const sayHello1 = () => {
  console.log('Hi I want to say hello1');
}

export const sayHello2 = () => {
  console.log('Hi I want to say hello2');
}

export const sayHello3 = () => {
  console.log('Hi I want to say hello3');
}
複製代碼

src/app.jsweb

import { sayHello1, sayHello2, sayHello3 } from './module';

sayHello1();
sayHello2();
sayHello3();


// 異步加載 async-module1
setTimeout(() => {
  require.ensure(
    [],
    function () {
      const asyncModule = require("./async-module1");
      console.log(asyncModule.data);
    },
    "module1"
  );
}, 3000);

// 異步加載 async-module2
setTimeout(() => {
  require.ensure(
    [],
    function () {
      const asyncModule2 = require("./async-module2");
      console.log(asyncModule2.data);
    },
    "module2"
  );
}, 3000);


// 引用第三方庫
// https://github.com/lodash/lodash
import * as _ from "lodash";
// https://github.com/axios/axios
import * as axios from "axios";

console.log(_);
console.log(axios);
複製代碼

3.配置打包第三方庫的規則

使用 webpack4 的 splitChunks 能夠很容易的作到。npm

關於splitChunks 的各個參數的用法,能夠看個人這篇文章 demo08 關於SplitChunksPlugin

splitChunks: {
      cacheGroups: {
        vendors: {
          chunks: "all", // 使用 all 模式
          test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 下的模塊
          name: "vendors", // 包命名,最終的命名要結合 output 的 chunkFilename
          minChunks: 1,
          minSize: 30000,
          priority: 10 // 設置優先級
        }
      }
    }
複製代碼

4.配置打包異步加載包的規則

打包異步加載包

splitChunks: {
      cacheGroups: {
        async: {
          chunks: "async",
          minChunks: 1, // 代碼塊至少被引用的次數
          maxInitialRequests: 3, // 設置最大的請求數
          minSize: 0, // 設置每一個 chunk 最小的大小 (默認30000),這裏設置爲 0,以方便測試
          automaticNameDelimiter: '~',
          priority: 9
        },
      }
    }
複製代碼

5.完整的 webpack 配置文件

const path = require("path");

module.exports = {
  mode: 'development', // 使用development模式,方便看到各個包名中的 [name],以區分各個包,在production模式下,[name]會被轉化爲0 1 2...
  entry: {
    app: "./src/app.js",
  },

  output: {
    publicPath: __dirname + "/dist/", // 打包後資源文件的引用會基於此路徑
    path: path.resolve(__dirname, "dist"), // 打包後的輸出目錄
    filename: "[name].[chunkhash].bundle.js", // 每一個包包含 chunkhash
    chunkFilename: "[id].[chunkhash].chunk.js"
  },
  optimization: {
    runtimeChunk: "single",
    splitChunks: {
      cacheGroups: {
        async: {
          chunks: "async",
          minChunks: 1, // 代碼塊至少被引用的次數
          maxInitialRequests: 3, // 設置最大的請求數
          minSize: 0, // 設置每一個 chunk 最小的大小 (默認30000),這裏設置爲 0,以方便測試
          automaticNameDelimiter: '~',
          priority: 9
        },
        vendors: {
          chunks: "all", // 使用 all 模式
          test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 下的模塊
          name: "vendors", // 包命名,最終的命名要結合 output 的 chunkFilename
          minChunks: 1,
          minSize: 30000,
          priority: 10 // 設置優先級
        }
      }
    }
  }
};

複製代碼

5.執行打包命令

(默認你已經安裝了全局 webpack 以及 webpack-cli )

webpack
複製代碼

打包成功後,結果輸出在 demo09 的 dist 目錄下

(注意這裏設置 "mode""development" )

app.226a343cb53e0a689358.chunk.js (app主模塊)
async~module1.87d116fd41640c30a6b2.chunk.js (async-module1模塊)
async~module2.65866f4d15253512c981.chunk (async-module2模塊)
runtime.4e6de616bd3030f8bff8.bundle.js (webpack運行時模塊)
vendors.a83c085b3a7ac03b1b47.chunk.js (第三方依賴模塊)

複製代碼

6.修改程序代碼,驗證打包結果

能夠經過修改 app.js 等代碼,再次運行 webpack 命令,你會發現,第三方依賴模塊的包名沒有被改變: vendors.a83c085b3a7ac03b1b47.chunk.js

在瀏覽器運行 dist/index.html,打開控制檯能夠觀察異步加載模塊的效果。

(備註:runtime.xxxxxxxx.bundle.js模塊包含了對異步加載模塊的引用邏輯,此外,異步加載引用的相對路徑受 output -> publicPath 配置的影響)

7.源碼地址

demo 代碼地址: github.com/SimpleCodeC…

倉庫代碼地址(及目錄): github.com/SimpleCodeC…

相關文章
相關標籤/搜索