WebPack系列--開啟HappyPack之後,再將專案打包速度縮短5秒

孤舟蓑翁發表於2021-04-29

效果展示

打包時間:縮短了 26.296s-20.586s=5.71s

先看兩組測試資料,第一組是沒有使用DllPlugin的打包測試資料,測量三次取平均值是26.296s
(25.72+25.56+27.61)/3≈26.296s

 

第二組是使用了DllPlugin的打包測試資料,測量三次取平均值是20.586s
(20.62+21.31+19.83)/3≈20.586s 

 

 

打包體積:減少了 8.72M-4.8M=3.92M

沒用動態庫之前是8.72M

用了動態庫之後是1.8M+2958K≈4.8M
 

減少的原因是避免了在業務程式碼中重複引入第三方工具包。

為什麼會快?

我們的專案程式碼,可以分為第三方工具包和業務程式碼,第三方工具包一般比較成熟,用webpack打包編譯過,無需每次專案構建時都再次打包。可以把這部分程式碼從剝離出去,通過外鏈script標籤引入,每次構建,只打包業務程式碼。所以能縮短整體打包時間。

如何實現

要想實現這樣的效果,你需要在現有專案的基礎上,做如下配置:

第一步,安裝依賴

yarn add -D assets-webpack-plugin clean-webpack-plugin webpack-bundle-analyzer

第二步,編寫生成dll庫的webpack配置檔案

const path = require("path");
const webpack = require("webpack");
const WebpackBar = require("webpackbar");
const AssetsPlugin = require("assets-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // 打包前清空dll資料夾
// 讀取package.json裡的執行依賴包
const pkg = require("../package.json");
let dependencies = Object.keys(pkg.dependencies) || [];
dependencies = dependencies.length > 0 ? dependencies : [];

console.log("dll", dependencies);
module.exports = {
  entry: {
    dll: dependencies,
  },
  mode: "production",
  output: {
    path: path.resolve(__dirname, "../dll"),
    filename: "[name]_[hash:6].js",
    library: "[name]_[hash:6]", // 暴露給外部使用
    // libraryTarget 指定如何暴露內容,預設時就是 var
  },
  plugins: [
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, "../dll/*.*")],
    }),
    new webpack.DllPlugin({
      path: path.resolve(__dirname, "../dll", "[name]-manifest.json"),
      name: "[name]_[hash:6]", // name和library一致
    }),
    // 把帶hash的dll.js插入到index.html中,和html-webpack-plugin外掛配合使用,告訴html-webpack-plugin插入的dll.js檔名稱
    new AssetsPlugin({
      filename: "dll-config.json",
      path: "./dll/",
    }),
    // webpackbar可以在打包時實時顯示打包進度
    new WebpackBar(),
  ],
};

在package.json中,新增生成dll庫的指令:

"scripts": {
    "build:dll": "webpack --config webpack/dll.js",
},

生成動態庫

第三步:在index.html靜態模板中,載入動態庫

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8" />
    <meta name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" />
    <meta name="theme-color" content="#000000" />
    <meta name="keywords" content="" />
    <meta name="description" content="" />
    <title></title>
</head>

<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script src="//at.alicdn.com/t/font_1343302_nuzqn1v7zae.js"></script>
    <!-- 插入動態庫 -->
    <% if (htmlWebpackPlugin.options.dllJsName) { %>
    <script src="<%= htmlWebpackPlugin.options.dllJsName %>"></script>
    <% } %>
    <!-- iconfont svg地址 -->
</body>

</html>

第四步:在webpack.base.js中,配置動態庫載入和庫對映檔案路徑

// 是否為本地開發環境
const isDev = process.env.NODE_ENV === "development";
// 根目錄
const basename = process.env.BASE_NAME ? `${process.env.BASE_NAME}/` : "/";
const publicPath = isDev ? "/" : `/${basename}`;
// 這裡的路徑與webpack資料夾下的dll.js配置檔案中的路徑保持一致
const dllConfig = require("../dll/dll-config.json");
const manifest = require("../dll/dll-manifest.json");

module.exports = {
  plugins: [
    new HtmlPlugin({
      template: path.resolve(rootPath, "./index.html"),
      favicon: path.resolve(rootPath, "./favicon.ico"),
      // index.html中載入dll的script標籤的src地址
      dllJsName: isDev ? `${publicPath}dll/${dllConfig.dll.js}` : "",
      // html壓縮
      minify: {
        collapseWhitespace: true,
        preserveLineBreaks: true,
      },
    }),
    // 載入生成的dll庫
    isDev
      ? new webpack.DllReferencePlugin({
          manifest,
        })
      : () => {},
  ],
};

打包構建時,檢視打包內容和大小的配置

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; // 包分析工具
module.module.exports = () => {
  return merge(webpackBaseConfig, {
    plugins: [
      process.argv.indexOf("--pa") !== -1
        ? new BundleAnalyzerPlugin()
        : () => {},
    ],
  });
};

沒使用動態庫之前入口檔案大小是1.43M

 使用了動態庫之後入口檔案大小是648K

 問題與解答

首頁載入速度對比:使用動態庫之後,首頁載入速度變慢了3.08 - 2.51 =0.57s

使用動態庫之前,首頁載入時間是2.51s

使用動態庫之後,首頁載入時間是3.08s

使用了動態庫之後,如何不拖慢首頁的載入速度?

首頁載入速度變慢了一些,是由於打包的第三方庫,不再是按需載入,而是在首頁一次性載入,要改善這種情況,有兩條思路:

1.縮小打包體積,只把每個頁面都會用到的三方工具打包進動態庫, 還有對打包之後的內容進行gzip壓縮。

2.只在開發環境使用動態庫功能。

Dll和External的區別

對於如下的引用, Dll直接將庫的應用指向xxx庫,不會再把xxx/lib/module打包,而External則認為 import Foo from 'xxx' 和 import AA from 'xxx/lib/module',是引用了兩個不同的庫,因此xxx在專案中已經存在的情況下, xxx/lib/module還會被打包進專案。用import Foo from 'xxx/lib/module'這樣的方式引用模組,使用動態庫是比較吃虧的。

import Foo from 'xxx/lib/module'

 

相關文章