“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:

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
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

  1. insrcDirectory of newpublic-path.js:
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
  1. Entrance to the filemain.jsModify 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
  1. 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
  1. 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

  1. insrcDirectory of newpublic-path.js:
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
  1. Entrance to the filemain.tsModify 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
  1. 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
  1. 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

  1. insrcDirectory of newpublic-path.js:
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code
  1. 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
  1. 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
  1. package.jsonConfiguration 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
  1. 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

  1. Installing a plug-in
# @ umijs installation/plugin - qiankun
$ yarn add @umijs/plugin-qiankun
Copy the code
  1. Modifying a Configuration Fileumirc.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

  1. 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…

  1. Entry file declarationentryThe 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
  1. 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
  1. For easy startup and loading, usehttp-serverStarting 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
  1. 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

  1. insrcDirectory 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
  1. Set the base of the route in history mode,src/app/app-routing.module.tsFile:
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
  1. 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
  1. 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
  1. Startup attempt load

    Waka ka!! Error…

  • The solution

    • Installed in the active applicationzoom.jsAnd, inimport qiankunBefore the introduction of
    • Will be microappliedsrc/polyfills.tsThe introduction insidezone.js
    • Micro applicationsrc/index.html <head>The introduction ofzone.js
  1. 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= >scriptTo 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
  1. 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 microapplicationspropsThe value of
  • initGlobalStateDefine 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.

  1. 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
  1. Microapplications acquire communication, also inmountLifecycle
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

  1. Conclusion under
  • initGlobalStateInitialize thestate
  • onGlobalStateChangeMonitoring for state changes
  • setGlobalStateModify the state of
  • offGlobalStateChangeRemove the monitor
  1. 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