Samgao0312 / Blog

MIT License
1 stars 1 forks source link

【积点成势】重学Webpack (6) —— 如何提高Webpack的构建速度 #153

Open Samgao0312 opened 2 years ago

Samgao0312 commented 2 years ago

随着功能和业务代码越来越多,相应的 Webpack 的构建时间也会越来越久,构建的效率也会越来越低,那如何提升Webpack 构建速度,是前端工程化的重要一环。常用的手段有如下一些:

1、优化 Loader 配置

在使用 Loader 时,可以通过配置include、exclude、test属性来匹配文件,通过include、exclude来规定匹配应用的loader。例如,下面是ES6 项目中配置 babel-loader 的例子:

module.exports = {
  module: {
    rules: [
      {
        // 如果项目源码中只有 js 文件就不要写成 /\.jsx?$/,提升正则表达式性能
        test: /\.js$/,
        // babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启
        use: ['babel-loader?cacheDirectory'],
        // 只对项目根目录下的 src 目录中的文件采用 babel-loader
        include: path.resolve(__dirname, 'src'),
      },
    ]
  },
};

2、合理resolve.extensions

在开发中,我们会有各种各样的模块依赖,这些模块可能来自第三方库,也可能是自己编写的, resolve可以帮助Webpack从每个 require/import 语句中,找到需要引入到合适的模块代码。

具体来说,通过resolve.extensions是解析到文件时自动添加拓展名,默认情况如下:

module.exports = {
    ...
    extensions:[".warm",".mjs",".js",".json"]
}

当我们引入文件的时候,若没有文件后缀名,则会根据数组内的值依次查找。所以,处理配置的时候,不要随便把所有后缀都写在里面。

3、优化 resolve.modules

resolve.modules 用于配置 webpack 去哪些目录下寻找第三方模块,默认值为['node_modules']。所以,在项目构建时,可以通过指明存放第三方模块的绝对路径来减少寻找的时间。

module.exports = {
  resolve: {
    modules: [path.resolve(__dirname, 'node_modules')]   // __dirname 表示当前工作目录
  },
};

4、优化 resolve.alias

alias 给一些常用的路径起一个别名,特别当我们的项目目录结构比较深的时候,一个文件的路径可能是 ./../../ 的形式,通过配置alias以减少查找过程。

module.exports = {
    ...
    resolve:{
        alias:{
            "@":path.resolve(__dirname,'./src')
        }
    }
}

5、使用 DLL Plugin 插件

DLL全称是动态链接库, 是为软件在 winodw 种实现共享函数库的一种实现方式,而 Webpack 也内置了 DLL 的功能,为的就是可以共享,不经常改变的代码,抽成一个共享的库。使用步骤分成两部分:

5.1 打包一个 DLL 库

Webpack内置了一个DllPlugin可以帮助我们打包一个DLL的库文件,如下。

module.exports = {
    ...
    plugins:[
        new webpack.DllPlugin({
            name:'dll_[name]',
            path:path.resolve(__dirname,"./dll/[name].mainfest.json")
        })
    ]
}

5.2 引入 DLL 库

首先,使用 webpack 自带的 DllReferencePlugin 插件对 mainfest.json 映射文件进行分析,获取要使用的DLL库。然后,再通过AddAssetHtmlPlugin插件,将我们打包的DLL库引入到Html模块中。

module.exports = {
    ...
    new webpack.DllReferencePlugin({
        context:path.resolve(__dirname,"./dll/dll_react.js"),
        mainfest:path.resolve(__dirname,"./dll/react.mainfest.json")
    }),
    new AddAssetHtmlPlugin({
        outputPath:"./auto",
        filepath:path.resolve(__dirname,"./dll/dll_react.js")
    })
}

6、合理使用使用 cache-loader

在一些性能开销较大的 loader 之前添加 cache-loader,以将结果缓存到磁盘里,显著提升二次构建速度。比如:

module.exports = {
    module: {
        rules: [
            {
                test: /\.ext$/,
                use: ['cache-loader', ...loaders],
                include: path.resolve('src'),
            },
        ],
    },
};

需要说明的是,保存和读取这些缓存文件会有一些时间开销,所以请只对性能开销较大的 loader 使用此 loader。

7、开启多线程

开启多进程并行运行可以提高构建速度,配置如下:

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true,          //开启多线程
      }),
    ],
  },
};