You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Express实例在React脚手架中实现Webpack多入口共享代码库应用

没问题,我来帮你梳理这个「React脚手架+Webpack多入口+共享代码+双Express服务」的完整实现方案,咱们一步一步来落地:

一、Webpack 多入口配置(基于Create React App 自定义)

因为Create React App默认隐藏Webpack配置,咱们用react-app-rewired来修改更省心,不用 eject。

  1. 先安装依赖:
npm install react-app-rewired customize-cra html-webpack-plugin --save-dev
  1. 在项目根目录新建config-overrides.js,配置多入口、多HTML模板和共享代码拆分:
const { override, addWebpackPlugin, addWebpackEntry, addWebpackOutput } = require('customize-cra');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = override(
  // 配置多入口,关联你的两个入口JS文件
  addWebpackEntry({
    vendor: path.resolve(__dirname, 'src/vendor.js'),
    settings: path.resolve(__dirname, 'src/settings.js'),
  }),
  // 配置输出规则,让两个应用的产物分开存放
  addWebpackOutput({
    filename: '[name]/static/js/[name].[contenthash:8].js',
    chunkFilename: '[name]/static/js/[name].[contenthash:8].chunk.js',
    path: path.resolve(__dirname, 'build'), // 统一输出到build目录下的子文件夹
  }),
  // 配置两个HTML模板,分别对应两个应用的入口页面
  addWebpackPlugin([
    new HtmlWebpackPlugin({
      inject: true,
      template: path.resolve(__dirname, 'public/vendor.html'),
      filename: 'vendor/index.html',
      chunks: ['vendor', 'vendors'], // 关联vendor入口和共享代码chunk
    }),
    new HtmlWebpackPlugin({
      inject: true,
      template: path.resolve(__dirname, 'public/settings.html'),
      filename: 'settings/index.html',
      chunks: ['settings', 'vendors'], // 关联settings入口和共享代码chunk
    }),
  ]),
  // 配置共享代码自动拆分,提取被两个入口共同引用的代码
  (config) => {
    config.optimization.splitChunks = {
      chunks: 'all',
      name: 'vendors', // 共享chunk的统一名称
      minChunks: 2, // 被至少2个入口引用才会拆分
    };
    return config;
  }
);
二、完善Express Server.js 配置

把你现有的Server.js补全,实现两个独立的Express服务,分别对应两个应用的静态资源和路由:

const express = require('express');
const path = require('path');
const { resolve } = path;

// 通用的服务初始化函数,复用逻辑
function setup(app, { domain, outputPath, publicPath }) {
  // 生产环境:托管打包后的静态文件
  app.use(publicPath, express.static(outputPath));

  // 路由:返回对应应用的HTML入口
  app.get('*', (req, res) => {
    res.sendFile(resolve(outputPath, 'index.html'));
  });

  // 启动服务,给两个应用分配不同端口
  const port = domain === 'Vendor' ? 3001 : 3002;
  app.listen(port, () => {
    console.log(`${domain} app running at http://localhost:${port}`);
  });
}

// 初始化两个应用服务
const appVendor = express();
const appSetting = express();

// 注意:这里的outputPath要和Webpack配置的输出目录对应
setup(appVendor, {
  domain: 'Vendor',
  outputPath: resolve(process.cwd(), 'build/vendor'),
  publicPath: '/',
});

setup(appSetting, {
  domain: 'Settings',
  outputPath: resolve(process.cwd(), 'build/settings'),
  publicPath: '/',
});

如果是开发环境,还要集成Webpack热更新,修改setup函数:

const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackConfig = require('./config-overrides.js');

function setup(app, { domain, outputPath, publicPath }) {
  if (process.env.NODE_ENV === 'development') {
    // 开发环境:启用Webpack实时编译和热更新
    const compiler = webpack(webpackConfig);
    app.use(webpackDevMiddleware(compiler, {
      publicPath: publicPath,
      stats: 'minimal',
    }));
    app.use(webpackHotMiddleware(compiler));
  } else {
    // 生产环境:托管静态文件
    app.use(publicPath, express.static(outputPath));
  }

  // 路由逻辑适配开发/生产环境
  app.get('*', (req, res) => {
    const htmlPath = process.env.NODE_ENV === 'development' 
      ? resolve(__dirname, `public/${domain.toLowerCase()}.html`)
      : resolve(outputPath, 'index.html');
    res.sendFile(htmlPath);
  });

  // 启动服务
  const port = domain === 'Vendor' ? 3001 : 3002;
  app.listen(port, () => {
    console.log(`${domain} app running at http://localhost:${port}`);
  });
}
三、共享代码的组织与使用

在src目录下新建shared文件夹,把两个应用共用的组件、工具函数、样式放在这里:

src/
├── vendor.js       # Vendor应用入口
├── settings.js     # Settings应用入口
└── shared/
    ├── components/ # 共享组件(比如通用Button、Header)
    ├── utils/      # 共享工具函数(比如请求工具、日期格式化)
    └── styles/     # 共享全局样式

然后在两个入口文件里直接引用即可,Webpack会自动把被两个入口共同引用的代码拆分到vendors chunk里:

// src/vendor.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './shared/styles/global.css';
import VendorApp from './components/VendorApp';
import { formatDate } from './shared/utils/date';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <VendorApp />
  </React.StrictMode>
);
四、配置构建与运行脚本

修改package.json里的scripts,方便一键构建和启动:

{
  "scripts": {
    "start:dev": "cross-env NODE_ENV=development node Server.js",
    "build": "react-app-rewired build",
    "start:prod": "node Server.js"
  }
}

(注:如果是Windows系统,安装cross-env来兼容环境变量配置,避免命令报错)

最后验证一下:

  • 开发环境运行npm run start:dev,两个服务会分别在3001和3002端口启动,修改代码会实时热更新
  • 生产环境运行npm run build,会在build目录下生成vendor和settings两个子文件夹,对应两个应用的产物,再运行npm run start:prod即可启动生产服务

内容的提问来源于stack exchange,提问作者Rohit Dubey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:11:31