webpack 优化

vue.config中configureWebpack 与 chainWebpack区别

configureWebpack 和chainWebpack的作用相同,唯一的区别就是它们修改webpack配置的方式不同:
① configureWebpack:通过操作对象的形式,来修改默认的webpack配置,该对象将会被 webpack-merge 合并入最终的 webpack 配置;
② chainWebpack:通过链式编程的形式,来修改默认的webpack配置。

configureWebpack: {
    resolve: {
        alias: {
            '@': resolve('src'),
        },
    },
    //警告 webpack 的性能提示
    performance: {
        hints: 'warning',
        //入口起点的最大体积 整数类型(以字节为单位)
        maxEntrypointSize: 50000000,
        //生成文件的最大体积 整数类型(以字节为单位 300k)
        // maxAssetSize: 50000000,
        maxAssetSize: 3000,
        // maxAssetSize: 30000000,
        //只给出 js 文件的性能提示
        assetFilter: function (assetFilename) {
            return assetFilename.endsWith('.js');
        },
    },
}

chainWebpack(config) {
    config.plugin('preload').tap(() => [
        {
            rel: 'preload',
            // to ignore runtime.js
            // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
            fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
            include: 'initial',
        },
    ]);
    config.plugins.delete('prefetch');
    config.module.rule('svg').exclude.add(resolve('src/icons')).end();
    config.module
        .rule('icons')
        .test(/\.svg$/)
        .include.add(resolve('src/icons'))
        .end()
        .use('svg-sprite-loader')
        .loader('svg-sprite-loader')
        .options({
            symbolId: 'icon-[name]',
        })
        .end();
}
复制代码

vue.config中configureWebpack 与 chainWebpack区别
vue.config.js中configureWebpack和chainWebpack区别

optimize-css-assets-webpack-plugin 插件

optimize-css-assets-webpack-plugin 是 webpack 用来压缩 css 文件的插件,这个插件会在 webpack 构建过程中搜索 CSS ,并优化 CSS。

主要作用:
① 优化 css,去掉重复的 css;
② 压缩 css 文件。

安装

 npm install optimize-css-assets-webpack-plugin --save-dev
复制代码

使用

// vue.config.js:
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    configureWebpack: {
        plugins: [
            new OptimizeCSSAssetsPlugin({
                assetNameRegExp: /\.css$/g,
                cssProcessor: require('cssnano'),
                // cssProcessorOptions: cssnanoOptions,
                cssProcessorPluginOptions: {
                    preset: [
                        'default',
                        {
                            discardComments: {
                                removeAll: true,
                            },
                        },
                    ],
                },
            }),
        ],
    }
}
复制代码

拓展
webpack4使用optimize-css-assets-webpack-plugin压缩单独的css文件
webpack 如何压缩文件
webpack之插件optimize css assets webpack plugin
optimize-css-assets-webpack-plugin

terser-webpack-plugin 插件

terser-webpack-plugin 内部封装了 terser 库,用于处理 js 的压缩和混淆,通过 webpack plugin 的方式对代码进行处理。

主要作用:
① 压缩 js 文件;
② 通过配置选项去除 console.log 语句及 debugger 等。

terser-webpack-plugin 替代 uglifyjs-webpack-plugin
① uglifyjs-webpack-plugin 不支持 es6,且uglify-es不再更新;
② terser-webpack-plugin 支持 es6。

安装

npm install terser-webpack-plugin --save-dev
复制代码

webpack v5 开箱即带有最新版本的 terser-webpack-plugin。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装 terser-webpack-plugin。如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本。

使用

// vue.config.js:
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    chainWebpack(config) {
        config.when(process.env.NODE_ENV !== 'dev', (config) => {
            config.optimization.minimize = true;
            config.optimization.minimizer([
                new TerserPlugin({
                    extractComments: false,
                    terserOptions: {
                        compress: {
                            arguments: true,
                            dead_code: true,
                        },
                        toplevel: true,
                        keep_classnames: true,
                        keep_fnames: true,
                    },
                }),
            ]);
        }
    }
}
复制代码

拓展
源码细读-深入了解terser-webpack-plugin的实现
terser-webpack-plugin 中文文档
terser-webpack-plugin替代uglifyjs-webpack-plugin
webpack的压缩插件uglifyjs-webpack-plugin变为teaser-webpack-plugin
terser-webpack-plugin

