likes
comments
collection
share

记一次Webpack构建性能优化

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

背景

项目技术栈:Vue2.6、Vuex、TS、ClassComponent

整个项目在开发环境启动极其慢,电脑风扇狂转,今天终于受不了了,决定针对性的优化一下

项目当前的构建速度

记一次Webpack构建性能优化

记一次Webpack构建性能优化

问题:

  1. 打包构建出来的资源相当大
  2. 从开始构建到完成一共用时3分多钟,这已经不能用慢来形容了,那是相当慢!!!

优化策略

合理配置路径解析,优化模块查找的优先级

以下代码默认会最后查找.ts文件,而我们的项目是使用ts书写的,这样的模块查找性能很差

resolve: {
    extensions: ['.js', '.vue', '.json', '.scss', '.css', '.less', '.ts']
}

改良后:

resolve: {
    extensions: ['.ts', '.js', '.vue', '.json', '.scss', '.css', '.less']
}

优化loader查找文件的范围

合理配置inlcude与exclude属性,满足include条件的模块才会使用对应的loader进行处理,从而减少打包时间,通常情况下node_modules目录下的包都是经过处理的,没必要再次处理。(这里并不是说exclude匹配的文件就不打包了,一样会打包,只是少了loader处理

{
    include: path.resolve(__dirname, 'src'),
}
{
    exclude: path.resolve(__dirname, 'node_modules')
}

使用HappyPack开启多线程加速编译

{
    test: /\.js$/,
    include: path.resolve(__dirname, 'src'),
    use: 'happypack/loader?id=babel' // id为唯一值,标识在plugin中需要匹配到的规则
}

new HappyPack({
    id: 'babel',
    threads: 4,
    loaders: ['cache-loader', 'babel-loader']
})

使用cache-loader和happyPackMode

使用thread-loader配合happyPackMode,加速ts文件编译与缓存

在一些性能开销较大的 loader 之前添加 cache-loader,以便将结果缓存到磁盘里。

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

{
    test: /\.tsx?$/,
    use: [
        {
            loader: 'cache-loader'
        },
        {
            loader: 'thread-loader',
            options: {
                workers: require('os').cpus().length - 1,
            },
        },
        {
            loader: 'ts-loader',
            options: {
                appendTsSuffixTo: [/\.vue$/],
                happyPackMode: true
            }
        }
    ],
    include: path.resolve(__dirname, '../src')
}

经过上述处理后,目前文件打包的时长如下: 记一次Webpack构建性能优化

虽然还是很慢,但是已经将时间缩短了2/3,收益非常可观

使用DllPlugin

大部分情况下,很多第三方库的代码并不会发生变更(除非是版本升级),这时就可以用到dll:把复用性较高的第三方模块打包到动态链接库中,在不升级这些库的情况下,动态库不需要重新打包,每次构建只重新打包业务代码

配置webpack.dll.config.js

// 定义常用对象
const path = require('path');
const webpack = require('webpack');

// dll文件存放的目录
const dllPath = '../dist/dll';

module.exports = {
    // 需要提取的库文件
    entry: {
        vue: ['vue', 'vue-router', 'vuex', 'axios'],
    },
    output: {
        path: path.join(__dirname, dllPath),
        filename: '[name].dll.js',
        // vendor.dll.js中暴露出的全局变量名
        // 保持与 webpack.DllPlugin 中名称一致
        library: '[name]_dll_[hash]'
    },
    plugins: [
        // 定义插件
        new webpack.DllPlugin({
            path: path.join(__dirname, dllPath, '[name].manifest.json'),
            // 保持与 output.library 中名称一致
            name: '[name]_dll_[hash]'
        })
    ]
};

在npm script中添加命令

    "dll": "webpack --config build/webpack.dll.config.js"

执行

npm run dll

在webpack.dev.config.js中配置

plugins: [
    // 这个插件帮助我们在html中引入dll文件
    new AddAssetHtmlWebpackPlugin({
        filepath: path.resolve(__dirname, '../dist/dll/vue.dll.js') // 对应的 dll 文件路径
    }),
    new webpack.DllReferencePlugin({
        manifest: require('../dist/dll/vue.manifest.json')
    })
]

再次打包

记一次Webpack构建性能优化 对比之前的 44.1mb 少了 600kb 大小,这个就是打出来的库的大小,当然项目里还有很多其他文件占了很大的空间,还需要进一步优化。

经过所有处理后,最终的开发环境构建时长:

记一次Webpack构建性能优化

功夫不负有心人,折腾了一晚上,构建速度提升了 6 倍,算是不小的收获吧!

纸上得来终觉浅 绝知此事要躬行