likes
comments
collection
share

webpack5性能优化篇

作者站长头像
站长
· 阅读数 70

优化构建速度

优化babel-loader

为了让我们写的ES6+语法的 JS 代码能够正常运行在低版本的浏览器中,通常需要将其转换为ES5语法,这时我们需要用到babel-loader。但直接使用babel-loader可能会导致webpack构建速度慢,所以我们从以下两点进行优化:

  • 转译尽可能少的文件
  • 开启转译缓存

配置如下:

module: {
  rules: [
    {
      test: /\.js$/,
      // 通过 cacheDirectory 开启缓存,
      // 缓存目录为 node_modules/.cache/babel-loader
      use: ["babel-loader?cacheDirectory"],
      // 排除范围,include 和 exclude 两者选一个即可
      include: srcPath,
      exclude: /node_modules/,
    },
  ],
},

IgnorePlugin

例如我们在使用moment依赖时,默认会引入所有语言的 JS 代码,如果直接使用,会导致打包后的代码体积比较大。这时我们可以使用IgnorePlugin来忽略我们不需要引入的代码,使用方式如下:

plugins: [
  // 忽略 moment 下的 /locale 目录
  new webpack.IgnorePlugin({
    resourceRegExp: /^\.\/locale$/,
    contextRegExp: /moment$/,
  }),
],

这时候moment默认使用语言英语,如果要使用别的语言,可以手动引入需要使用的语言包。

import moment from "moment";
import "moment/locale/zh-cn";
moment.locale("zh-cn");

noParse

react.min.jsjQuery等已经进行模块化的文件,我们无需再次构建,可对其进行忽略处理,处理方式如下:

module: {
  // min.js 一般已经模块化,无需我们再次处理
  noParse: [/react\.min\.js/],
},

IgnorePlugin 对比 noParse IgnorePlugin 直接不引入,代码中没有。noParse 引入,但不打包。

happypack

JS 是单线程的,使用happypack开启多进程打包,提高构建速度。

const HappyPack = require("happypack");

module: {
  rules: [
    {
      test: /\.js$/,
      // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例
      use: ["happypack/loader?id=babel"],
      // 排除范围,include 和 exclude 两者选一个即可
      include: srcPath,
      // exclude: /node_modules/,
    },
  ],
},

plugins: [
  // happy开启多进程打包
  new HappyPack({
    // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件
    id: "babel",
    // 如何处理 .js 文件,用法和 Loader 配置中一样
    loaders: ["babel-loader?cacheDirectory"],
  }),
],

terser-webpack-plugin

该插件可以压缩 JS 代码体积,开启多进程压缩可提高构建速度,配置如下:

const TerserJSPlugin = require("terser-webpack-plugin");

optimization: {
  // 压缩 js
  minimizer: [
    new TerserJSPlugin({
      // 开启多进程压缩
      parallel: true,
    }),
  ],
}

关于开启多进程 项目较大,打包较慢,开启多进程能提高速度 项目较小,打包很快,开启多进程会降低速度(进程开销) 按需使用

热更新

自动刷新热更新的区别:

  • 自动刷新:整个网页全部刷新,速度较慢
  • 自动刷新:整个网页全部刷新,状态会丢失
  • 热更新:新代码生效,网页不刷新,状态不丢失
devServer: {
  // 开启热更新
  hot: true,
},

如需改动样式文件,热更新即可生效。 如需改动 js 文件,则需要进行如下改写:

// 开启热更新之后的代码逻辑
if (module.hot) {
  // math.js中代码发生变化页面不会整体刷新
  module.hot.accept("./math.js", () => {
    // 热更新的回调函数
    const sumRes = sum(10, 20);
    console.log("热更新", sumRes);
  });
}

优化代码体积

小图片 base64 编码

module: {
  rules: [
    // 图片 - 考虑 base64 编码的情况
    {
      test: /\.(png|jpg|jpeg|gif)$/,
      use: {
        loader: "url-loader",
        options: {
          // 小于 5kb 的图片用 base64 格式产出
          // 否则,依然延用 file-loader 的形式,产出 url 格式
          limit: 5 * 1024,
          // 打包到 img 目录下
          outputPath: "/img/",
          // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
          // publicPath: 'http://cdn.abc.com'
        },
      },
    },
  ],
},

bundle 加 hash

output: {
  filename: "[name].[contenthash:8].js", // name 即多入口时 entry 的 key
},

提取公共代码

optimization: {
  // 分割代码块
  splitChunks: {
    chunks: "all",
    /**
     * initial 入口chunk,对于异步导入的文件不处理
     * async 异步chunk,只对异步导入的文件处理
     * all 全部chunk
     */
    // 缓存分组
    cacheGroups: {
      // 第三方模块
      vendor: {
        name: "vendor", // chunk 名称
        priority: 1, // 权限更高,优先抽离,重要!!!
        test: /node_modules/,
        minSize: 0, // 大小限制
        minChunks: 1, // 最少复用过几次
      },

      // 公共的模块
      common: {
        name: "common", // chunk 名称
        priority: 0, // 优先级
        minSize: 0, // 公共模块的大小限制
        minChunks: 2, // 公共模块最少复用过几次
      },
    },
  },
},

IgnorePlugin

使用方式在优化构建速度中已经说明了,使用IgnorePlugin也可以减少构建后代码体积

使用 CDN 加速

所有的静态文件都会加上 CDN 的前缀,打包后需要将静态文件放到 CDN 上

output: {
  publicPath: "http://cdn.abc.com", // 修改所有静态文件 url 的前缀(如 cdn 域名)
},

使用 production

  • 能够自动开启代码压缩
  • Vue React 等会自动删掉调试代码(如开发环境的 warning)
  • 启动 Tree-Shaking(ES6 Module 才能让 tree-shaking 生效)

Scope Hosting

未开启时,一个 js 文件会生成一个函数,开启后会将多个 js 文件相关代码合并到一个函数中。

开启后优点:

  • 代码体积更小
  • 创建函数作用域更少
  • 代码可读性更好
resolve: {
  // 针对 npm 中的第三方模块优先采用 jsnext:main 中指向的 ES6 模块化语法的文件
  mainFields: ["jsnext:main", "browser", "main"],
},

plugins: [
  // 开启 scope hosting
  new webpack.optimize.ModuleConcatenationPlugin(),
];
转载自:https://juejin.cn/post/7230823928758796325
评论
请登录