SplitChunks 插件

简单来说 SplitChunks 是 webpack 中一个提取或分离代码的插件。

主要作用:
① 提取公共代码,防止代码被重复打包;
② 拆分过大的 js 文件,合并零散的 js 文件。

SplitChunks插件默认配置选项

// vue.config.js:
module.exports = {
    configureWebpack: config => {
        return {
            optimization: {
                splitChunks: {
                    chunks: 'async', // 决定要提取哪些模块,默认是 async:只提取异步加载的模块出来打包到一个文件中。
                                     // (异步加载的模块:通过 import(‘xxx’) 或 require([‘xxx’],() =>{}) 加载的模块)
                    
                    minSize: 30000, // 规定被提取的模块在压缩前的大小最小值,单位为字节;默认为30000,只有超过了
                                    // 30000字节才会被提取。
                    maxSize: 0, // 把提取出来的模块打包生成的文件大小不能超过maxSize值;如果超过了,要对其进行
                                // 分割并打包生成新的文件。单位为字节,默认为0,表示不限制大小。
                    minChunks: 1, // 表示要被提取的模块最小被引用次数,引用次数超过或等于minChunks值,才能被提取。
                    maxAsyncRequests: 6, // 最大的按需(异步)加载次数,默认为 6;
                    maxInitialRequests: 4, // 打包后的入口文件加载时,还能同时加载js文件的数量(包括入口文件),
                                           // 默认为 4。
                    automaticNameDelimiter: '~', // 打包生成的js文件名的分割符,默认为:~
                    cacheGroups: { // 核心重点,配置提取模块的方案,里面每一项代表一个提取模块的方案。
                        vendors: {
                            name: `chunk-vendors`,
                            test: /[\\/]node_modules[\\/]/,
                            priority: -10,
                            chunks: 'initial'
                        },
                        common: {
                            name: `chunk-common`,
                            minChunks: 2,
                            priority: -20,
                            chunks: 'initial',
                            reuseExistingChunk: true
                        }
                    }
                }
            }
        }
    }
};
复制代码

在项目中的配置

// vue.config.js:
module.exports = {
    chainWebpack(config) {
        config.when(process.env.NODE_ENV !== 'dev', (config) => {
            config.optimization.splitChunks({
                chunks: 'all',
                minSize: 200000,
                maxSize: 500000,
                cacheGroups: {
                    libs: {
                        name: 'chunk-libs',
                        test: /[\\/]node_modules[\\/]/,
                        priority: 10,
                        chunks: 'initial', // only package third parties that are initially dependent
                    },
                    elementUI: {
                        name: 'chunk-elementUI', // split elementUI into a single package
                        priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                        test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
                    },
                    commons: {
                        name: 'chunk-commons',
                        test: resolve('src/components'), // can customize your rules
                        minChunks: 2, //  minimum common number
                        priority: 1,
                        // priority: 5,
                        // reuseExistingChunk: true,
                    },
                },
            });
            // https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
            config.optimization.runtimeChunk('single');
        }
    }
}
复制代码

拓展
Webpack中 SplitChunks 插件用法详解
如何使用 splitChunks 精细控制代码分割
如何使用 splitChunks 精细控制代码分割
splitChunks探索(二)
常见的plugin以及作用的总结(webpack部分)

DefinePlugin 插件

DefinePlugin 允许创建一个在编译时可以配置的全局常量。

用法
每个传进 DefinePlugin 的键值都是一个标志符或者多个用 . 连接起来的标志符:
① 如果这个值是一个字符串,它会被当作一个代码片段来使用;
② 如果这个值不是字符串,它会被转化为字符串(包括函数);
③ 如果这个值是一个对象,它所有的 key 会被同样的方式定义;
④ 如果在一个 key 前面加了typeof,它会被定义为 typeof 调用。

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true),
    VERSION: JSON.stringify('5fa3b9'),
    BROWSER_SUPPORTS_HTML5: true,
    TWO: '1+1',
    'typeof window': JSON.stringify('object'),
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
})
复制代码

拓展
DefinePlugin插件
实用webpack插件之DefinePlugin

vue.config.js 的完整配置(超详细)!

分类:
前端
标签: