1

When executing Webpack 4 for development and production mode the chunks for development are smaller than when built for production. I am currently using the following Webpack 4 configuration;

const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const DuplicatePackageCheckerPlugin = require('@cerner/duplicate-package-checker-webpack-plugin');

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const bundleAnalyzerPlugin = new BundleAnalyzerPlugin();

/** ignore @anwb packages
 * Keep warning for multiple react-is versions as warning
 * * */
const duplicatePackageChecker = new DuplicatePackageCheckerPlugin({
    verbose: true,
    exclude(instance) {
        // ignore @anwb packages
        if (instance.name.includes('@anwb')) {
            return true;
        }
        return false;
    },
});

/** clean dist on build , webpack 5 supports clean property in output object * */
const cleanWebpackPlugin = new CleanWebpackPlugin();

module.exports = (env, argv) => {
    const isDevelopment = argv.mode === 'development';
    // No sourcemaps in production
    // const devtool = isDevelopment ? { devtool: 'source-map' } : {};
    const devtool = { devtool: 'source-map' };
    // Separated output folders for OTA an P to separate artifacts in pipeline
    const distFolder = isDevelopment ? 'distota' : 'dist';

    console.log(`Webpack build for       : ${isDevelopment ? 'development' : 'production'}`);
    console.log(`Source maps included    : ${Object.keys(devtool).length !== 0 ? 'yes' : 'no'}`);
    console.log(`Build directory         : ${distFolder}`);

    return {
        entry: {
            index: path.resolve(__dirname, './src/index.tsx'),
        },

        /**
         * Library target is set to umd so the anwb core js loading system can import it
         */
        output: {
            path: path.resolve(__dirname, `./${distFolder}`),
            filename: '[name].js',
            chunkFilename: '[name].js',
            libraryTarget: 'umd',
            publicPath: `/`,
        },

        resolve: {
            /**
             * Import files from the src or node_modules directory
             */
            modules: ['src', 'node_modules'],

            /**
             * Load preact-compat when react is encountered
             */
            alias: {
                react: 'preact/compat',
                'react-dom': 'preact/compat',
                '@anwb/typography': path.resolve(__dirname, '.', 'node_modules', '@anwb/typography'),
            },
            extensions: ['.ts', '.tsx', '.js'],
        },

        bail: true,

        /**
         * Include source maps
         */
        ...devtool,

        module: {
            rules: [
                /**
                 * The font is loaded using the fileloader and placed in a fonts folder
                 */
                {
                    test: /\.(eot|ttf|woff|woff2)$/,
                    loader: 'file-loader',
                    options: {
                        name: 'fonts/[name].[ext]',
                    },
                },

                /**
                 * The svg images are loaded and placed in the images directory
                 */
                {
                    test: /\.svg$/,
                    loader: 'file-loader',
                    options: {
                        name: 'images/[name][hash].[ext]',
                    },
                },

                /**
                 * All images bigger then 25000 bytes are placed in an images folder. Small images are included as inline base 64.
                 */
                {
                    test: /\.(png|jpg|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: '25000',
                        name: 'images/[name][hash].[ext]',
                    },
                },

                /**
                 * All less files are converted down to css and are autoprefixed using the postcss module
                 */
                {
                    test: /\.(less|css)$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        'postcss-loader',
                        {
                            loader: 'less-loader',
                            options: {
                                lessOptions: {
                                    javascriptEnabled: true,
                                },
                            },
                        },
                    ],
                },

                /**
                 * Js is transpiled using babel
                 */
                {
                    test: /\.(js|ts|tsx)$/,
                    exclude: ['/node_modules'],
                    include: [/src/, /node_modules\/@anwb/],
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                                '@babel/env',
                                {
                                    modules: false,
                                    targets: ['> 1% in NL', 'last 2 versions', 'last 5 iOS versions'],
                                    // NewRelic uses Chrome 72 (2019). Therefore we need to Polyfill some features like Promise.allSettled.
                                    // Story is made to remove it when NR is updated (MACS-13942)
                                    useBuiltIns: 'usage',
                                    corejs: { version: 3, proposals: true },
                                },
                            ],
                            '@babel/react',
                            '@babel/flow',
                        ],
                        plugins: [
                            ['@babel/plugin-transform-react-jsx', { pragma: 'h' }],
                            'syntax-dynamic-import',
                        ],
                    },
                },
            ],
        },

        optimization: {
            // splitChunks: {
            //  chunks: 'all',
            // },
            minimizer: [
                new CssMinimizerPlugin({
                    test: /.css$/i,
                    minimizerOptions: {
                        preset: [
                            'default',
                            {
                                discardComments: { removeAll: true },
                            },
                        ],
                    },
                }),
                new UglifyJsPlugin({
                    uglifyOptions: {
                        output: {
                            comments: false,
                        },
                    },
                }),
            ],
        },

        plugins: [
            bundleAnalyzerPlugin,
            cleanWebpackPlugin,

            /**
             * The extract text plugin makes sure that all css is put into a single css file named after the application
             */
            new MiniCssExtractPlugin({
                filename: '[name].css',
                chunkFilename: '[name].css',
            }),

            duplicatePackageChecker,

            /**
             * Dont use all moment locales
             */
            new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /nl/),

            new webpack.DefinePlugin({
                // "process.env": {
                //  NODE_ENV: simulateProduction ? JSON.stringify("production") : JSON.stringify("development")
                // },
                PRODUCTION: true,
            }),
        ],
    };
};

E.g. if the build is created for development the component has a stat size of 203KB

enter image description here

If the same build is run for production the same component has a stat size of 676KB

enter image description here

When the Webpack optimization is removed, this does not change. So i can rule this out.

Webpack is started using the two following package.json scripts;

    "build": "webpack --config ./webpack.js --mode=production",
    "build:ota": "webpack --config ./webpack.js --mode=development",

Any ideas how to optimize the chunks for production ?

pcvnes
  • 927
  • 2
  • 15
  • 41

0 Answers0