如何在 WEBPACK + VUEJS 中减小包大小

Posted

技术标签:

【中文标题】如何在 WEBPACK + VUEJS 中减小包大小【英文标题】:How to reduce bundle size in WEBPACK + VUEJS 【发布时间】:2019-09-27 07:36:51 【问题描述】:

我遵循了很多关于如何减小包大小的教程,但没有对包大小产生任何影响,我不知道为什么。

每次我向 webpack 添加一些新代码时,我的包大小都和以前一样。

(我的应用是用vue cli 3 pwa插件、webpack...等构建的)

如果我运行npm run build,我会得到这个输出:

webpack.config.js:

    const path = require('path');
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    const OfflinePlugin = require('offline-plugin');
    const webpack = require('webpack');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const WebpackChunkHash = require('webpack-chunk-hash');
    const CompressionPlugin = require('compression-webpack-plugin');

    if (process.env.NODE_ENV === 'production') 
        module.exports.plugins = (module.exports.plugins || []).concat([
            // or use push because it's faster
            new webpack.DefinePlugin(
                'process.env': 
                    'process.env.NODE_ENV': '"production"',
                ,
            ),
            new webpack.optimize.UglifyJsPlugin(
                mangle: true,
                compress: 
                    warnings: false, // Suppress uglification warnings
                    pure_getters: true,
                    unsafe: true,
                    unsafe_comps: true,
                    screw_ie8: true,
                ,
                output: 
                    comments: false,
                ,
                exclude: [/\.min\.js$/gi], // skip pre-minified libs
            ),
            new webpack.HashedModuleIdsPlugin(),
            new WebpackChunkHash(),
            new CompressionPlugin(
                asset: '[path].gz[query]',
                algorithm: 'gzip',
                test: /\.js$|\.css$|\.html$/,
                threshold: 10240,
                minRatio: 0,
            ),
        ]);
    

    const config = (module.exports = 
        mode: 'production',
        devtool: '', // Removed dev-tools mapping
        entry: [
            './src/app.js',
            
                vendor: ['offline-plugin/runtime'],
            ,
        ],
        output: 
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'build/client'),
            publicPath: 'build/client',
        ,
        resolve: 
            extensions: ['.js', '.vue', '.json'],
            alias: 
                vue$: 'vue/dist/vue.esm.js', // Use the full build
            ,
        ,
        module: 
            rules: [
                
                    test: /\.vue$/,
                    use: 'vue-loader',
                ,
                
                    test: /\.css$/,
                    use: [
                        
                            loader: MiniCssExtractPlugin.loader,
                            options: 
                                // you can specify a publicPath here
                                // by default it use publicPath in webpackOptions.output
                                publicPath: '../',
                            ,
                        ,
                        'vue-loader',
                    ],
                ,
            ],
        ,
        optimization: 
            runtimeChunk: 
                name: 'runtime',
            ,
            splitChunks: 
                chunks: 'all',
                maxInitialRequests: Infinity,
                minSize: 0,
                cacheGroups: 
                    vendor: 
                        test: /[\\/]node_modules[\\/]/,
                        name(module) 
                            // get the name. E.g. node_modules/packageName/not/this/part.js
                            // or node_modules/packageName
                            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

                            // npm package names are URL-safe, but some servers don't like @ symbols
                            return `npm.$packageName.replace('@', '')`;
                        ,
                    ,
                ,
            ,
        ,
        plugins: [
            new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(en|zh-tw)$/),
            new webpack.optimize.ModuleConcatenationPlugin(),
            new BundleAnalyzerPlugin(),
            new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
            new OfflinePlugin(
                AppCache: false,
                // important for working 200 respons => index.html ./
                externals: ['./'],
                ServiceWorker: 
                    events: true,
                ,
            ),
            new webpack.optimize.CommonsChunkPlugin(
                name: 'vendor',
                minChunks: function(module) 
                    return module.context && module.context.indexOf('node_modules') !== -1;
                ,
            ),
            new MiniCssExtractPlugin(
                // Options similar to the same options in webpackOptions.output
                // both options are optional
                filename: '[name].css',
                chunkFilename: '[id].css',
            ),
        ],
        );

        if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 
          'test') 
         
          config.plugins = [...config.plugins, new BundleAnalyzerPlugin()];
         

【问题讨论】:

【参考方案1】:

来自 webpack 团队的肖恩。有几件事我会推荐。

    升级到webpack 4(我可以告诉你在 3,因为你正在使用 CommonsChunkPlugin())。 webpack 4 附带了大量的大小和构建时间性能。新的 vue-cli 默认使用它。

    代码拆分您的路线和组件。代码拆分让您可以延迟加载 javascript,直到以后需要它为止。这种技术减少了将要创建的初始包中的代码量。这是我对此发表的演讲:Code Splitting Patterns with Vue with Sean Thomas Larkin。

    与使用代码拆分相比,尝试使用 webpack 配置永远不会获得真正的加载时性能!!!

【讨论】:

哦,我以为我使用的是 webpack 4 :_。但是感谢您的帮助,我会看一下视频。谢谢! 我们在 webpack 4 中弃用了 CommonsChunkPlugin :-) 所以这对我来说是个信号。

以上是关于如何在 WEBPACK + VUEJS 中减小包大小的主要内容,如果未能解决你的问题,请参考以下文章

图表太大。如何减小 vue js 中图表的大小?

Vuejs:如何使用 webpack 模板操作元素?

如何在 vuejs 和 webpack 中加载字体文件?

如何在 webpack 中使用 vuejs 禁用将块拆分为不同的文件?

如何在 vuejs webpack cli 项目中包含 jquery?

如何使用 webpack 从模板加载 VueJS 应用程序?