[Webpack] [反应]在具有代码拆分功能的SSR上,如何获取页面所需的块列表?

时间:2018-12-18 14:39:25

标签: reactjs webpack serverside-rendering code-splitting

我有一个React应用程序,具有完美的SSR和Webpack代码拆分功能。

我的webpack.config.js看起来像这样:

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"
    }),
  ],
}];

...,它会为js和css生成块,当从不同页面移动时,使用该应用程序加载的块均正确,所有页面均由react-router映射。

问题是,当我重新加载其中一个页面时,所需的css块将在呈现后加载,而不是从SSR直接链接到页面中,因此有一秒钟,我有了FOUC

由于我想使用React-Helmet在我对应用程序进行SSR时向页面头部注入所需的css块,我如何才能在代码中获得重新加载页面所需的块文件名列表? / p>

让我们说该页面需要: 0.js 2.js style.chunk.0.css style.chunk.2.css

如何获取这些文件的列表,以便动态生成页面标题中的链接?

谢谢。

1 个答案:

答案 0 :(得分:0)

使用webpack-manifest-plugin生成manifest.json文件,其中将包含所有块的列表。

在您的webpack.config.js中:

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

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

这将在根输出目录中生成一个manifest.json文件,其中所有源文件名都映射到其对应的输出文件,例如:

{
  "mods/alpha.js": "mods/alpha.1234567890.js",
  "mods/omega.js": "mods/omega.0987654321.js"
}