zoukankan      html  css  js  c++  java
  • WebPack系列--开启HappyPack之后,再将项目打包速度缩短5秒

    效果展示

    打包时间:缩短了 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'
  • 相关阅读:
    ubuntu中KDE与GNOME安装切换
    前向算法的数学意义上的实现
    题目1023:EXCEL排序
    题目1022:游船出租
    php notice提示
    Php显示中文时乱码
    题目1021:统计字符
    题目1020:最小长方形
    题目1013:开门人和关门人
    题目1032:ZOJ
  • 原文地址:https://www.cnblogs.com/wangpenghui522/p/14716903.html
Copyright © 2011-2022 走看看