webpack从入门到原理(高级六)——优化代码运行性能(Code Split 上)

276 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

Code Split(代码分割)

在我们打包代码时会将所有 js 文件打包到一个文件中,体积太大了。假如我们只要渲染首页,就应该只加载首页的 js 文件,其他文件不应该加载,所以我们可以将打包生成的文件进行代码分割,生成多个 js 文件,渲染哪个页面就只加载哪个 js 文件,这样加载的资源就少,速度就更快。

使用

代码分割(Code Split)主要做了两件事:

  1. 分割文件:将打包生成的文件进行分割,生成多个 js 文件。
  2. 按需加载:需要哪个文件就加载哪个文件。

代码的分割的实现方式有多种,创建一个新的文件用来截图发文,看的更加明显(手动狗头!)文件目录及配置如下:

├── public
├── src
|   ├── app.js
|   └── main.js
├── package.json
└── webpack.config.js
// webpack.config.js

const path = require("path");

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  // entry: './src/main.js',
  entry: {
    app: './src/main.js',
    main: './src/app.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: "[name].js",
    // clear: true
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public/index.html")
    }),
  ],
  mode: "production",
}

多入口

通过 entry 设置多个参数来实现多入口打包,将代码分割成多个文件。为了防止文件名冲突导致覆盖或报错,output设置输出的文件名filename: "[name].js"

[name]是webpack命名规则,使用chunk的name作为输出的文件名(打包的资源就是chunk,输出出去叫bundle)。完成以上配置npx webpack进行打包,在dist目录就可以看到两个js文件。

image.png

提取重复代码

如果多入口文件中都引用了同一份代码正常打包如下图,会看到reduce函数被分别在app.js和main.js中引入。当项目变得越来越大,被复用的代码越来越多,被复用的次数越来越大会使得打包欧虎的代码体积变得很大!为减小代码体积我们可以提取重复的代码,只打包生成一个 js 文件,其他文件引用它就好! image.png

配置如下:

// webpack.config.js
  optimization: {
    // 代码分割配置
    splitChunks: {
      chunks: "all", // 对所有模块都进行分割
      // 以下是默认值
      // minSize: 20000, // 分割代码最小的大小
      // minRemainingSize: 0, // 类似于minSize,最后确保提取的文件大小不能为0
      // minChunks: 1, // 至少被引用的次数,满足条件才会代码分割
      // maxAsyncRequests: 30, // 按需加载时并行加载的文件的最大数量
      // maxInitialRequests: 30, // 入口js文件最大并行请求数量
      // enforceSizeThreshold: 50000, // 超过50kb一定会单独打包(此时会忽略minRemainingSize、maxAsyncRequests、maxInitialRequests)
      // cacheGroups: { // 组,哪些模块要打包到一个组
      //   defaultVendors: { // 组名
      //     test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
      //     priority: -10, // 权重(越大越高)
      //     reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
      //   },
      //   default: { // 其他没有写的配置会使用上面的默认值
      //     minChunks: 2, // 这里的minChunks权重更大
      //     priority: -20,
      //     reuseExistingChunk: true,
      //   },
      // },
      // 修改配置
      cacheGroups: {
        // 组,哪些模块要打包到一个组
        // defaultVendors: { // 组名
        //   test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
        //   priority: -10, // 权重(越大越高)
        //   reuseExistingChunk: true, // 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
        // },
        default: {
          // 其他没有写的配置会使用上面的默认值
          minSize: 0, // 我们定义的文件体积太小了,所以要改打包的最小文件体积
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    }
  }

重新运行打包就会发现reduce函数被分开成了单独的文件,在app.js和main.js中分别引用。

image.png

小结

今天是持续更文的第十二天了,继续加油!