# 优化

# 压缩css、js

  • optimize-css-assets-webpack-plugin + uglify-webpack-plugin
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    mode: 'production',
    optimization: {
        minimizer: [
            new OptimizeCssAssetsWebpackPlugin(),
            new UglifyjsWebpackPlugin()
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
  • optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
    mode: 'production',
    plugins: [
        new OptimizeCssAssetsWebpackPlugin()
    ]
}
1
2
3
4
5
6
7

# externals

告诉 webpack,这是外部引入的,不需要再次打包。

# exclude、include

# IgnorePlugin

// js
import 'moment/locale/zh-cn' // 手动引入语言包

// webpack.config.js
module.exports = {
    plugins: [
        new webpack.IgnorePlugin(/\.\/locale/, /moment/) // 忽略moment内部所有引入的 ./locale
    ]
}
1
2
3
4
5
6
7
8
9

# DllPlugin

DLLPluginDLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。

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

module.exports = {
    entry: {
        react: ['react', 'react-dom']
    },
    mode: 'production',
    output: {
        filename: '[name].dll.js',
        path: path.resolve(__dirname, 'dist', 'dll'),
        library: '[name]_dll' //暴露给外部使用
        //libraryTarget:'var' | 'commonjs' | 'amd' 指定如何暴露内容,缺省时就是 var
    },
    plugins: [
        new webpack.DllPlugin({
            //name和library一致
            name: '[name]_dll', 
            path: path.resolve(__dirname, 'dist', 'dll', 'manifest.json') //manifest.json的生成路径
        })
    ]
}


//webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
    //...
    plugins: [
        new webpack.DllReferencePlugin({
            manifest: path.resolve(__dirname, 'dist', 'dll', 'manifest.json')
        }),
        new CleanWebpackPlugin({
            cleanOnceBeforeBuildPatterns: ['**/*', '!dll', '!dll/**'] //不删除dll目录
        })
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# happypack

const Happypack = reuqire('happypack')
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'Happypack/loader?id=js',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: 'Happypack/loader?id=css'
            }
        ]
    },
    plugins: [
        new Happypack({
            id: 'js',
            use: [
                {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            '@babel/preset-env'
                        ],
                        plugins: [
                            '@babel/plugin-transform-runtime',
                            {
                                corejs: 3
                            }
                        ]
                    }
                }
            ]
        }),
        new Happypack({
            id: 'css',
            use: ['style-loader', 'css-loader']
        })
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# webpack自带优化

# tree-shaking

如果使用ES6的 import 语法,那么在生产环境下,会自动移除未引用代码。

# scope hosting:作用域提升

生产环境下,webpack 会自动省略可以简化的代码

const a = 1
const b = 2
let c = a + b
// 打包后的代码为 var c = 3
1
2
3
4

# 抽取公共代码

module.exports = {
    optimization: {
        splitChunks: {
            cacheGroups: {
                common: {
                    chunks: 'initial',
                    minSize: 0,
                    minChunks: 2
                },
                // 第三方依赖
                vendor: {
                    priority: 1, // 优先级
                    test: /node_modules/,
                    chunks: 'initial',
                    minSize: 0,
                    minChunks: 2 // 最少引入次数
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 懒加载

import() 语法需要 @babel/plugin-syntax-dynamic-import 插件的支持,使用 @babel/preset-env 则不需要再次安装和配置

webpack 遇到 import() 语法,会新生成一个 Chunk 文件,在执行到 import() 时再去加载这个文件。

# 热更新

const webpack = require('webpack')
module.exports = {
    devServer: {
        hot: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
}
1
2
3
4
5
6
7
8
9