在本节中,我们将详细介绍如何配置和集成子应用到主应用中。子应用将是独立的React 18项目,通过Qiankun框架与主应用集成。以下步骤将指导你完成子应用的创建、配置和集成过程。
创建子应用
每个子应用也是一个Vite+React 18项目。我们将创建一个子应用,并配置它以支持微前端架构。
-
初始化子应用
-
创建并初始化一个新的Vite项目作为子应用:
npm create vite@latest sub-app-1 --template react-ts cd sub-app-1 npm install
-
子应用的文件结构:
sub-app-1/ ├── public/ ├── src/ │ ├── App.tsx │ ├── main.tsx │ ├── index.css ├── index.html ├── package.json └── vite.config.ts
-
配置子应用的生命周期函数
修改子应用的main.tsx以支持作为微前端应用启动:
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
function render(props: any) {
const { container } = props;
const root = ReactDOM.createRoot(container ? container.querySelector('#root') : document.querySelector('#root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('React app bootstraped');
}
export async function mount(props: any) {
render(props);
}
export async function unmount(props: any) {
const { container } = props;
const root = container ? container.querySelector('#root') : document.querySelector('#root');
ReactDOM.unmountComponentAtNode(root);
}
- 配置Vite支持跨域加载
在vite.config.ts中配置CORS支持,以便主应用可以加载子应用的资源:
// vite.config.tsimport { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({plugins: [react()],server: {port: 7100,cors: true,
},
});
- 添加基本组件
创建一个简单的子应用页面:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 7100,
cors: true,
},
});
集成子应用到主应用
- 启动子应用
在sub-app-1目录下启动子应用:
npm run dev
- 注册子应用
在主应用中使用Qiankun的registerMicroApps方法注册子应用,并启动Qiankun。
// src/App.tsx
import React, { useEffect } from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import { registerMicroApps, start } from 'qiankun';
import Home from './pages/Home';
import About from './pages/About';
const App = () => {
useEffect(() => {
registerMicroApps([
{
name: 'sub-app-1',
entry: '//localhost:7100', // 子应用入口
container: '#subapp-container',
activeRule: '/subapp1',
},
]);
start();
}, []);
return (
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/subapp1">Sub App 1</Link></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/subapp1/*" element={<div id="subapp-container"></div>} />
</Routes>
</div>
);
};
export default App;
- 测试集成
访问主应用的URL,导航到/subapp1路径,应该会看到子应用1的内容被正确加载。
高级配置
- 样式隔离
子应用的样式可能会与主应用冲突。可以使用CSS Module、Shadow DOM或者在CSS选择器中加入应用特定的前缀。
- 通信机制
使用自定义事件或全局状态管理库(如Redux)实现主应用与子应用之间的通信。
- 性能优化
采取懒加载子应用、代码分割、资源预加载等策略优化启动性能。
- 安全性
采用内容安全策略(CSP)和沙箱环境等技术降低安全风险。
示例代码
完整的主应用代码示例:
// src/App.tsx
import React, { useEffect } from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import { registerMicroApps, start } from 'qiankun';
import Home from './pages/Home';
import About from './pages/About';
const App = () => {
useEffect(() => {
registerMicroApps([
{
name: 'sub-app-1',
entry: '//localhost:7100', // 子应用入口
container: '#subapp-container',
activeRule: '/subapp1',
},
]);
start();
}, []);
return (
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/subapp1">Sub App 1</Link></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/subapp1/*" element={<div id="subapp-container"></div>} />
</Routes>
</div>
);
};
export default App;
子应用代码示例:
// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
function render(props: any) {
const { container } = props;
const root = ReactDOM.createRoot(container ? container.querySelector('#root') : document.querySelector('#root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('React app bootstraped');
}
export async function mount(props: any) {
render(props);
}
export async function unmount(props: any) {
const { container } = props;
const root = container ? container.querySelector('#root') : document.querySelector('#root');
ReactDOM.unmountComponentAtNode(root);
}
通过本节内容,我们已经了解了如何创建和配置子应用,并将其集成到主应用中。我们还介绍了样式隔离、通信机制、性能优化和安全性等高级配置。下一步,我们将继续探索子应用之间的通信和状态管理。