Skip to content

提升打包构建速度

HotModuleReplacement

HotModuleReplacement(HMR/热模块替换):在程序运行中,替换、添加或删除模块,而无需重新加载整个页面

当开发时修改其中一个模块代码,Webpack 默认会将所有模块全部重新打包编译,速度很慢。为了更快的打包速度,需要做到修改某个模块代码,就只有这个模块代码需要重新打包编译,其他模块不变。

使用

  1. 基本配置
    css 样式经过 style-loader 处理,已经具备 HMR 功能,js 还需额外配置

    js
    module.exports = {
      // 其他省略
      devServer: {
        host: "localhost", // 启动服务器域名
        port: "3000", // 启动服务器端口号
        open: true, // 是否自动打开浏览器
        hot: true, // 开启HMR功能(只能用于开发环境,生产环境不需要)
      },
    };
  2. js 配置

    js
    // main.js
    import count from "./js/count";
    
    const result = count(2, 1);
    console.log(result);
    
    // 判断是否支持HMR功能
    if (module.hot) {
      module.hot.accept("./js/count.js", function (count) {
        const result = count(2, 1);
        console.log(result);
      });
    }

实际开发我们会借助其他 loader 来解决:vue-loader, react-hot-loader

OneOf

只要匹配上一个 loader, 剩下的就都不匹配

打包时每个文件都会经过所有 loader 处理,每个 loader 条件都会匹配一遍,影响打包速度

OneOf 使用

js
// webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  // ...
  module: {
    rules: [
      {
        oneOf: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
          },
          {
            test: /\.less$/,
            use: ["style-loader", "css-loader", "less-loader"],
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: "babel-loader",
          },
          // 其余loader略
        ],
      },
    ],
  },
  // ...
};

Include/Exclude

指定要处理的或者不需要处理的文件,提升构建速度

Include/Exclude 使用

js
// webpack.config.js
const path = require("path");
const EslintWebpackPlugin = requrie("eslint-webpack-plugin");

module.exports = {
  //...
  module: {
    ruels: [
      {
        test: /\.js$/,
        // exclude:/node_modules/,// 排除依赖包
        include: path.resolve(__dirname, "./src"), //只加载src目录下的文件
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new EsLlintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 默认值
    }),
  ],
  //...
};

Cache

对 Eslint 检查 和 Babel 编译结果进行缓存

每次打包 js 文件都要经过 Eslint 检查 和 Babel 编译,速度比较慢。可以缓存之前的 Eslint 检查 和 Babel 编译结果,提升第二次打包速度

Cache 使用

js
// webpack.config.js
const path = require("path");
const EslintWebpackPlugin = requrie("eslint-webpack-plugin");

module.exports = {
  //...
  module: {
    ruels: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, "./src"),
        loader: "babel-loader",
        options: {
          cacheDirectory: true, //开启babel编译缓存
          cacheCompression: false, //缓存文件压缩
        },
      },
    ],
  },
  plugins: [
    new EsLlintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules", // 默认值
      cache: true, //开启缓存
      // 缓存目录
      cacheLocation: path.resolve(__dirname, "./node_modules/.cache/.eslintcache"),
    }),
  ],
  //...
};

Thead

多进程打包:开启电脑的多个进程同时干一件事,速度更快。

注意

请仅在特别耗时的操作中使用,因为每个进程启动就有大约为 600ms 左右开销。

当项目越来越庞大时,打包速度会越来越慢。想要继续提升打包速度,其实就是要提升 js 的打包速度,因为其他文件都比较少。而对 js 文件处理主要是 eslint 、babel、Terser 三个工具,所以要提升它们的运行速度。我们可以开启多进程同时处理 js 文件,这样速度会比之前的单进程打包更快

Thead 使用

  1. 获取电脑启动进程数(CPU)

    js
    // nodejs核心模块
    const os = require("os");
    // CPU核数
    const threads = os.cpus().length;
  2. 安装依赖

    shell
    npm i thread-loader -D
  3. 应用

js
// webpack.config.js
const path = reuqire("path");
const os = requrie("os");
const TerserPlugin = require("terser-webpack-plugin");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");

// 获取CPU核数
const threads = os.cpus().length;

module.exports = {
  //...
  module: {
    rules: [
      // 其余略
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "thread-loader", //开启多进程
            options: {
              workers: threads, //数量
            },
          },
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true, // 开启babel编译缓存
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new EslintWebpackPlugin({
      context: path.resolve(__dirname, "./src"),
      threads, // 开启多进程
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: threads, //开启多进程
      }),
    ],
  },
  //...
};