如何在单个React应用中创建多个可随时提取、可独立构建的子应用
React 单根项目多子应用实现方案
基础项目结构调整
按照需求调整后的项目结构如下,所有资源全局共用,子应用完全独立隔离:
project-root/ ├── public/ # 全局共用静态资源目录,所有子应用可直接访问 ├── src/ │ ├── root-app/ # 根应用代码,负责子应用列表展示、路由分发 │ ├── apps/ # 子应用统一存放目录,每个子应用完全独立 │ │ ├── App1/ # 子应用1,自带独立入口、路由、业务逻辑 │ │ ├── App2/ # 子应用2 │ │ └── App3/ # 子应用3 │ └── common/ # 全局公共组件、工具函数、通用样式,所有应用可复用 ├── package.json # 全局唯一依赖清单,所有应用共用一套npm依赖 └── 构建配置文件(vite.config.js / webpack.config.js)
共用npm依赖与public目录实现
- 所有项目依赖全部安装在根目录
package.json,子应用不需要单独维护package.json,引入依赖时直接从根目录node_modules读取,天然共用一套依赖版本。 - 构建工具默认配置全局public目录即可,所有应用引用静态资源时直接使用
/资源路径的格式,即可访问public下的文件,无需单独适配。
子应用提取支持
完全支持随时提取任意子应用独立运行,只需要遵循2个开发规范即可:
- 每个子应用保留独立入口文件(如
main.jsx)、独立路由配置、独立状态管理实例,所有业务逻辑收敛在自身目录内。 - 子应用只能引入根目录
common下的公共代码,禁止直接引入其他子应用的内部代码,避免跨应用耦合。
提取时直接拷贝对应子应用目录+依赖的common目录代码,补充基础React项目构建配置即可独立运行,无需额外改造。
子应用单独构建实现
核心逻辑为通过构建参数动态切换构建入口、输出目录,所有构建配置全局共用,不需要为每个子应用单独写配置。以下为两种常用构建工具的实现示例:
Vite 配置示例
- 根目录
package.json添加对应构建脚本:
{ "scripts": { "dev:root": "vite --mode root", "dev:app1": "vite --mode app1", "dev:app2": "vite --mode app2", "build:root": "vite build --mode root", "build:app1": "vite build --mode app1", "build:app2": "vite build --mode app2" } }
vite.config.js动态匹配入口:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' const entryMap = { root: './src/root-app/main.jsx', app1: './src/apps/App1/main.jsx', app2: './src/apps/App2/main.jsx' } export default defineConfig(({ mode }) => { return { plugins: [react()], publicDir: 'public', // 固定全局public目录 build: { rollupOptions: { input: entryMap[mode] }, outDir: `dist/${mode}` // 不同应用构建产物输出到独立目录 } } })
Webpack 配置示例
- 安装cross-env统一环境变量写法,根目录
package.json添加脚本:
{ "scripts": { "build:app1": "cross-env BUILD_TARGET=app1 webpack build", "build:root": "cross-env BUILD_TARGET=root webpack build" } }
webpack.config.js动态匹配配置:
const path = require('path') const entryMap = { root: './src/root-app/index.js', app1: './src/apps/App1/index.js', app2: './src/apps/App2/index.js' } module.exports = { entry: entryMap[process.env.BUILD_TARGET], output: { path: path.resolve(__dirname, `dist/${process.env.BUILD_TARGET}`), filename: 'bundle.[contenthash].js' }, // 其余loader、plugin配置全局共用,public目录通过copy-webpack-plugin统一引入即可 }
本地调试说明
- 执行根应用的dev脚本,即可启动完整项目,在根应用中通过路由切换访问所有子应用。
- 执行对应子应用的dev脚本,即可单独启动调试对应子应用,不需要启动完整项目。
内容的提问来源于stack exchange,提问作者Abhi Dwivedi
相关产品推荐
相关产品推荐

