Appearance
qiankun 入门指南
环境准备
在开始使用 qiankun 之前,需要准备以下环境:
系统要求
- Node.js 版本 >= 8
- npm 或 yarn 包管理器
- 现代浏览器(支持 ES6+)
安装依赖
bash
# 创建项目目录
mkdir qiankun-demo
cd qiankun-demo
# 初始化项目
npm init -y
# 安装 qiankun
npm install qiankun
# 安装开发依赖(根据需要)
npm install --save-dev webpack webpack-cli
主应用配置
1. 安装和导入 qiankun
javascript
// main.js 或 index.js
import { registerMicroApps, start } from 'qiankun';
2. 创建主应用 HTML 结构
html
<!DOCTYPE html>
<html>
<head>
<title>主应用</title>
</head>
<body>
<div id="main-app">
<h1>主应用</h1>
<nav>
<a href="#/home">首页</a>
<a href="#/app1">应用1</a>
<a href="#/app2">应用2</a>
</nav>
<div id="subapp-container"></div>
</div>
<div id="subapp-viewport"></div>
</body>
</html>
3. 配置微应用
javascript
// main-app.js
import { registerMicroApps, start } from 'qiankun';
// 定义微应用列表
const apps = [
{
name: 'reactApp', // 应用名称
entry: '//localhost:3001', // 应用入口
container: '#subapp-viewport', // 应用挂载点
activeRule: '/app1', // 激活规则
},
{
name: 'vueApp',
entry: '//localhost:3002',
container: '#subapp-viewport',
activeRule: '/app2',
}
];
// 注册微应用
registerMicroApps(apps, {
// 可选的加载配置
beforeLoad: app => {
console.log('before load', app);
return Promise.resolve();
},
beforeMount: app => {
console.log('before mount', app);
return Promise.resolve();
},
afterMount: app => {
console.log('after mount', app);
return Promise.resolve();
},
beforeUnmount: app => {
console.log('before unmount', app);
return Promise.resolve();
},
afterUnmount: app => {
console.log('after unmount', app);
return Promise.resolve();
}
});
// 启动 qiankun
start({
prefetch: true, // 预加载
sandbox: {
strictStyleIsolation: false, // 严格样式隔离
experimentalStyleIsolation: true, // 实验性样式隔离
}
});
微应用配置
1. React 微应用配置
修改 React 应用入口文件
javascript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 声明全局变量,用于判断是否在微应用环境中
let app = null;
// 微应用独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
ReactDOM.render(<App />, document.getElementById('root'));
}
// 微应用接入 qiankun 时的生命周期
export async function bootstrap(props) {
console.log('React应用启动');
}
export async function mount(props) {
console.log('React应用挂载', props);
const { container } = props;
app = ReactDOM.render(
<App />,
container ? container.querySelector('#root') : document.getElementById('root')
);
}
export async function unmount(props) {
console.log('React应用卸载', props);
const { container } = props;
ReactDOM.unmountComponentAtNode(
container ? container.querySelector('#root') : document.getElementById('root')
);
app = null;
}
配置 webpack
javascript
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// ... 其他配置
devServer: {
port: 3001, // 设置端口避免冲突
headers: {
'Access-Control-Allow-Origin': '*',
},
},
output: {
library: 'reactApp', // 微应用名称
libraryTarget: 'umd', // 输出格式
publicPath: '//localhost:3001/', // 公共路径
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
2. Vue 微应用配置
修改 Vue 应用入口文件
javascript
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
let app = null;
// 微应用独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
app = createApp(App).use(store).use(router).mount('#app');
}
// 微应用接入 qiankun 时的生命周期
export async function bootstrap() {
console.log('Vue应用启动');
}
export async function mount(props) {
console.log('Vue应用挂载', props);
const { container } = props;
app = createApp(App);
app.use(store);
app.use(router);
app.mount(container ? container.querySelector('#app') : '#app');
}
export async function unmount() {
console.log('Vue应用卸载');
app.unmount();
app = null;
}
配置 Vue CLI
javascript
// vue.config.js
module.exports = {
devServer: {
port: 3002,
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: 'vueApp',
libraryTarget: 'umd',
publicPath: '//localhost:3002/',
},
},
};
通信机制
1. 全局状态管理
javascript
// 主应用中初始化全局状态
import { initGlobalState } from 'qiankun';
const initialState = {
user: { name: 'admin' },
theme: 'light',
};
const { onGlobalStateChange, setGlobalState } = initGlobalState(initialState);
// 监听全局状态变化
onGlobalStateChange((state, prev) => {
console.log('全局状态变化', state, prev);
});
2. 微应用中使用全局状态
javascript
// 微应用中接收和修改全局状态
export async function mount(props) {
// 监听全局状态变化
props.onGlobalStateChange((state, prev) => {
console.log('微应用监听到全局状态变化', state, prev);
});
// 修改全局状态
props.setGlobalState({
user: { name: 'microAppUser' },
updateTime: Date.now(),
});
}
高级配置
1. 沙箱配置
javascript
start({
sandbox: {
// 严格模式沙箱,样式隔离
strictStyleIsolation: true,
// 实验性样式隔离
experimentalStyleIsolation: false,
// 激活可选沙箱
iframe: false,
}
});
2. 预加载配置
javascript
start({
// 预加载配置
prefetch: {
// 关键应用列表,立即预加载
criticalAppList: [
{ name: 'criticalApp', entry: '//localhost:3003' }
],
// 闲置应用列表,空闲时预加载
idleAppList: [
{ name: 'idleApp', entry: '//localhost:3004' }
],
}
});
路由配置
1. 主应用路由
javascript
// 主应用路由配置
const routes = [
{ path: '/', component: Home },
{ path: '/app1', component: () => import('./MicroApp1') },
{ path: '/app2', component: () => import('./MicroApp2') },
];
// 使用 history 模式时的配置
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
2. 微应用路由
微应用的路由配置保持不变,但需要注意与主应用的路由规划协调。
常见问题解决
1. 跨域问题
javascript
// 开发环境下解决跨域
// 微应用的 webpack 配置
module.exports = {
devServer: {
port: 3001,
headers: {
'Access-Control-Allow-Origin': '*',
},
},
};
2. 样式冲突
javascript
// 启用严格样式隔离
start({
sandbox: {
strictStyleIsolation: true,
}
});
3. 资源加载问题
javascript
// 确保微应用资源路径正确
output: {
publicPath: '//localhost:3001/', // 确保与微应用部署路径一致
}
完整示例
主应用 package.json
json
{
"name": "main-app",
"version": "1.0.0",
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack --mode production"
},
"dependencies": {
"qiankun": "^2.10.0"
}
}
微应用 package.json
json
{
"name": "micro-app",
"version": "1.0.0",
"scripts": {
"start": "webpack serve --mode development",
"build": "webpack --mode production"
},
"dependencies": {
"react": "^17.0.0",
"react-dom": "^17.0.0"
}
}
通过以上配置,您就可以成功搭建一个基于 qiankun 的微前端应用了。记住要确保主应用和微应用的端口不冲突,并且微应用支持跨域访问。