Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

[Webpack][React] On SSR with code-splitting how I can get the list of chunks needed by the page?

I've a React application with perfectly working SSR and Webpack code-splitting.

My webpack.config.js looks like this:

const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ServerMiniCssExtractPlugin = require("./server/utils/serverMiniCssExtractPlugin");

module.exports = [{
  name: 'react-app',
  mode: 'development',
  devtool: 'eval',
  cache: true,
  entry: {
    main: [
      'babel-polyfill',
      'webpack-hot-middleware/client',
      './react/index.tsx',
    ],
  },
  output: {
    path: `${__dirname}/dist/__build__`,
    filename: '[name].js',
    chunkFilename: '[name].js',
    publicPath: '/__build__/',
  },
  module: {
    rules: [{
      test: /\.(ts|js)x?$/,
      loader: 'babel-loader',
      exclude: [/node_modules/],
    }, {
      test: /\.scss$/,
      oneOf: [{
        resourceQuery: /^\?raw$/,
        use: [MiniCssExtractPlugin.loader, {
          loader: 'css-loader',
          options: {
            modules: true,
            sourceMap: true,
            camelCase: false,
            localIdentName: '[local]',
          },
        }, 'sass-loader', 'postcss-loader'],
      }, {
        use: [MiniCssExtractPlugin.loader, {
          loader: 'css-loader',
          options: {
            modules: true,
            sourceMap: true,
            camelCase: true,
            localIdentName: '[path]___[name]__[local]___[hash:base64:5]',
          },
        }, 'sass-loader', 'postcss-loader'],
      }]
    }],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        CLIENT: JSON.stringify(true),
      },
    }),
    new webpack.IgnorePlugin(/^vertx$/),
    new MiniCssExtractPlugin({
      filename: "style.css",
      chunkFilename: "style.chunk.[id].css"
    }),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /node_modules/,
          name: 'vendor',
          enforce: true
        },
      },
    },
  },
}, {
  name: 'server-side rendering',
  mode: 'development',
  devtool: 'eval',
  cache: true,
  entry: [
    './react/ssr.tsx',
  ],
  target: 'node',
  output: {
    path: `${__dirname}/dist/__server__/`,
    filename: 'ssr.js',
    publicPath: '/__server__/',
    libraryTarget: 'commonjs2',
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  module: {
    rules: [{
      test: /\.(ts|js)x?$/,
      exclude: [/node_modules/, /.+\.config.js/],
      loader: 'babel-loader',
    }, {
      test: /\.scss$/,
      oneOf: [{
        resourceQuery: /^\?raw$/,
        use: [ServerMiniCssExtractPlugin.loader, {
          loader: 'css-loader',
          options: {
            modules: true,
            sourceMap: true,
            camelCase: false,
            localIdentName: '[local]',
          },
        }, 'sass-loader', 'postcss-loader'],
      }, {
        use: [ServerMiniCssExtractPlugin.loader, {
          loader: 'css-loader',
          options: {
            modules: true,
            sourceMap: true,
            camelCase: true,
            localIdentName: '[path]___[name]__[local]___[hash:base64:5]',
          },
        }, 'sass-loader', 'postcss-loader'],
      }]
    }],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        SERVER: JSON.stringify(true),
      },
    }),
    new webpack.IgnorePlugin(/^vertx$/),
    new ServerMiniCssExtractPlugin({
      filename: "style.css",
      chunkFilename: "style.chunk.[id].css"
    }),
  ],
}];

... and it generates chunks for both js and css that using the app are loaded correctly when moving from the different pages, all mapped with react-router.

The problem is that when I reload one of the pages the needed css chunks are loaded once rendered and not linked directly in the page from the SSR, so for a second I have FOUC.

Since I would like using React-Helmet to inject in the page head the needed css chunks when I SSR the app how I can get in the code the list of chunks file names that are needed for the page that I reload?

Let say that the page needs: 0.js 2.js style.chunk.0.css style.chunk.2.css

How I can get the list of these files so I can generate dynamically the links in the page head?

Thanks.

like image 264
StefS Avatar asked Jan 22 '26 18:01

StefS


1 Answers

Use the webpack-manifest-plugin to generate a manifest.json file that will include a list of all your chunks.

In your webpack.config.js:

var ManifestPlugin = require('webpack-manifest-plugin');

module.exports = {
    // ...
    plugins: [
      new ManifestPlugin()
    ]
};

This will generate a manifest.json file in your root output directory with a mapping of all source file names to their corresponding output file, for example:

{
  "mods/alpha.js": "mods/alpha.1234567890.js",
  "mods/omega.js": "mods/omega.0987654321.js"
}
like image 101
prograhammer Avatar answered Jan 25 '26 07:01

prograhammer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!