kevinxft / Notebook

个人笔记本
0 stars 0 forks source link

Webpack构建性能优化技巧 #26

Open kevinxft opened 2 years ago

kevinxft commented 2 years ago

使用最新版本的webpack

使用lazyCompilation

Webpack5.17.0后引入,按需编译。试想一个场景,你的项目中有一个入口(entry)文件及若干按路由划分的异步模块,Webpack 启动后会立即将这些入口与异步模块全部一次性构建好 —— 即使页面启动后实际上只是访问了其中一两个异步模块, 这些花在异步模块构建的时间着实是一种浪费!

约束 Loader 执行范围

配置 exclude: /node_modules/ 属性后,Webpack 在处理 node_modules 中的 js 文件时会直接跳过这个 rule 项,不会为这些文件执行 Loader 逻辑。

使用 noParse 跳过文件编译

有不少 NPM 库已经提前做好打包处理(文件合并、Polyfill、ESM 转 CJS 等),不需要二次编译就可以直接放在浏览器上运行,例如:

// webpack.config.js
module.exports = {
  //...
  module: {
    noParse: /lodash|react/,
  },
};

需要注意

开发模式禁用产物优化

Tree-Shaking、SplitChunks、Minimizer 等

module.exports = {
  // ...
  mode: "development",
  optimization: {
    removeAvailableModules: false,
    removeEmptyChunks: false,
    splitChunks: false,
    minimize: false,
    concatenateModules: false,
    usedExports: false,
  },
};

最小化 watch 监控范围

// webpack.config.js
module.exports = {
  //...
  watchOptions: {
    ignored: /node_modules/
  },
};

跳过TS类型检查

module.exports = {
  // ...
  module: {
    rules: [{
      test: /\.ts$/,
      use: [
        {
          loader: 'ts-loader',
          options: {
            // 设置为“仅编译”,关闭类型检查
            transpileOnly: true
          }
        }
      ],
    }],
  }
};

其他检查的方案

优化eslint性能

使用新版本组件 eslint-webpack-plugin 替代旧版 eslint-loader

const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
  // ...
  plugins: [new ESLintPlugin(options)],
  // ...
};

source-map

针对 source-map 功能,Webpack 提供了 devtool 选项,可以配置 eval、source-map、cheap-source-map 等值,不考虑其它因素的情况下,最佳实践:

设置 resolve 缩小搜索范围

Webpack 默认提供了一套同时兼容 CMD、AMD、ESM 等模块化方案的资源搜索规则 —— enhanced-resolve,它能将各种模块导入语句准确定位到模块对应的物理资源路径。例如:

resolve.extensions 配置:

默认值为 ['.js', '.json', '.wasm'] ,这意味着 Webpack 在针对不带后缀名的引入语句时,可能需要执行三次判断逻辑才能完成文件搜索,优化措施

resolve.modules 配置:

类似于 Node 模块搜索逻辑,当 Webpack 遇到 import 'lodash' 这样的 npm 包导入语句时,会先尝试在当前项目 node_modules 目录搜索资源,如果找不到,则按目录层级尝试逐级向上查找 node_modules 目录,如果依然找不到,则最终尝试在全局 node_modules 中搜索。

开发者可以通过修改 resolve.modules 配置项,主动关闭逐层搜索功能,例如:


// webpack.config.js
const path = require('path');

module.exports = { //... resolve: { modules: [path.resolve(__dirname, 'node_modules')], }, };



### resolve.mainFiles 配置:
与 resolve.extensions 类似,resolve.mainFiles 配置项用于定义文件夹默认文件名,例如对于 import './dir' 请求,假设 resolve.mainFiles = ['index', 'home'] ,Webpack 会按依次测试 ./dir/index 与 ./dir/home 文件是否存在。

**因此,实际项目中应控制 resolve.mainFiles 数组数量,减少匹配次数。**