「本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!javascript
你們好,我是
前端小菜雞之菜雞互啄
,若是你喜歡個人文章,記得給我點個贊哦💪css
在正式介紹 qiankun 以前,咱們須要知道,qiankun 是一個基於 single-spa 的微前端實現庫,旨在幫助你們能更簡單、無痛的構建一個生產可用微前端架構系統。html
微前端的概念借鑑自後端的微服務,主要是爲了解決大型工程在變動、維護、擴展等方面的困難而提出的。目前主流的微前端方案包括如下幾個:前端
嚴格來說,這些方案都不算是完整的微前端解決方案,它們只是用於解決微前端中運行時容器的相關問題。vue
本文咱們主要對 qiankun 所基於的基座模式進行介紹。它的主要思路是將一個大型應用拆分紅若干個更小、更簡單,能夠獨立開發、測試和部署的微應用,而後由一個基座應用根據路由進行應用切換。java
🥄 簡單node
因爲主應用微應用都能作到技術棧無關,qiankun 對於用戶而言只是一個相似 jQuery 的庫,你須要調用幾個 qiankun 的 API 便可完成應用的微前端改造。同時因爲 qiankun 的 HTML entry 及沙箱的設計,使得微應用的接入像使用 iframe 同樣簡單。react
🍡 解耦/技術棧無關jquery
微前端的核心目標是將巨石應用拆解成若干能夠自治的鬆耦合微應用,而 qiankun 的諸多設計均是秉持這一原則,如 HTML entry、沙箱、應用間通訊等。這樣才能確保微應用真正具有 獨立開發、獨立運行 的能力。webpack
本文適合剛接觸
qiankun
的新人,介紹瞭如何從 0 構建一個qiankun
項目。項目主要有如下構成:
主應用:
vue 微應用:
react 微應用:
umi3 微應用:
非 webpack 構建的微應用:
Angular 微應用:
主應用按照官方的說法,不限技術棧,只須要提供一個容器 DOM,而後註冊微應用並 start 便可。這裏咱們使用 umi 來初始化。
# 項目初始化
$ yarn create @umijs/umi-app
# 安裝依賴
$ yarn
# 啓動
$ yarn start
# 安裝 qiankun
$ yarn add qiankun
複製代碼
基本環境搭建完成,在主應用中增長一些菜單和路由,用於主應用頁面以及主應用和微應用之間切換操做。頁面佈局和路由配置這裏不作過多介紹,文末會奉上源碼。大體頁面以下圖:
註冊微應用的基礎配置信息。當瀏覽器 url 發生變化時,會自動檢查每個微應用註冊的 activeRule 規則,符合規則的應用將會被自動激活。本示列分別有一個主應用五個微應用構成,在主應用中增長微應用的配置文件,對註冊微應用作單獨的管理。
主應用 src 文件下增長
registerMicroAppsConfig.ts
,內容以下:
const loader = (loading: boolean) => {
// 此處能夠獲取微應用是否加載成功,能夠用來觸發全局的 loading
console.log("loading", loading);
};
export const Microconfig = [
//name: 微應用的名稱,
//entry: 微應用的入口,
//container: 微應用的容器節點的選擇器或者 Element 實例,
//activeRule: 激活微應用的規則(能夠匹配到微應用的路由),
//loader: 加載微應用的狀態 true | false
{
name: "vue2",
entry: "http://localhost:8001",
container: "#subContainer",
activeRule: "/vue2",
loader,
},
{
name: "vue3",
entry: "http://localhost:8002",
container: "#subContainer",
activeRule: "/vue3",
loader,
},
{
name: "react",
entry: "http://localhost:8003",
container: "#subContainer",
activeRule: "/react",
loader,
},
{
name: "umi",
entry: "http://localhost:8004",
container: "#subContainer",
activeRule: "/umi",
loader,
},
{
name: "purehtml",
entry: "http://127.0.0.1:8005",
container: "#subContainer",
activeRule: "/purehtml",
loader,
},
//angular
{
name: "angular",
entry: "http://127.0.0.1:8006",
container: "#subContainer",
activeRule: "/angular",
loader,
},
];
複製代碼
主應用入口文件引入(主應用使用的 umi,因此直接在 pages/index.tsx 引入)
import LayoutPage from "@/layout/index";
import {
registerMicroApps,
start,
addGlobalUncaughtErrorHandler,
} from "qiankun";
import { Microconfig } from "@/registerMicroAppsConfig";
// 註冊微應用
registerMicroApps(Microconfig, {
// qiankun 生命週期鉤子 - 微應用加載前
beforeLoad: (app: any) => {
console.log("before load", app.name);
return Promise.resolve();
},
// qiankun 生命週期鉤子 - 微應用掛載後
afterMount: (app: any) => {
console.log("after mount", app.name);
return Promise.resolve();
},
});
// 啓動 qiankun
start();
export default function IndexPage({ children }: any) {
return (
<LayoutPage> <div>{children}</div> {/* 增長容器,用於顯示微應用 */} <div id="subContainer"></div> </LayoutPage>
);
}
複製代碼
// 添加全局異常捕獲
addGlobalUncaughtErrorHandler((handler) => {
console.log("異常捕獲", handler);
});
複製代碼
ShadowDOM
)start({
prefetch: true, // 開啓預加載
sandbox: {
experimentalStyleIsolation: true, // 開啓沙箱模式,實驗性方案
},
});
複製代碼
import { setDefaultMountApp } from "qiankun"
setDefaultMountApp('/purehtml');
複製代碼
注意微應用的名稱
package.json
=>name
須要和主應用中註冊時的name
相對應,且必須確保惟一。
# 安裝 vueCli
$ yarn add @vue/cli
# 建立項目
$ vue create vue2.x_root
# 選擇 vue2 版本
# 安裝依賴
$ yarn
# 啓動
$ yarn serve
複製代碼
src
目錄新增 public-path.js
:if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
複製代碼
main.js
修改import "./public-path";
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import routes from "./router";
Vue.config.productionTip = false;
let router = null;
let instance = null;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
// 注意這裏的name,最好不要寫死,直接使用主應用傳過來的name
base: window.__POWERED_BY_QIANKUN__ ? `${props.name}` : "/",
mode: "history",
routes,
});
Vue.use(VueRouter);
instance = new Vue({
router,
render: (h) => h(App),
}).$mount(container ? container.querySelector("#app") : "#app");
}
// 獨立運行時
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log("[vue2] vue app bootstraped");
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = "";
instance = null;
router = null;
}
複製代碼
vue.config.js
):const path = require("path");
const { name } = require("./package");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
filenameHashing: true,
lintOnSave: process.env.NODE * ENV !== "production",
runtimeCompiler: true,
productionSourceMap: false,
devServer: {
hot: true,
disableHostCheck: true,
// 修改默認端口,和註冊時一直
port: 8001,
overlay: {
warnings: false,
errors: true,
},
// 解決主應用加載子應用出現跨域問題
headers: {
"Access-Control-Allow-Origin": "*",
},
},
// 自定義 webpack 配置
configureWebpack: {
resolve: {
alias: {
"@": resolve("src"),
},
},
// 讓主應用能正確識別微應用暴露出來的一些信息
output: {
library: `${name}-[name]`,
libraryTarget: "umd", // 把子應用打包成 umd 庫格式
jsonpFunction: `webpackJsonp*${name}`,
},
},
};
複製代碼
# 安裝 vueCli
$ yarn add @vue/cli
# 建立項目
$ vue create vue3.x_root
# 選擇 vue3 版本
# 安裝依賴
$ yarn
# 啓動
$ yarn serve
複製代碼
src
目錄新增 public-path.js
:if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
複製代碼
main.ts
修改//@ts-nocheck
import './public-path';
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';
let router = null;
let instance = null;
let history = null;
function render(props = {}) {
const { container } = props;
history = createWebHistory(window.__POWERED_BY_QIANKUN__ ? `${props.name}` : '/');
router = createRouter({
history,
routes,
});
instance = createApp(App);
instance.use(router);
instance.use(store);
instance.mount(container ? container.querySelector('#app') : '#app');
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.unmount();
instance._container.innerHTML = '';
instance = null;
router = null;
history.destroy();
}
複製代碼
vue.config.js
):const path = require('path')
const { name } = require('./package')
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
filenameHashing: true,
lintOnSave: process.env.NODE_ENV !== 'production',
runtimeCompiler: true,
productionSourceMap: false,
devServer: {
hot: true,
disableHostCheck: true,
// 修改默認端口,和註冊時一直
port: 8002,
overlay: {
warnings: false,
errors: true
},
headers: {
'Access-Control-Allow-Origin': '*'
}
},
// 自定義webpack配置
configureWebpack: {
resolve: {
alias: {
'@': resolve('src')
}
},
// 讓主應用能正確識別微應用暴露出來的一些信息
output: {
library: `${name}-[name]`,
libraryTarget: 'umd', // 把子應用打包成 umd 庫格式
jsonpFunction: `webpackJsonp_${name}`
}
}
}
複製代碼
# 建立項目
$ yarn add create-react-app react_root
# 啓動
$ yarn start
複製代碼
src
目錄新增 public-path.js
:if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
複製代碼
剛剛建立的項目沒有路由,因此先要安裝路由
# 路由安裝
$ yarn add react-router react-router-dom
複製代碼
入口文件 index.js 修改,爲了不根 id #root 與其餘的 DOM 衝突,須要限制查找範圍。
import './public-path';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter, Route, Link } from "react-router-dom"
function render(props) {
const { container } = props;
ReactDOM.render(
<BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? '/react' : '/'}> <App/> </BrowserRouter>
, 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'));
}
複製代碼
安裝插件 @rescripts/cli,固然也能夠選擇其餘的插件,例如 react-app-rewired
# 安裝
$ yarn add @rescripts/cli
複製代碼
根目錄增長配置文件
.rescriptsrc.js
,注意必定是根目錄下哦
const { name } = require('./package');
module.exports = {
webpack: (config) => {
config.output.library = `${name}-[name]`;
config.output.libraryTarget = 'umd';
config.output.jsonpFunction = `webpackJsonp_${name}`;
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;
},
};
複製代碼
package.json
配置修改{
"name": "react_root",
"version": "0.1.0",
"private": true,
"dependencies": {
"@rescripts/cli": "^0.0.16",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "5.0",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "set PORT=8003&&rescripts start",
"build": "rescripts build",
"test": "rescripts test",
"eject": "rescripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
複製代碼
umi 項目初始化方式參考初始化主應用的方式。umi 應用使用
@umijs/plugin-qiankun
能夠一鍵開啓微前端模式。
# 安裝 @umijs/plugin-qiankun
$ yarn add @umijs/plugin-qiankun
複製代碼
umirc.ts
若是是配置文件抽離到
config
中,直接修改config.js
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/', component: '@/pages/index' },
],
fastRefresh: {},
//開啓qiankun配置
qiankun:{
slave:{
}
}
});
複製代碼
這裏只是作了簡單的集成配置,更過功能請參看@umijs/plugin-qiankun
非 webpack 應用有個須要注意點的點:接入以前請確保你的項目裏的圖片、音視頻等資源能正常加載,若是這些資源的地址都是完整路徑(例如 qiankun.umijs.org/logo.png),則…
entry
入口<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<body>
<div id="test">測試微應用</div>
</body>
</html>
<!-- entry 入口 -->
<script src="./index.js" entry></script>
複製代碼
const render = ($) => {
// 這裏能夠在渲染以前作些什麼。。。
return Promise.resolve();
};
((global) => {
//purehtml 是對應的微應用名稱
global['purehtml'] = {
bootstrap: () => {
console.log('purehtml bootstrap');
return Promise.resolve();
},
mount: (props) => {
console.log('purehtml mount00000000000',props);
props.onGlobalStateChange((state,prev)=>{
console.log(state,prev)
})
return render($);
},
unmount: () => {
console.log('purehtml unmount');
return Promise.resolve();
},
};
})(window);
複製代碼
http-server
啓動本地服務
根目錄增長
package.json
文件, 注意name
:purehtml
{
"name": "purehtml",
"version": "1.0.0",
"description": "",
"main": "index.html",
"scripts": {
"start": "cross-env PORT=8005 http-server . --cors",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"devDependencies": {
"cross-env": "^7.0.2",
"http-server": "^0.12.1"
}
}
複製代碼
# 安裝 CLI
$ yarn add -g @angular/cli@9.1.12
# 建立項目
$ ng new angular_root
# 啓動
$ ng serve
複製代碼
src
目錄新增 public-path.js
:if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
}
複製代碼
src/app/app-routing.module.ts
文件:import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { APP_BASE_HREF } from '@angular/common';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
// @ts-ignore
providers: [{ provide: APP_BASE_HREF, useValue: window.__POWERED_BY_QIANKUN__ ? '/angular' : '/' }]
})
export class AppRoutingModule { }
複製代碼
import './public-path';
import { enableProdMode, NgModuleRef } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
let app: void | NgModuleRef<AppModule>;
async function render() {
app = await platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap(props: Object) {
console.log(props);
}
export async function mount(props: Object) {
render();
}
export async function unmount(props: Object) {
console.log(props);
// @ts-ignore
app.destroy();
}
複製代碼
根據官方指示:先安裝
@angular-builders/custom-webpack
,注意:angular 9 項目只能安裝 9.x 版本,angular 10 項目能夠安裝最新版。
$ yarn add @angular-builders/custom-webpack@9.2.0
複製代碼
在根目錄增長
custom-webpack.config.js
const appName = require('./package.json').name;
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
output: {
library: `${appName}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${appName}`,
},
};
複製代碼
修改 angular.json 配置文件
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angularRoot": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"outputPath": "dist/angularRoot",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [],
"customWebpackConfig": {
"path": "./custom-webpack.config.js"
}
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "angularRoot:build"
},
"configurations": {
"production": {
"browserTarget": "angularRoot:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angularRoot:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "angularRoot:serve"
},
"configurations": {
"production": {
"devServerTarget": "angularRoot:serve:production"
}
}
}
}
}
},
"defaultProject": "angular"
}
複製代碼
哇咔咔!!! 報錯。。。
解決方式
zoom.js
, 而且在 import qiankun
以前引入src/polyfills.ts
裏面的引入 zone.js
src/index.html
<head>
中引入 zone.js
哇咔咔!!! 又報錯了。。。 什麼鬼,頁面卻是加載出來了,可是報了一串紅
查閱資料,貌似是熱更新的
bug
啊。 這裏不作過多解釋,暴力解決方案:做爲子應用時不使用熱更新
。
package.json
=> script
中增長以下命令:"serve:qiankun": "ng serve --disable-host-check --port 8006 --base-href /angular --live-reload false"
複製代碼
做爲微應用時使用:
ng serve:qiankuan
啓動加載
build 報錯問題: 修改
tsconfig.json
文件
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es5",
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom"]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
複製代碼
多個應用間通訊,這裏舉個簡單的例子:主應用中登陸獲取用戶
id
,當加載微應用時,微應用須要根據不一樣的用戶id
展現不一樣的數據或者展現不一樣的頁面。這個時候就須要主應用中把對應的用戶id
傳到微應用中去。傳值方式,這裏總結了三種方式:
props
傳值initGlobalState
定義全局狀態註冊微應用的基礎配置信息時,增長
props
,傳入微應用須要的信息
{
name: 'vue2',
entry: 'http://localhost:8001',
container: '#subContainer',
activeRule: '/vue2',
//props
props: {
id: 'props基礎傳值方式'
},
loader,
}
複製代碼
微應用中在
mount
生命週期props
中獲取
export async function mount(props) {
console.log('獲取主應用傳值',props)
render(props);
}
複製代碼
定義全局狀態,並返回通訊方法,建議在主應用使用,微應用經過
props
獲取通訊方法。
// 全局狀態
const state = {
id: 'main_主應用',
};
// 初始化 state
const actions: MicroAppStateActions = initGlobalState(state);
// 監聽狀態變動
actions.onGlobalStateChange((state, prev) => {
// state: 變動後的狀態; prev 變動前的狀態
console.log(state, prev);
});
複製代碼
mount
生命週期中獲取export async function mount(props) {
console.log('initGlobalState傳值',props)
render(props);
}
複製代碼
打印出來發現好像並無咱們須要的值:
我想在這裏,細心的同窗應該會發現,好像有個
onGlobalStateChange
,setGlobalState
這兩個方法,見名知意,應該是用來作狀態的監聽和修改使用的。無論什麼神仙,先調用下試試看嘍
封裝一個
storeTest
方法作統一調用
function storeTest(props) {
props.onGlobalStateChange &&
props.onGlobalStateChange(
(value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
true,
);
// 爲了演示效果明顯增長定時器
setTimeout(() =>{
props.setGlobalState &&
props.setGlobalState({
id: `${props.name}_子應用`
});
},3000)
}
複製代碼
export async function mount(props) {
storeTest(props);
render(props);
}
複製代碼
輸出兩次 ???
輸出兩次的緣由是在
微應用
中調用setGlobalState
, 主應用中的onGlobalStateChange
也會執行
initGlobalState
初始化 state
onGlobalStateChange
監聽狀態變動setGlobalState
修改狀態offGlobalStateChange
移除監聽若是想在微應用某個頁面內修改全局狀態應該怎麼作 ? 固然是能夠把
props
中的方法掛載到當前應用的全局上啦。例如:
export async function mount(props) {
storeTest(props);
render(props);
// 掛載到全局 instance 上
instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}
複製代碼
定義全局狀態池,說白了就是在主應用中定義全局狀態,可使用
redux
vuex
等來定義。定義好全局狀態,能夠定義一個全局的類,類中聲明兩個方法,一個用來獲取全局狀態,一個用來修改全局狀態。定義好以後,把這個類經過第一種props
的傳值方式傳入,微應用經過mount
=>props
接收。這種方式就不作演示,我的建議使用第二種方式。
到這裏,基於
qiankun
的微前端搭建基本完成。本文只是對qiankun從0搭建到搭建過程當中遇到問題而且解決問題以及後期項目中的一些基礎配置和使用作簡單概述。下一次將會對多應用部署
問題作個詳細概述。
若是以爲本文對你有幫助,但願可以給我點贊支持一下哦 💪 也能夠關注公衆號:前端開發愛好者 一塊兒學習前端技能