返回

React SSR 实践过程(三):生产环境配置和 JS 按需加载

前端

在上一篇文章中,我们对资源做了一些处理。接下来,让我们配置一下生产环境,并对 JS 进行按需动态加载处理。

在开发中,我们经常需要基于路由分包或对一些不太常用的库进行分包。前面,我们已经使用 webpack.base.js 将服务端和客户端的相同部分抽离出来。现在,有了生产环境配置,让我们修改一下 webpack.base.js。

以下是对 webpack.base.js 的修改:

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: path.resolve(__dirname, 'src', 'index.js'),
  output: {
    filename: '[name].[contenthash].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public', 'index.html'),
    }),
    new webpack.DllReferencePlugin({
      context: path.resolve(__dirname),
      manifest: path.resolve(__dirname, 'dist', 'vendor-manifest.json'),
    }),
  ],
  optimization: {
    moduleIds: 'deterministic',
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
};

我们引入了 webpack.DllReferencePlugin,它允许我们在生产构建中使用 DLL(动态链接库)。DLL 是一个包含共享代码的预编译库,可以提高构建速度。我们还修改了优化配置,以启用模块 ID 的确定性,使用单个运行时块,并使用拆分块将代码拆分为多个文件。

我们还需要创建一个 vendor-manifest.json 文件,它包含 DLL 中包含的模块的映射。这个文件将在生产构建期间由 webpack 自动生成。

{
  "dll-name": [
    "module-1",
    "module-2",
    "module-3"
  ]
}

最后,我们需要在服务端代码中引用 vendor.js 文件:

const express = require('express');
const path = require('path');

const app = express();

app.use(express.static(path.resolve(__dirname, 'dist')));

app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000');
});

通过这些修改,我们对 React SSR 项目进行了生产环境配置,并启用了 JS 的按需动态加载。这将提高我们的应用程序的性能和加载时间。