未改造CRA应用能否接入single-spa根配置导入映射?
问题解答
核心结论
不可直接在single-spa根配置的importmap中连接未改造的Create React App(CRA)应用。原因是普通CRA应用没有遵循single-spa模块规范:既没有打包成SystemJS可加载的模块格式,也不提供single-spa要求的bootstrap/mount/unmount生命周期钩子,无法被single-spa的模块加载机制识别和管理。
推荐集成方案(无需将CRA转为single-spa应用)
方案1:iframe嵌入(最简便,零改造CRA)
直接通过iframe加载CRA应用,完全隔离CRA与其他微应用的运行环境,无需修改CRA代码。
在single-spa的根应用或子应用中,创建一个包裹组件:
function CRAIframeWrapper() { return ( <iframe src="http://localhost:3000" // CRA本地开发地址,生产环境替换为部署域名 style={{ width: '100%', height: '100vh', border: 'none' }} title="cra-embedded-app" /> ); }
之后将该组件挂载到single-spa的路由对应路径下即可。
方案2:将CRA打包为UMD模块(轻量改造,无iframe隔离)
对CRA做极小改造,将其打包为UMD格式,然后在single-spa中手动管理生命周期:
- 安装依赖:
npm install react-app-rewired customize-cra --save-dev
- 在项目根目录创建
config-overrides.js,修改webpack输出配置:
const { override, adjustWebpackConfig } = require('customize-cra'); module.exports = override( adjustWebpackConfig(webpackConfig => { webpackConfig.output.library = 'CRAEmbeddedApp'; webpackConfig.output.libraryTarget = 'umd'; webpackConfig.output.globalObject = 'window'; return webpackConfig; }) );
- 修改
package.json的脚本命令:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }
- 在single-spa根配置的importmap中添加路径:
<% if (isLocal) { %> <script type="systemjs-importmap"> { "imports": { "@org1/root-config": "//localhost:9000/org1-root-config.js", "cra-app": "//localhost:3000/static/js/main.xxxx.js" // 替换为CRA本地UMD入口文件名 } } </script> <% } %>
- 在single-spa中注册自定义应用,手动处理挂载/卸载:
import ReactDOM from 'react-dom'; singleSpa.registerApplication({ name: 'cra-app', app: async () => { const craModule = await System.import('cra-app'); const CRAComponent = craModule.default; return { bootstrap: () => Promise.resolve(), mount: (props) => { ReactDOM.render(<CRAComponent />, props.domElementGetter()); return Promise.resolve(); }, unmount: (props) => { ReactDOM.unmountComponentAtNode(props.domElementGetter()); return Promise.resolve(); } }; }, activeWhen: ['/cra-app'], customProps: { domElementGetter: () => document.getElementById('cra-app-container') } });
方案3:使用single-spa的HTML应用类型
通过single-spa提供的singleSpaHtml工具直接加载CRA的完整HTML内容,适合不需要深度集成的场景:
import { registerApplication, singleSpaHtml } from 'single-spa'; registerApplication({ name: 'cra-app', app: singleSpaHtml({ template: () => fetch('http://localhost:3000').then(res => res.text()) }), activeWhen: ['/cra-app'], domElementGetter: () => document.getElementById('cra-app-container') });
注意:此方式可能存在全局样式、脚本冲突问题,需自行处理隔离。
内容的提问来源于stack exchange,提问作者Nandy
相关产品推荐
相关产品推荐

