此文章以vue2为主应用为例,配置的子应用包含Vue2、Vue3+vite、React+vite、React(webpack),入门小Demo,简单配置运行,如果配置有错误的地方欢迎大家指正.(补充:导航菜单的路由路径根据第一个子应用的示例自行添加,以达到切换效果)
先上效果图!
一、主应用搭建(Vue2)
(1)主应用项目创建
使用的是Vue/cli创建的项目
1. 创建项目
步骤就不一一列举
npm i -g @vue/cli //其他的包管理工具就不多赘述
2. 修改端口号
在vue.config.js
修改当前项目的端口号:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
//我这里就以5000为例以此类推
devServer: {
port: 5000
}
})
3. 启动项目
npm run serve
(2)主应用页面
我们自己通过element-ui简单搭建了一个布局和菜单
(3)主应用配置qiankun
1. 路由配置
// src/router/index.js
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
redirect: "/home",
meta: {
base: true
},
children: [
{
path: 'home',
component: IndexView,
meta: {
base: true
},
},
{
path: 'user',
component: UserView,
meta: {
base: true
},
}
]
},
// 给其他qiankun子应用页面使用的路由
{
path: "/*",
component: HomeView
}
]
2. 下载qiankun
npm i qiankun
3. 配置qiankun
创建一个qiankun的配置文件
src
|--- qiankun
| |--- index.js
添加以下配置
// src/qiankun/index.js
import { registerMicroApps, start } from 'qiankun';
const apps = []
// 注册微(子)应用
registerMicroApps(apps);
export default start;
4. 全局启动qiankun
在main.js
中引入启动qiankun:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
//引入qiankun
import qiankunStart from './qiankun'
import './plugins/element.js'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
//启动qiankun
qiankunStart();
5.配置子应用出口 (主应用配置完成)
在布局中添加出口
<el-main>
<!-- 根据设置的标识来判断是主应用还是子应用 -->
<router-view v-if="$route.meta.base"></router-view>
<!-- 设置子应用出口 -->
<div id="container" v-show="!$route.meta.base"></div>
</el-main>
二、子应用配置(Vue2)
(1)搭建子应用
子应用搭建完成更改端口号:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 5001
},
})
(2)子应用页面
- 创建页面组件
- 配置路由(有变化,往下看)
- 启动项目
(3)配置qiankun子应用
1.修改webpack path配置
在src
中创建一个public-path.js
文件,添加以下代码
if (window.__POWERED_BY_QIANKUN__) {
window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
2.拆分路由配置
原来路由的配置文件(注释为删除的,在main
配置)
// import Vue from 'vue'
// import VueRouter from 'vue-router'
import UserView from '@/views/UserView.vue'
import IndexView from '@/views/IndexView.vue'
// Vue.use(VueRouter)
const routes = [
{
path: '/index',
component: IndexView
},
{
path: '/user',
component: UserView
}
]
// const router = new VueRouter({
// routes,
// mode: history
// })
export default routes
main
中添加路由配置
import Vue from 'vue'
import App from './App.vue'
//引入路由
import VueRouter from 'vue-router'
import routes from './router';
Vue.use(VueRouter)
import '@/public-path'
import store from './store'
Vue.config.productionTip = false
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
// 挂载路由
router = new VueRouter({
// `/children1`为子应用的路由前缀
base: window.__POWERED_BY_QIANKUN__ ? '/children1' : '/',
mode: 'history',
routes,
});
// Vue实例
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时(没有作为 qiankun 的子应用运行)
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
// qiankun 子应用的生命周期函数
export async function bootstrap() {
console.log('Vue2 的子应用初始化完成');
}
export async function mount(props) {
console.log('Vue2 的子应用挂载完成', props);
render(props);
}
// 子应用销毁
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
3.配置子应用的 webpack
vue.config.js
文件中
const { defineConfig } = require('@vue/cli-service')
// const { name } = require('./package');
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 5005,
// 设置请求头
headers: {
'Access-Control-Allow-Origin': '*',
}
},
configureWebpack: {
output: {
library: 'chlidren-vue2', // 设置子应用的名称
libraryTarget: 'umd', // 把微应用打包成 umd 库格式
// jsonpFunction: `webpackJsonp_${name}`, //官网这里有这一行,但是我保留了会报错所以注释
//自行尝试
},
})
(4)主应用注册子应用 (子应用Vue2配置完成)
在主应用的src/qiankun/index.js
文件中:
import { registerMicroApps, start } from 'qiankun';
const apps = [
{
name: 'chlidren-vue2', //子应用名称
entry: '//localhost:5001', //子应用的端口
container: '#container', //子应用出口容器的标签
activeRule: '/children1', //子应用的路由前缀
},
]
// 注册微(子)应用
registerMicroApps(apps);
export default start;
在菜单添加跳转进行测试
<el-submenu index="1" style="height: 100%;">
<template slot="title">
<span>主应用(Vue2)</span>
</template>
<el-menu-item-group>
<el-menu-item index="/home">Vue2主页</el-menu-item>
<el-menu-item index="/user">Vue2用户</el-menu-item>
</el-menu-item-group>
</el-submenu>
三、子应用配置(React)
(1)创建React子应用
1.创建项目
npx create-react-app react-app
2.下载依赖
.........路由(必备),其他随意
3.修改端口号
在项目根目录创建.env
的文件,添加以下代码:
PORT=5002
(2)搭建子应用页面
- 创建组件
- 配置路由
- 启动项目
(3)配置qiankun
1.修改webpack path 配置
在 src
中创建一个 public-path.js
文件,添加以下代码
if (window.__POWERED_BY_QIANKUN__) {
window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
2.设置history
模式路由的base
App.js
配置:
const App = () => {
return (
<BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/children2' : '/'}>
<Routes>
<Route path="/index" element={<Index />}></Route>
<Route path='/user' element={<User />}></Route>
</Routes>
</BrowserRouter>
)
}
3.配置qiankun子应用
在index.js
配置:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './public-path';
let root = null;
function render (props) {
const { container } = props;
root = ReactDOM.createRoot(
container ? container.querySelector('#root') : document.getElementById('root')
);
root.render(
<App />
);
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap () {
console.log('React 子应用初始化');
}
export async function mount (props) {
console.log('React 子应用挂载完成', props);
render(props);
}
export async function unmount (props) {
if (root) {
root.unmount();
root = null;
}
}
(4)配置webpack
1. 下载插件
npm i react-app-rewired -D
2.更改启动项目命令(重要)
在package.json
文件中,修改启动命令:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
3.创建配置文件
在项目根目录创建config-overrides.js
文件,作为React项目中webpack的配置.
4.配置webpack
在文件config-overrides.js
添加以下代码
module.exports = {
webpack: (config) => {
//子应用名称
config.output.library = 'children-react';
config.output.libraryTarget = 'umd';
return config;
},
devServer: (configFunction) => {
return (proxy, allowedHost) => {
const config = configFunction(proxy, allowedHost);
config.headers = {
'Access-Control-Allow-Origin': '*',
}
// 配置 history 模式
config.historyApiFallback = true;
return config;
}
}
}
5.注册子应用
const apps = [
//Vue2子应用
{
name: 'chlidren-vue2',
entry: '//localhost:5001',
container: '#container',
activeRule: '/children1',
},
//react子应用
{
name: 'children-react',
entry: '//localhost:5002',
container: '#container',
activeRule: '/children2',
},
]
四、子应用(Vue3+vite)
(1)搭建项目
1.创建Vue3项目
yarn create vite vue3-app --template vue-ts
2.下载路由依赖等....
3.修改端口号
在vite.config.ts
文件中修改端口号:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
port: 5003,
},
});
(2)搭建子应用页面
1.创建页面组件
2.配置路由
import { createRouter, createWebHistory } from "vue-router";
import { qiankunWindow } from "vite-plugin-qiankun/dist/helper";
import Index from "../views/index/HelloWorld.vue";
import User from "../views/user/User.vue";
const routes = [
{
path: "/index",
component: Index,
},
{
path: "/user",
component: User,
},
];
const router = createRouter({
routes,
history: createWebHistory(
qiankunWindow.__POWERED_BY_QIANKUN__ ? "/children3" : "/"
),
});
export default router;
路由配置完成挂载全局
import router from './router'
createApp(App).use(router).mount('#app')
3.配置路由出口
测试是否可以单独访问
(3)配置qiankun子应用
1.下载插件
yarn add vite-plugin-qiankun -D
2.配置qiankun子应用
在main.ts
配置:
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
// 全局挂载路由
import router from "./router";
// 引入qiankun
import {
qiankunWindow,
renderWithQiankun,
} from "vite-plugin-qiankun/dist/helper";
let app: any = null;
function render(props: any = {}) {
const { container } = props;
app = createApp(App);
app.use(router).mount(container ? container.querySelector("#app") : "#app");
}
// 独立运行
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render();
} else {
// 作为子应用运行
renderWithQiankun({
//生命周期函数
mount(props) {
render(props);
},
bootstrap() {
console.log("Vue3子应用挂载完成");
},
update() {
console.log("Vue3子应用更新");
},
unmount() {
app.unmount();
},
});
}
3.配置vite子应用
vite.config.ts
中完整配置
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import qiankun from "vite-plugin-qiankun";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
qiankun("children-vue3", {
useDevMode: true,
}),
],
server: {
port: 5002,
headers: {
"Access-Control-Allow-Origin": "*",
},
},
});
(4)主应用注册子应用
const apps = [
{
name: 'chlidren-vue2',
entry: '//localhost:5001',
container: '#container',
activeRule: '/children1',
},
{
name: 'children-react',
entry: '//localhost:5002',
container: '#container',
activeRule: '/children2',
},
{
name: 'children-vue3',
entry: '//localhost:5003',
container: '#container',
activeRule: '/children3',
}
]
五、子应用(React+vite)
(1)搭建项目
1.创建React项目
yarn create vite children-reactVite --template react-ts
2.下载依赖
3.修改端口参照Vue3
(2)搭建子应用
配置路由 src/router/RouterConfig.tsx
import Index from '../pages/index/Index'
import { useRoutes } from 'react-router-dom'
import User from '../pages/user/User'
const routes = [
{
path: '/index',
element: <Index />
},
{
path: '/user',
element: <User />
}
]
const RouterConfig = () => {
const router = useRoutes(routes)
return (
<>
{router}
</>
)
}
export default RouterConfig
(3)下载插件
yarn add vite-plugin-qiankun -D
(4)配置页面路由
import { Suspense } from "react"
//引入qiankunWindow
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
import { BrowserRouter } from 'react-router-dom'
import RouterConfig from "./router/RouterConfig"
function App() {
return (
<>
<Suspense >
//这里的window改为qiankunWindow
<BrowserRouter basename={qiankunWindow.__POWERED_BY_QIANKUN__ ? '/children4' : '/'}>
<RouterConfig></RouterConfig>
</BrowserRouter>
</Suspense>
</>
)
}
export default App
(5)路由挂载全局
main.js
挂载路由
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
//引入插件
import { qiankunWindow, renderWithQiankun } from 'vite-plugin-qiankun/dist/helper';
let root: any = null;
function render(props: any) {
const { container } = props;
root = ReactDOM.createRoot(
container ? container.querySelector('#root') : document.getElementById('root')
);
root.render(
<App />
);
}
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render({});
} else {
// 生命周期函数
renderWithQiankun({
mount(props) {
render(props);
},
bootstrap() {
console.log('React子应用挂载完成');
},
update() {
console.log('React子应用更新');
},
unmount() {
root.unmount();
root = null;
},
})
}
(6)配置vite子应用
在vite.config.ts
中配置
import { defineConfig } from "vite";
import qiankun from "vite-plugin-qiankun";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
// 一定要删除这一行
// react(),
qiankun("children-reactVite", {
useDevMode: true,
}),
],
server: {
port: 5004,
headers: {
"Access-Control-Allow-Origin": "*",
},
},
});
(7)主应用注册子应用
const apps = [
{
name: 'chlidren-vue2',
entry: '//localhost:5001',
container: '#container',
activeRule: '/children1',
},
{
name: 'children-react',
entry: '//localhost:5002',
container: '#container',
activeRule: '/children2',
},
{
name: 'children-vue3',
entry: '//localhost:5003',
container: '#container',
activeRule: '/children3',
},
{
name: 'children-reactVite',
entry: '//localhost:5004',
container: '#container',
activeRule: '/children4',
}
]