Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack code splitting impacts web performance

I have a React/Node + SSR application, I am trying to create a production build, I have managed to do that but the problem is that the files that I have in the build are too large. I use latest version of react + webpack 4. Here is my webpack configuration:

clientConfig.js

const path = require('path');
const common = require('./webpack.common-config');

const clientConfig = {
  ...common,
  mode: 'production',
  name: 'client',
  target: 'web',
  devtool: false,
  entry: {
    client: [
      '@babel/polyfill',
      './src/client.js'
    ],
  },
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: '[name].js',
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          chunks: 'all',
          name: 'vendor',
          test: module => /node_modules/.test(module.resource),
          enforce: true
        },
        common: {
          chunks: 'all',
          name: 'client'
        }
      },
    },
  },
  node: {
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
  }
};

module.exports = clientConfig;

serverConfig.js

const nodeExternals = require('webpack-node-externals');
const path = require('path');
const common = require('./webpack.common-config');

const serverConfig = {
  ...common,
  mode: 'production',
  name: 'server',
  target: 'node',
  devtool: false,
  externals: [nodeExternals()],
  entry: {
    server: ['@babel/polyfill', path.resolve(__dirname, 'src', 'server.js')],
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
    }
  },
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: '[name].js',
    chunkFilename: "[id].chunk.js"
  },
  node: {
    console: false,
    global: false,
    process: false,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },
};

module.exports = serverConfig;

commonConfig.js

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const common = {
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        include: [path.resolve(__dirname, 'src')],
        query: {
          presets: [
            ['@babel/preset-env', {loose: true, modules: false}],
            "@babel/preset-react"
          ],
          plugins: [
            "@babel/plugin-proposal-class-properties"
          ]
        },
      },
      {
        test: /\.css$/,
        use: [
            {
                loader: MiniCssExtractPlugin.loader,
            },
            'css-loader'
        ]
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: 'fonts/'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new OptimizeCSSAssetsPlugin(),
    new MiniCssExtractPlugin({
      filename: "styles.css",
    })
  ],
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()]
  },
};

module.exports = common;

And another file which basically merges the client and the server config.

I run npm run build after that I run webpack -p --mode=production --optimize-minimize && node ./build/server.js

I get the following warning:

    WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
    This can impact web performance.
    Assets: 
      vendor.js (667 KiB)
    
    WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
    Entrypoints:
      client (928 KiB)
          vendor.js
          styles.css
          client.js

Any advice or idea for the above size warning would be great! Thank you!

like image 453
Nicolae Maties Avatar asked Jul 10 '20 13:07

Nicolae Maties


People also ask

Does code splitting improve performance?

Code-splitting is splitting the bundle file into chunks based on the user's needs or what the user is interested in seeing. This idea brings about a decrease in the website's load time since users will need to download a smaller bundle file, giving users a better experience.

Does webpack improve performance?

Code Splitting Code splitting is a feature provided by webpack to split your code into multiple bundles which can be used on-demand. Code splitting results in reduced bundle size which can help us in improving the load time, hence, improving the performance.

Does webpack do code splitting?

Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel.

Why is my webpack build so slow?

Over the past eight years, webpack has become increasingly powerful. However, due to the additional packaging process, the building speed is getting slower as the project grows. As a result, each startup takes dozens of seconds (or minutes), followed by a round of build optimization.


1 Answers

I recommend that you try core-js instead of babel/pollyfill this can help you to reduce your bundle size.

Also, I recommend that you try dynamic importing with react-loadable which supports SSR. there are different strategies for splitting your code. you can read more here(most important one)

In case you are using CSS frameworks such as bootstrap you should only use parts that you need and avoid importing all of them. there is a tool for purging unused CSS named purgecss but use it with caution and you have to know what are you doing.

In case you are using libraries such as lodash or material-ui you should import your module specifically to avoid importing all the packages into your bundle.

exp: import debounce from 'lodash/debounce'

npm dedup or yarn dedup can help to remove duplicate dependencies inside bundle.

like image 55
Alireza Avatar answered Oct 11 '22 09:10

Alireza