微前端提供通過不同技術(shù)棧培他、能夠以單獨發(fā)布的方式將多個子應用構(gòu)建成一個主應用的技術(shù)方案。
所以結(jié)構(gòu)分為主框架遗座,和任意多個子應用舀凛。
核心價值
- 和技術(shù)棧無關(guān),每個子應用可以選擇不同的技術(shù)棧
- 子應用可以單獨開發(fā)途蒋、部署猛遍,部署完后主框架自動完成同步更新。
- 每個子應用可以獨立運行
使用場景
一般適用于較大型的項目号坡,需要將項目拆分成多個子應用并合并懊烤,不同的業(yè)務模塊之間相對獨立,可單獨開發(fā)部署的項目宽堆。
Dome
- 建三個項目腌紧,包括一個主應用(qiankun-base),兩個子應用(qiankun-vue畜隶、qiankun-react) 可以用腳手架生成(vue create 壁肋、create-react-app)
- 安裝包 qiankun
- 盡量端口號不一樣,保證三個項目能夠同時跑起來
主應用(qiankun-base)
dome選擇vue作為基座
修改入口文件src/App.vue
<template>
<div id="app">
<el-menu :router="true" mode="horizontal">
<!--基座中可以放自己的路由-->
<el-menu-item index="/">Home</el-menu-item>
<!--引用其他子應用路由-->
<el-menu-item index="/vue">vue應用</el-menu-item>
<el-menu-item index="/react">react應用</el-menu-item>
</el-menu>
<!-- 主應用自己的路由 -->
<router-view></router-view>
<!-- 子應用的渲染位置 -->
<div id="vue"></div>
<div id="react"></div>
</div>
</template>
修改src/main.js引入qiankun
// 引入qiankun
import { registerMicroApps, start } from 'qiankun';
const apps = [
{
name: 'vueApp', // 子應用的名字
entry: '//localhost:8081', // 默認會加載這個html 解析里面的js 動態(tài)的執(zhí)行 (子應用必須支持跨域)fetch
container: '#vue', // App.vue中容器名(此項目頁面中定義的容器id籽慢,用于把對應的子應用放到此容器中)
activeRule: '/vue', // 激活的路徑
props: { a: 1 } // 傳遞的值(可選)
},
{
name: 'reactApp',
entry: '//localhost:20000', // 默認會加載這個html 解析里面的js 動態(tài)的執(zhí)行 (子應用必須支持跨域)fetch
container: '#react',
activeRule: '/react',
}
]
registerMicroApps(apps); // 注冊應用
start({
prefetch: false // 取消預加載
});// 開啟
const router = new VueRouter({
mode: "history",
routes,
});
new Vue({
router,
render: h => h(App),
}).$mount('#app')
子應用(qiankun-vue)
src/main.js
import Vue from 'vue'
import App from './App.vue'
// import router from './router'
// Vue.config.productionTip = false
let instance = null
function render(props) {
instance = new Vue({
// router,
render: h => h(App)
}).$mount('#vueApp'); // 這里是掛載到自己的html中 基座會拿到這個掛載后的html 將其插入進去
}
if (window.__POWERED_BY_QIANKUN__) { // 動態(tài)添加publicPath
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
if (!window.__POWERED_BY_QIANKUN__) { // 默認獨立運行
render();
}
// 父應用加載子應用浸遗,子應用必須暴露三個接口:bootstrap、mount箱亿、unmount
// 子組件的協(xié)議就ok了
export async function bootstrap(props) {
};
export async function mount(props) {
render(props)
}
export async function unmount(props) {
instance.$destroy();
}
public/index.html
<div id="vueApp"></div>
vue.config.js
module.exports = {
lintOnSave: false, // 關(guān)閉eslint檢測
devServer: {
port: 8080,//這里的端口是必須和父應用配置的子應用端口一致
headers: {
//因為qiankun內(nèi)部請求都是fetch來請求資源跛锌,所以子應用必須允許跨域
'Access-Control-Allow-Origin': '*'
}
},
configureWebpack: {
output: {
//資源打包路徑
library: 'vueApp',
libraryTarget: 'umd'
}
}
}
子應用(qiankun-react)
安裝包:react-app-rewired
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
function render(){
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
}
if(!window.__POWERED_BY_QIANKUN__){
render();
}
export async function bootstrap(){
}
export async function mount() {
render()
}
export async function unmount(){
ReactDOM.unmountComponentAtNode( document.getElementById('root')); // 卸載節(jié)點
}
qiankun-react下創(chuàng)建config-overrides.js
module.exports = {
webpack: (config) => {
config.output.library = 'reactApp';
config.output.libraryTarget = 'umd';
config.output.publicPath = 'http://localhost:20000/'; // 此應用自己的端口號
return config;
},
devServer: (configFunction) => {
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost);
config.headers = {
"Access-Control-Allow-Origin": '*'
}
return config
}
}
}
qiankun-react下創(chuàng)建.env文件
PORT=20000
BROWSER=none
修改package.json的啟動命令
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},