使用esbuild提升webpack5的性能

项目冷启动

一般情况下,我们对一个jsx?文件的解析loader是这么配置:

{
    test: /\.[jt]sx?$/,
    use: [
        {
            loader: 'babel-loader',
            options: {
                presets: ['@babel/preset-react', '@babel/preset-typescript']
            }
        }
    ]
}
复制代码

现有项目在做了dll优化的情况下,开发冷启动时间在2s+甚至3s+这个时间:

webpack 5.65.0 compiled successfully in 2419 ms
复制代码

热更新时间基本在100ms左右:

./src/app.jsx 192 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 174 ms
./src/app.jsx 192 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 156 ms
./src/app.jsx 192 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 62 ms
./src/app.jsx 192 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 90 ms
复制代码

使用esbuild-loader替换一下:

{
    test: /\.[jt]sx?$/,
    use: [
        {
            loader: 'esbuild-loader',
            options: {
                loader: 'tsx'
            }
        }
    ]
},
复制代码

冷启动时间有了比较显著的提升,可以控制在2s以内:

webpack 5.65.0 compiled successfully in 1672 ms
复制代码

热更新时间基本在100ms以内:

./src/app.jsx 168 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 137 ms # 啪~!
./src/app.jsx 234 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 59 ms
./src/app.jsx 234 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 58 ms
./src/app.jsx 192 bytes [built] [code generated]
webpack 5.65.0 compiled successfully in 92 ms
...
复制代码

……反正看着是能快点……那webpack配置还简单了呢,不用额外装preset了啊。

所以

主要是冷启动时间提升。但我这个项目是个demo而已,不知道在大项目里是不是能有更好的表现。

编译压缩

以前常用的uglifyjs-webpack-pluginwebpack5项目里是没办法安装的,报依赖错误,要求降级到webpack^4

而且只要配置上--mode=productionwebpack自然会压缩代码,所以这个uglify-js貌似并没有那么重要了。

根据以前的经验,使用uglify-js会比webpack的压缩输出还要再小一点,然后找到了一个新的压缩插件:terser-webpack-plugin,url: terser-webpack-plugin

在这个插件中,内置了四个压缩引擎,分别是:terser uglify-js swc esbuild;其中后面三个,还需要额外安装依赖unlify-js @swc/coreesbuild。找了一个现成的项目,分别进行了压缩测试,结果还是非常值得玩味的。

先上webpack的配置文件,这是上面那个项目的dll的输出配置:

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const { DllPlugin } = require('webpack')
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
    entry: {
        react: ['react', 'react-dom'],
        vue: ['vue'],
    },
    output: {
        path: path.resolve(__dirname, 'dll'),
        filename: '[name].dll.js',
        library: '[name]_dll',
    },
    mode: 'production',
    plugins: [
        new CleanWebpackPlugin(),
        new DllPlugin({
            path: path.resolve(__dirname, './dll/manifest_[name].json'),
            name: '[name]_dll',
            context: __dirname,
        }),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                test: /\.js(\?.*)?$/i,
                // minify: TerserPlugin.terserMinify,
                // minify: TerserPlugin.uglifyJsMinify,
                // minify: TerserPlugin.swcMinify,
                // minify: TerserPlugin.esbuildMinify,
                terserOptions: {},
            }),
        ],
    },
}
复制代码

使用webpack原生压缩

这种情况,是在配置中把optimization节点完全删掉了,主要结果为:

asset react.dll.js 127 KiB [emitted] [minimized] (name: react) 1 related asset
asset vue.dll.js 64.2 KiB [emitted] [minimized] (name: vue) 1 related asset
webpack 5.65.0 compiled successfully in 5264 ms
复制代码

使用 terserMinify

asset react.dll.js 127 KiB [emitted] [minimized] (name: react) 1 related asset
asset vue.dll.js 64.5 KiB [emitted] [minimized] (name: vue) 1 related asset
webpack 5.65.0 compiled successfully in 3895 ms
复制代码

使用 uglifyJsMinify

asset react.dll.js 126 KiB [emitted] [minimized] (name: react) 1 related asset
asset vue.dll.js 63.5 KiB [emitted] [minimized] (name: vue) 1 related asset
webpack 5.65.0 compiled successfully in 5377 ms
复制代码

使用 swcMinify

asset react.dll.js 127 KiB [emitted] [minimized] (name: react)
asset vue.dll.js 64.1 KiB [emitted] [minimized] (name: vue)
webpack 5.65.0 compiled successfully in 1030 ms
复制代码

使用 esbuildMinify

asset react.dll.js 129 KiB [emitted] [minimized] (name: react)
asset vue.dll.js 68.2 KiB [emitted] [minimized] (name: vue)
webpack 5.65.0 compiled successfully in 753 ms
复制代码

数据汇总

引擎 react体积(KiB) vue体积(KiB) 耗时(ms)
原生 127 64.2 5264
terser 127 64.5 3895
uglify-js 126 63.5 5377
swc 127 64.1 1030
esbuild 129 68.2 753

可以看到,uglify-jsesbuild分别是体积最优解和时间最优解。

PS: swc和esbuild分别是基于rust和golang的js代码转译工具。

以上。

猜你喜欢

转载自juejin.im/post/7049638461229236238