Breaking webpack chunks to ensure multiple chunks while having minimum dependency in my react app

106 Views Asked by At

I am using webpack to create chunks for my react application. My base repo has some JS files in it, and some submodules which are separate repos. Each submodule may be consuming on JS files from the base repo. The webpack is as follows :-

let baseConfig = {
    devtool: false,
    mode: 'production',
    entry: {
        main: path.join(__dirname, 'src', 'app-client.js'),
        common: ['axios', 'react-router']
    },
    externals: {
        react: 'React',
        'react-dom': 'ReactDOM',
    },
    output: {
        path: path.join(__dirname, 'src', 'static', 'pwa', 'js', 'bundle'),
        publicPath: cfg.jsAssetPath + "/bundle/",
        filename: 'bundle.[contenthash].js',
        chunkFilename: '[name].[contenthash].js'
    },

    plugins: debug ? [] : [
        new webpack.DefinePlugin({
        }),
        new WebpackAssetsManifest({
            writeToDisk: true,
            output: path.join(__dirname, 'src', 'static', 'pwa', 'js', 'bundle', "manifest.json"),
        }),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new OptimizeJsPlugin({
            sourceMap: false
        }),
        // new BundleAnalyzerPlugin(),

    ],
    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
        runtimeChunk: {
            name: 'manifest',
        },
        splitChunks: {
            chunks: 'async',
            minSize: 10, // minimum size for a chunk to eligible for creation
            maxSize: 0,
            minChunks: 1,
            maxAsyncRequests: 2,
            maxInitialRequests: 20,
            automaticNameDelimiter: '-',
            automaticNameMaxLength: 200,
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: 10,
                    name: "nodeModules",
                    //chunks: "all"
                },
                first_chunk: {
                    test: /[\\/]first[\\/]/,
                    name: "first_chunk",
                    priority: 11,
                    //chunks: "all"
                },
                second_chunk: {
                    test: /[\\/]second[\\/]/,
                    name: "second_chunk",
                    priority: 12,
                    //chunks: "all"
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                },
            }
        }
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                include: path.resolve(__dirname, 'react-common'),
                use: [
                    { loader: 'cache-loader' },
                    {
                        loader: 'babel-loader',
                        options: { presets: ['react', 'es2015'] },
                    }
                ]
            }, {
                test: /\.js$/,
                include: path.resolve(__dirname, 'src'),
                use: [
                    { loader: 'cache-loader' },
                    {
                        loader: 'babel-loader',
                        options: { presets: ['react', 'es2015'] },
                    }
                ]
            },
            {
                test: /\.js$/,
                include: path.resolve(__dirname, process.env.PRODUCT),
                use: [
                    { loader: 'cache-loader' },
                    {
                        loader: 'babel-loader',
                        options: { presets: ['react', 'es2015'] },
                    }
                ]
            }, {
                test: /\.(sa|sc|c)ss$/,
                include: path.resolve(__dirname, 'react-common'),
                use: useCssLoader
            },
            {
                test: /\.(sa|sc|c)ss$/,
                include: path.resolve(__dirname, 'src'),
                use: useCssLoader
            },
            {
                test: /\.(sa|sc|c)ss$/,
                include: path.resolve(__dirname, process.env.PRODUCT),
                use: useCssLoader
            },
            {
                test: /\.js$/,
                include: path.resolve(__dirname, 'first-repo'),
                use: [
                    { loader: 'cache-loader' },
                    {
                        loader: 'babel-loader',
                        options: { presets: ['react', 'es2015'] },
                    }
                ]
            },
            {
                test: /\.(sa|sc|c)ss$/,
                include: path.resolve(__dirname, 'second-repo'),
                use: useCssLoader
            }, {
                test: /\.js$/,
                include: path.resolve(__dirname, 'second-repo'),
                use: [
                    { loader: 'cache-loader' },
                    {
                        loader: 'babel-loader',
                        options: { presets: ['react', 'es2015'] },
                    }
                ]
            },
        ]
    },
    resolve: {
        alias: {
            "@approot": path.resolve(__dirname, "src"),
            "@react-common": path.resolve(__dirname, "react-common"),
            "@project": path.resolve(__dirname, process.env.PRODUCT),
            'react': path.resolve(dirpath, 'node_modules', 'react'),
            "@first-repo": path.resolve(__dirname, "first-repo"),
            "@second-repo": path.resolve(__dirname, "second-repo"),
        },
        modules: [
            path.resolve('./' + process.env.PRODUCT),
            path.resolve('./src'),
            path.resolve('./react-common'),
            path.resolve(dirpath, 'node_modules'),
            path.resolve('./first-repo'),
            path.resolve('./second-repo'),
        ],
        extensions: ['.js', '.jsx', '.scss', '.css'],
        symlinks: false,
        cacheWithContext: false
    },
    node: {
        //This due to Module not found: Error: Can't resolve 'child_process' in Memcahced
        //with reference http://www.programfaqs.com/faq/conditional-memcached-usage-in-isomorphic-application/
        net: 'empty',
        child_process: 'empty',
    },
};


module.exports = function () {

    return baseConfig;
}

Now, in my cache group, if i use "all", it breaks chunks without code repetition, but my app wont run unless i include all chunks. If i run it with "async", it creates chunks, but dumps everything in "main".

Both cases, i end up getting a lot of JS on the page which wont execute on page load, which is hurting my SEO.

First and second module are independent functionally, we dont need the JS to load on the other.

Can anyone help here ?

0

There are 0 best solutions below