“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!
Hello everyone, I am the front end of the small dish chicken dish chicken peck, if you like my article, remember to give me a thumbs up 💪
Introduce qiankun
Before we officially introduce Qiankun, we need to know that Qiankun is a single spa based micro front-end implementation library designed to make it easier and painless to build production-usable micro front-end architecture systems.
The concept of micro front end refers to the micro service from the back end, which is mainly put forward to solve the difficulties of change, maintenance, extension and other aspects of large-scale engineering. The current mainstream micro front-end solutions include the following:
- iframe
- The base mode, which is mainly based on route distribution, qiankun and Single-SPA are based on this mode
- Modular integration, in which components are built individually and loaded on demand, is similar to an NPM package
- EMP, mainly based on Webpack5 Module Federation
- Web Components
Strictly speaking, none of these solutions is a complete micro front end solution, but they are designed to address the problems associated with the runtime container in the micro front end.
In this article, we mainly introduce the base mode based on the Qiankun. The idea is to break up a large application into smaller, simpler microapplications that can be independently developed, tested, and deployed, and then switch applications by a base application based on routing.
The core design concept of Qiankun
-
🥄 simple
Because the main application and micro-applications can be stack independent, Qiankun is just a library like jQuery for users. You need to call a few of qiankun’s apis to complete the micro-front-end transformation of your application. Also, thanks to the HTML entry and sandbox design in Qiankun, micro-application access is as easy as using iframe.
-
🍡 decoupled/technology stack independent
The core goal of the Micro front is to break boulders down into loosely coupled micro-applications that can be autonomous, and Many of The designs at Qiankun are in line with this principle, such as HTML entry, sandbox, and inter-app communication. Only in this way can we ensure that microapplications are truly capable of independent development and independent operation.
features
- 📦 is based on a single-SPA package that provides a more out-of-the-box API.
- 📱 stack independent, any stack application can use/access, whether React/Vue/Angular/JQuery or other frameworks.
- 💪 HTML Entry access allows you to access microapps as easily as using an iframe.
- 🛡 Style isolation ensures that styles between microapplications do not interfere with each other.
- 🧳 JS sandbox to ensure that global variables/events between microapplications do not conflict.
- ⚡️ Resource preloading: The browser preloads unused micro-application resources in idle time to speed up the opening of micro-applications.
- 🔌 Umi plugin provides @umijs/ plugin-Qiankun for UMI applications to switch to a micro front-end architecture system with one click.
The project of actual combat
This article is for those new to Qiankun. It describes how to build an Qiankun project from 0. The project mainly consists of the following components:
-
Main application:
- @umijs/plugin-qiankun (@umijs/plugin-qiankun
-
Vue Micro application:
- Created using vue2.x
- Use vue3. X, not built with Vite, visual vite is not compatible
-
React Micro app:
- Create using create-react-app
-
Umi3 micro application:
- Use umi3. Combine the plugin @umijs/plugin-qiankun
-
Microapplications built without WebPack:
- Some non-WebPack built projects, such as jQuery projects, JSP projects, can do this.
- Access before the pictures, audio and video, please ensure that your project resources such as normal load, if the address of these resources are full path (for example qiankun.umijs.org/logo.png), is no problem. If the paths are relative, upload the resources to the server first and use the full path.
-
Angular Micro apps:
- The @angular/[email protected] version used
Set up the main application environment
Officially, the master application has no technical stack, and only needs to provide a container DOM, register the microapplication, and start it. Here we use UMI to initialize.
Initializing & Installing Qiankun
# Project initialization
$ yarn create @umijs/umi-app
# Install dependencies
$ yarn
# start
$ yarn start
# installation qiankun
$ yarn add qiankun
Copy the code
After the basic environment is set up, some menus and routes are added to the main application for the main application page and switching between the main application and micro-application. The page layout and routing configuration will not be introduced here, and the source code will be provided at the end of the article. The general page is as follows:
Register microapplications in the master application
Basic configuration information for registering microapplications. When the browser URL changes, the activeRule rules registered for each microapplication are automatically checked, and those that match the rules are automatically activated. This list is composed of one master application and five microapplications. The micro application profile is added to the master application and the registered micro application is managed separately.
Register the micro application basic configuration
Main application under the SRC file increase registerMicroAppsConfig ts, content is as follows:
const loader = (loading: boolean) = > {
// Here you can obtain whether the microapplication is loaded successfully, which can be used to trigger global loading
console.log("loading", loading);
};
export const Microconfig = [
//name: name of the microapplication,
//entry: micro application entry,
Container: a microapplication's container node selector or Element instance,
//activeRule: rules that activate the microapplication (routes to the microapplication can be matched),
Micro / / loader: load the application state of 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,
},
];
Copy the code
Main application entry file import (main application uses UMI, so directly import in pages/index.tsx)
import LayoutPage from "@/layout/index";
import {
registerMicroApps,
start,
addGlobalUncaughtErrorHandler,
} from "qiankun";
import { Microconfig } from "@/registerMicroAppsConfig";
// Register the app
registerMicroApps(Microconfig, {
// Qiankun Life cycle hook - micro app before loading
beforeLoad: (app: any) = > {
console.log("before load", app.name);
return Promise.resolve();
},
// Qiankun Life Cycle hook - After the microapp is mounted
afterMount: (app: any) = > {
console.log("after mount", app.name);
return Promise.resolve(); }});/ / start qiankun
start();
export default function IndexPage({ children }: any) {
return (
<LayoutPage>
<div>{children}</div>{/* add containers to display microapplications */}<div id="subContainer"></div>
</LayoutPage>
);
}
Copy the code
Add global exception catching
// Add global exception catching
addGlobalUncaughtErrorHandler((handler) = > {
console.log("Exception catching", handler);
});
Copy the code
Enable preload & sandbox mode
- ⚡️prefetch: enables preloading
- true | ‘all’ | string[] | function
- 🧳sandbox: whether to enable the sandbox
- StrictStyleIsolation Strict mode (
ShadowDOM
) - ExperimentalStyleIsolation experimental scheme, it is recommended to use
- StrictStyleIsolation Strict mode (
start({
prefetch: true.// Start preloading
sandbox: {
experimentalStyleIsolation: true.// Open the sandbox mode, experimental scheme}});Copy the code
Set the default micro application after the main application is started
import { setDefaultMountApp } from "qiankun"
setDefaultMountApp('/purehtml');
Copy the code
Create the corresponding microapplication
Note that the micro application name package.json => name must correspond to the name registered in the main application and must be unique.
Micro application vue2. X
Initialize the
# installation vueCli
$ yarn add @vue/cli
# Create project
$ vue create vue2.x_root
# Select vuE2 version
# Install dependencies
$ yarn
# start
$ yarn serve
Copy the code
Retrofit into microapplications
- in
src
Directory of newpublic-path.js
:
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
- Entrance to the file
main.js
Modify the
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({
// Use the name passed from the main application
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");
}
// Independent runtime
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;
}
Copy the code
- Package configuration modification (
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.// Change the default port, and register all the time
port: 8001.overlay: {
warnings: false.errors: true,},// Solve the cross-domain problem of the master application loader
headers: {
"Access-Control-Allow-Origin": "*",}},// Customize webPack configuration
configureWebpack: {
resolve: {
alias: {
"@": resolve("src"),}},// Let the main application correctly identify some of the information exposed by the micro application
output: {
library: `${name}-[name]`.libraryTarget: "umd".// Package the child application in umD library format
jsonpFunction: `webpackJsonp*${name}`,}}};Copy the code
- Main application view the loading effect
Micro application vue3. X
Initialize the
# installation vueCli
$ yarn add @vue/cli
# Create project
$ vue create vue3.x_root
# Select vue3 version
# Install dependencies
$ yarn
# start
$ yarn serve
Copy the code
Retrofit into microapplications
- in
src
Directory of newpublic-path.js
:
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
- Entrance to the file
main.ts
Modify the
//@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();
}
Copy the code
- Package configuration modification (
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.// Change the default port, and register all the time
port: 8002.overlay: {
warnings: false.errors: true
},
headers: {
'Access-Control-Allow-Origin': The '*'}},// Customize webPack configuration
configureWebpack: {
resolve: {
alias: {
The '@': resolve('src')}},// Let the main application correctly identify some of the information exposed by the micro application
output: {
library: `${name}-[name]`.libraryTarget: 'umd'.// Package the child application in umD library format
jsonpFunction: `webpackJsonp_${name}`}}}Copy the code
- Main application view the loading effect
Micro application the react
Initialize the
# Create project
$ yarn add create-react-app react_root
# start
$ yarn start
Copy the code
Retrofit into microapplications
- in
src
Directory of newpublic-path.js
:
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
- Set the base of the route in history mode:
The project you just created does not have routes, so you need to install them first
# Route installation
$ yarn add react-router react-router-dom
Copy the code
To prevent the root id #root from colliding with other DOM, you need to limit the search scope.
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'));
}
Copy the code
- Webpack configuration modification
Install the plugin @rescripts/cli and choose other plugins such as React-app-rewired
# installation
$ yarn add @rescripts/cli
Copy the code
Add configuration file. Rescriptsrc. js to the root directory
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': The '*'}; config.historyApiFallback =true;
config.hot = false;
config.watchContentBase = false;
config.liveReload = false;
returnconfig; }};Copy the code
package.json
Configuration changes
{
"name": "react_root"."version": "0.1.0 from"."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"]}}Copy the code
- Main application view the loading effect
Micro application umi
For details about how to initialize an UMI project, see initializing an application. Umi apps use @umijs/ plugin-Qiankun to enable micro-front mode with one click.
Enable the way
- Installing a plug-in
# @ umijs installation/plugin - qiankun
$ yarn add @umijs/plugin-qiankun
Copy the code
- Modifying a Configuration File
umirc.ts
If the configuration file is removed to config, modify config.js directly
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',},routes: [{path: '/'.component: '@/pages/index'},].fastRefresh: {},
// Enable the qiankun configuration
qiankun: {slave: {}}});Copy the code
Here is just a simple integration configuration, see @umijs/plugin-qiankun for more features
- Effect of load
Micro applications Non-WebPack applications
Non webpack application has a point of the point to note: please ensure that your project before access pictures, audio and video resources such as normal load, if the address of these resources are full path (for example qiankun.umijs.org/logo.png), then…
- Entry file declaration
entry
The entrance
<! DOCTYPEhtml>
<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">Test microapplication</div>
</body>
</html>
<! -- Entry -->
<script src="./index.js" entry></script>
Copy the code
- index.js
const render = ($) = > {
// Here's what to do before rendering...
return Promise.resolve();
};
((global) = > {
// Purehtml is the name of the corresponding microapplication
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);
Copy the code
- For easy startup and loading, use
http-server
Starting local Services
Add package.json file to the root directory, note 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"}}Copy the code
- Effect of load
Micro application presents
Initialize the
# installation CLI$yarn add -g@angular /[email protected]# Create project
$ ng new angular_root
# start
$ ng serve
Copy the code
Retrofit into microapplications
- in
src
Directory of newpublic-path.js
:
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; }}Copy the code
- Set the base of the route in history mode,
src/app/app-routing.module.ts
File:
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 {}Copy the code
- Modify the entry file, SRC /main.ts
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();
}
Copy the code
- Modify the WebPack configuration
Follow the official instructions: install @angular-builders/custom-webpack first. Note: Only the 9.x version can be installed for Angular 9 projects, and the latest version can be installed for Angular 10 projects.
$yarn add @ presents - builders/[email protected]Copy the code
Add custom-webpack.config.js to the root directory
const appName = require('./package.json').name;
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': The '*',}},output: {
library: `${appName}-[name]`.libraryTarget: 'umd'.jsonpFunction: `webpackJsonp_${appName}`,}};Copy the code
Modify the angular.json configuration file
{
"$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"
}
Copy the code
- Startup attempt load
Waka ka!! Error…
-
The solution
- Installed in the active application
zoom.js
And, inimport qiankun
Before the introduction of - Will be microapplied
src/polyfills.ts
The introduction insidezone.js
- Micro application
src/index.html
<head>
The introduction ofzone.js
- Installed in the active application
- Start again to try to load
Waka ka!! Wrong again… What the hell? The page loads, but it’s red
Look it up. It looks like a hot update bug. Without going into too much detail here, the violent solution: Don’t use hot updates when you’re a subapp.
package.json
= >script
To add the following command:
"serve:qiankun": "ng serve --disable-host-check --port 8006 --base-href /angular --live-reload false"
Copy the code
Use the command ng Serve: Qiankuan to start loading the microapplication
The tsconfig.json file is modified
{
"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}}Copy the code
- Viewing the loading effect
Application to application communication
Multiple applications communicate. Here is a simple example: the main application logs in to get the user ID. When loading the micro application, the micro application needs to display different data or display different pages based on different user IDS. At this point, the main application needs to transfer the corresponding user ID to the micro application. There are three ways to pass values:
- Direct when mounting microapplications
props
The value of initGlobalState
Define global state- Define a global pool of states
Props by value
When registering the basic configuration information of the micro application, add props to pass in the information required by the micro application
{
name: 'vue2'.entry: 'http://localhost:8001'.container: '#subContainer'.activeRule: '/vue2'.//props
props: {
id: 'props基础传值方式'
},
loader,
}
Copy the code
Mount lifecycle props for microapplications
export async function mount(props) {
console.log('Get master application pass',props)
render(props);
}
Copy the code
InitGlobalState (recommended)
Use the props method for the main application. The micro application uses props to get the props method.
- Declare global state in the master application
// Global state
const state = {
id: 'main_ Main application '};// Initialize the state
const actions: MicroAppStateActions = initGlobalState(state);
// Listen for status changes
actions.onGlobalStateChange((state, prev) = > {
// state: indicates the state after the change; Prev Indicates the status before the change
console.log(state, prev);
});
Copy the code
- Microapplications acquire communication, also in
mount
Lifecycle
export async function mount(props) {
console.log('initGlobalState spread value',props)
render(props);
}
Copy the code
Print it out and it doesn’t seem to have the value we need:
I think in this case, if you’re careful, you’ll notice that there are two methods, onGlobalStateChange and setGlobalState, which are used to monitor and modify the state. Whatever it is, why don’t you try it first
Encapsulate a storeTest method for unified calls
function storeTest(props) {
props.onGlobalStateChange &&
props.onGlobalStateChange(
(value, prev) = > console.log(`[onGlobalStateChange - ${props.name}] : `, value, prev),
true,);// Add timer for demonstration effect
setTimeout(() = >{
props.setGlobalState &&
props.setGlobalState({
id: `${props.name}_ subapplication '
});
},3000)}Copy the code
export async function mount(props) {
storeTest(props);
render(props);
}
Copy the code
Output twice??
The reason for output twice is that setGlobalState is called in the microapplication, and onGlobalStateChange in the main application is also executed
- Conclusion under
initGlobalState
Initialize thestate
onGlobalStateChange
Monitoring for state changessetGlobalState
Modify the state ofoffGlobalStateChange
Remove the monitor
- The problem
What should I do if I want to change the global state within a microapplication page? Of course, you can mount the props method to the global of the current application. Such as:
export async function mount(props) {
storeTest(props);
render(props);
// Mount to the global instance
instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}
Copy the code
Define a global pool of states
To define the global state pool is to define the global state in the main application, which can be defined using redux vuex, etc. By defining the global state, you can define a global class. The class declares two methods, one to retrieve the global state and one to modify the global state. After this is defined, pass this class in as the first props. The micro application receives the props via mount=>props. This is not the way to do the presentation. I recommend the second way.
conclusion
At this point, the construction of the micro front end based on Qiankun is almost complete. This article just gives a brief overview of the problems encountered and solved during the construction of Qiankun from 0 to build, as well as some basic configuration and use in the later project. Next time, we will give a detailed overview of the multi-application deployment problem.
The source address
Github.com/xushanpei/q…
The last
If you think this article is helpful to you, I hope to be able to give me support oh 💪 can also follow the public number: front-end development enthusiasts learn front-end skills together