新建一个文件夹
create-react-app qiankun-base
create-react-app qiankun-micro-app1
create-react-app qiankun-micro-app1
主应用安装
npm i qiankun -S
在入口文件index.js中配置需要的信息
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'react app',
entry: '//localhost:3011',//端口号
container: '#micro-app1',//挂载点
activeRule: '/micro-app1',//路由
},
{
name: 'vue app',
entry: '//localhost:3012',
container: '#micro-app2',
activeRule: '/micro-app2',
},
]);
start();
在qiankun-base\src\App.js编写挂载点
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<div id="micro-app1"></div>
<div id="micro-app2"></div>
</div>
);
}
export default App;
两个微应用项目在 src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
/* global __webpack_public_path__:writable */
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
两个微应用中qiankun-micro-app1\src\index.js修改如下生命周期:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './public-path'
function render(props) {
const { container } = props;
ReactDOM.render(<App />, container ? container.querySelector('#root') : document.querySelector('#root'));
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('[react16] react app bootstraped');
}
export async function mount(props) {
console.log('[react16] props from main framework', props);
render(props);
}
export async function unmount(props) {
const { container } = props;
ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
功能:可以重写webpack配置信息
微应用都安装如下:
npm i react-app-rewired
根目录创建config-overrides.js
填入:
const { name } = require('./package');
module.exports = {
webpack: (config) => {
config.output.library = `${name}-[name]`;
config.output.libraryTarget = 'umd';//采用umd方式注入
config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;//webpack5要把 jsonpFunction,改为 chunkLoadingGlobal
config.output.globalObject = 'window';
return config;
},
devServer: (_) => {
const config = _;
config.headers = {
'Access-Control-Allow-Origin': '*',//允许跨域,主应用才能使用微应用资源
};
config.historyApiFallback = true;
config.hot = false;
config.watchContentBase = false;
config.liveReload = false;
return config;
},
};
主应用 qiankun-base\src\index.js
微应用的mount中可以接收
主要是测试练手,不是一定要写
主应用qiankun-base\src\index.js加入如下代码
import {
initGlobalState,
registerMicroApps,
start
} from 'qiankun';
const state = {
nickname:'主应用山竹'
}
// 初始化state
const actions = initGlobalState(state)
actions.onGlobalStateChange((state, prev) => {
// state:变更后的状态;prev变更前的状态
console.log(state,prev,'主应用')
})
setTimeout(() => {
actions.setGlobalState({
...state,
age: 19
})
}, 2000)
actions.offGlobalStateChange()
微应用qiankun-micro-app1\src\index.js修改mount做接收
export async function mount(props) {
console.log('[react16] props from main framework', props);
props.onGlobalStateChange((state,prev)=>{
// state:变更后的状态;prev变更前的状态
console.log(state,prev,'微应用')
setTimeout(() => {
props.setGlobalState({
...state,
age: 20
})
}, 2000)
})
render(props);
}
1.创建微应用
npm create qiankun-micro-vue3-app3
2.安装依赖
npm i qiankun -S
3.在如上public-path文件拷贝在src,引入到mainjs
import {
createApp
} from 'vue'
import App from './App.vue'
import './public-path'
// createApp(App).mount('#app')
let instance = null
function render(props = {}) {
console.log(props);
const {
container
} = props
instance = createApp(App);
instance.mount(container ? container.querySelector('#app') : '#app')
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}
export async function unmount() {
instance.unmount();
instance.container.innerHTML = '';
instance = null;
}
初始路由
npm install react-router-dom@6
修改主应用index.js页面
import { BrowserRouter } from 'react-router-dom'
root.render(
<React.StrictMode >
<BrowserRouter>
<App / >
</BrowserRouter>
</React.StrictMode>
);
修改微应用index.js,注意不同微应用basename的名字
function render(props) {
const { container } = props;
ReactDOM.render(
<BrowserRouter basename={window.__POWERED_BY_QIANKUN__?'/micro-app1':'/'}>
<App />
</BrowserRouter>
, container ? container.querySelector('#root') : document.querySelector('#root'));
}
主应用qiankun-base\src\App.js
import { Link } from 'react-router-dom'
function App() {
return (
<div className="App">
<Link to={"/micro-app1"}>micro-app1</Link>
<Link to={"/micro-app2"}>micro-app2</Link>
<div id="micro-app1"></div>
<div id="micro-app2"></div>
<div id="micro-app3"></div>
</div>
);
}
试试创建页面
qiankun-micro-app1\src\pages\Cat\index.js
import React from 'react'
export default function Cat() {
return (
<div>Cat</div>
)
}
qiankun-micro-app1\src\pages\Dog\index.js
import React from 'react'
export default function Dog() {
return (
<div>Dog</div>
)
}
qiankun-micro-app1\src\App.js
import logo from './logo.svg';
import './App.css';
import { Routes,Route,Link} from 'react-router-dom'
import Cat from './pages/Cat/index'
import Dog from './pages/Dog/index'
function App() {
return (
<div className="App">
微应用1
<Link to={"/cat"}>cat</Link> |
<Link to={"/dog"}>dog</Link>
<Routes>
<Route path="/cat" element={<Cat/>}/>
<Route path="/dog" element={<Dog/>}/>
</Routes>
</div>
);
}
export default App;
效果
初始路由
npm install vue-router
qiankun-micro-vue3-app3\src\router\index.js
import { createRouter, createWebHashHistory } from "vue-router";
import ZoonCat from "../view/ZoonCat.vue"
import ZoonDog from "../view/ZoonDog.vue"
const routes = [
{
path:'/ZoonCat',
component:ZoonCat
},
{
path:'/ZoonDog',
component:ZoonDog
},
]
const router = createRouter({
history: createWebHashHistory(
window.__POWERED_BY_QIANKUN__?'/micro-app3':'/'
),
routes
})
export default router
随便来两个组件
qiankun-micro-vue3-app3\src\App.vue
<template>
<div>
<router-link to="/zoonCat">zoonCat</router-link>|
<router-link to="/zoonDog">zoonDog</router-link>
<router-view />
</div>
</template>
qiankun-micro-vue3-app3\src\main.js
import router from './router/index'
//。。。其他代码
function render(props = {}) {
console.log(props);
const {
container
} = props
instance = createApp(App);
instance.use(router)
instance.mount(container ? container.querySelector('#app') : '#app')
}
效果
vue2为基底
vue create vue-base
vue create app1
vue create app2
全部项目都要的
npm install vue-router@3.2.0 -S
\src\router\index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import ZoonCat from "../view/ZoonCat.vue"
import ZoonDog from "../view/ZoonDog.vue"
const routes = [
{
path:'/ZoonCat',
component:ZoonCat
},
{
path:'/ZoonDog',
component:ZoonDog
},
]
const router = new VueRouter({
mode: 'history',
base:window.__POWERED_BY_QIANKUN__?'app-1':'/',
routes,
})
export default router
\src\main.js(暂时这么写着)
//其他代码
import router from './router/index'
new Vue({
router,
// store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
App.vue中映射
<router-view/>
主应用安装
npm i qiankun -S
主应用注册微应用vue-base\src\main.js
import Vue from 'vue'
import App from './App.vue'
import { registerMicroApps, start } from 'qiankun';
Vue.config.productionTip = false
registerMicroApps([
{
name: 'app1',
entry: '//localhost:81',
container: '#app1',//挂载点
activeRule: '/app-1',
},
{
name: 'app2',
entry: '//localhost:82',
container: '#app2',
activeRule: '/app-2',
},
]);
// 启动 qiankun
start();
new Vue({
render: h => h(App),
}).$mount('#app')
微应用\src\main.js配置生命周期之类的
import './public-path'
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
let instance = null;
function render(props = {}) {
const { container } = props;
instance = new Vue({
router,
//store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
主应用App.vue
<template>
<div id="app">
<router-link to="/app-1/ZoonCat">app1的猫</router-link>
<br/>
<router-link to="/app-1/ZoonDog">app1的狗</router-link>
<br/>
<router-link to="/app-2/ZoonCat">app2的猫</router-link>
<br/>
<router-link to="/app-2/ZoonDog">app2的狗</router-link>
<div id="app1"></div>
<div id="app2"></div>
<router-view/>
</div>
</template>
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
引入mainjs
import './public-path'
如果报 error ‘webpack_public_path’ is defined but never used no-unused-vars 的错误,在app1\package.json找到eslintConfig,输入以下代码,然后重启服务。
"eslintConfig": {
//其他代码
"globals": {
"__webpack_public_path__": true
}
},
const { name } = require('./package');
module.exports = {
devServer: {
port: 82,//端口号
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd', // 把微应用打包成 umd 库格式
// jsonpFunction: `webpackJsonp_${name}`,webpack5可以不要
},
},
};
每个项目都要
npm install vuex@3
store\index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
username: ''
},
mutations: {
changeName(state, username) {
state.username = username
}
},
actions: {
changeName(context, username) {
context.commit('changeName', username)
}
},
modules: {}
})
main.js引入store
//其他代码
import store from './store'
new Vue({
router,
store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
主应用main.js
import { initGlobalState } from 'qiankun';
const state = {
username: "山竹"
}
// 初始化 state
const actions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();
store.dispatch('changeName',state.username),//这里只是通信例子,非必写
src\App.vue
{{$store.state}}
效果
子应用app1\src\main.js
//。。。其他代码
function storeTest(props) {
props.onGlobalStateChange &&
props.onGlobalStateChange(
(value) => store.dispatch('changeName',value.username),
true
)
props.setGlobalState &&
props.setGlobalState({
igone: props.name,
user: {
name: props.name
}
})
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
storeTest(props)
render(props);
}