教你如何做 webpack 的性能优化

950 阅读3分钟

# tree-shaking / scope-hosting

  1. 通过import语法引入的模块资源,在生产环境下会自动去除掉没用的代码

  2. webpack会省略可以简化的代码,如下:

let a = 1;
let b = 2;
let c = 3let d = a + b+ c;

console.log(d); 

打包时会直接输出 console.log(6),删除之前的可简化的生明;

# noParse

如果确定第三方的包不依赖其他包即可排除,如下:

module.exorts = {
    module:{
        noParse:/jquery/ // 不去解析jquery中的依赖关系
    }
}

# webpack.IgnorePlugin

module.exports = {
    plugins:[
        // 这里以 moment 理时间的库为例
        // 忽略掉 moment 引入 ./locale 部分
        // 他会自动引入所有语言包,所以我们忽略掉他引入的
        // 手动引入需要的语言包即可
        new webpack.IgnorePlugin(/\.\/locale/, /moment/)
    ]    
}

# source-map

source-map是一种提供源代码到构建代码映射的技术,如果构建后代码出错了,通过映射可以追踪到源代码。

webpack.config.js 文件

module.exprots = {
    entry: {...},
    output: {...},
    devtool: 'source-map' // 开启 source-map | inline-source-map | eval-source-map ...
}

devtool 取值及其含义

  1. source-map:外部
    能提示错误代码准确信息 和 源代码的错位置
  2. inline-source-map:内联
    只生成一个内联 source-map
    能提示错误代码准确信息 和 源代码的错位置
  3. hidden-source-map:外部
    能提示代码错误原因,但没有错误位置
    不能追踪源代码错误,只能提示到构建后代码的错误位置
    只隐藏代码,会提示构建后的代码错误信息
  4. eval-source-map:内联
    每一个文件都生成对应的 source-map,都在 eval 里
    能提示错误代码准确信息 和 源代码的错位置
  5. nosources-soure-map:外部
    能提示错误代码准确信息,但没有源代码信息
    会隐藏全部信息
  6. cheap-source-map:外部
    能提示错误代码准确信息 和 源代码的错位置
    只能精确到行
  7. cheap-module-source-map:外部
    能提示错误代码准确信息 和 源代码的错位置

对比特点:

开发环境:
速度:eval>inline>cheap
友好:source-map>cheap-module>cheap
建议使用:eval-source-map

生产环境:
内联会让代码体积变的非常大,所以生产环境只用外部的方式
建议使用
cheap-module-source-map (注重调试)
hidden-source-map (注重隐藏代码)

# oneOf

多个loader只会匹配一个,所以使用oneOf时不能有两个配置处理同一种类型文件

module.exports = {
    module: {
        rules: [{
            oneOf: [{
                test: /\.css$/,
                use: [
                    // 创建style标签将样式放入
                    // 'style-loader',
                    MiniCssExtractPlugin.loader,
                    // 将css文件整合到js文件中
                    'css-loader',
                    {
                        // postcss 找到package.json中browserslist节点里面的配置
                        // 通过配置加载制定的css兼容性样式
                        loader: 'postcss-loader',
                        options: {
                            outputPaht: path.resolve(__dirname, 'cssdd'),
                            ident: 'postcss',
                            plugins: () => ([
                                require('postcss-preset-env')()
                            ])

                        }
                    }
                ]
            }]
        },
        
        ... 其他 loader
        ]
    },
}

# 多进程打包

安装插件

npm install tread-loader -D

配置 webpack.config.js 

module.ecports = {
    module: {
        rules: [{
            test: /\.css$/,
            use: [
                {
                    loader: 'tread-loader',
                    options:{
                        workers: 2 // 启动两个进程
                    }
                },
                'style-loader', // 创建style标签将样式放入
                'css-loader' // 将css文件整合到js文件中
            ]
        }]
    }    
}

也可以利用happypack来进行多进程打包

安装插件

npm install happypack -D
webpack.config.js 文件

const Happypack = require('happypack');

module.exports = {
    module:{
        rules:[
            {
                test: /\.css$/,
                // 这里用 Happypack/loader 处理 css 文件
                // ?id=css: 告诉 Happypack/loader处理的是 css 文件
                use: 'Happypack/loader?id=css'
            },
            {
                test: /\.js$/,
                // 这里用 Happypack/loader 处理 js 文件
                // ?id=js: 告诉 Happypack/loader处理的是 js 文件
                use: 'Happypack/loader?id=js'
            }
        ]
    },
    plugins:[
        new Happlypack({
            id: 'css', // 这里与 Happypack/loader?id=css 对应
            use: ['style-loader', 'css-loader']
        }),
        new Happlypack({
            id: 'js', // 这里与 Happypack/loader?id=js 对应
            use: [{
                loader: 'babel-loader',
                options: {
                   presets: ["@babel/preset-env"]
                }
            }]
        })
    ]
}

1649842614(1).png 如上图,告诉我启用了三个线程来进行打包

注意:开启多进程打包时大概为600ms,进程通信需要开销,所以适合工作耗时比较长的情况,否则效果不会很明显。

# optimization

公共代码抽离一般用于多入口模式下,如下:

webpack.config.js
module.exports = {
    mode: 'production',
    entry:{
        home: './src/home.js',
        index: './src/index.js'
    },
    optimization: {
        // 分割代码块
        splitChunks: {
            // 缓存组
            cacheGroups: {
                common: { // 公共模块
                    chunks: 'initial', // 入口时抽离
                    minSize: 0, // 只要大于 0 字节就抽离
                    minChunks: 2 // 只要用过2次以上就被抽离
                },
                vendor: { // 第三方模块
                    // 不加权重会在common就抽离完了,不会走vendor了
                    // 加了权重就会先执行,再去执行common模块
                    priority: 1, // 权重
                    test: /node_modules/,
                    chunks: 'initial',
                    minSize: 0,
                    minChunks: 2,

                }
            }
        }
    }
})