The practice of micro-front-end has attracted more and more attention, and it has great application value on the platform of integrated resources. The newly added needs only need to add sub-applications, without managing bulky, coupled single applications. The unrestricted technology stack also makes it easier to retrofit aging micro-front-end projects. A description of microfront-end concepts and application value can be read in this translation.

single-spa

With single-SPA, the child application needs to throw the life cycle, and the main application dynamically mounts and unmounts the app according to the change of Location to realize the switch of the child application.

Single-spa hijacks the location change event to ensure that the child app’s mount operation is completed, and the child app’s routing system takes over the URL change event.

What did Qiankun do on the basis of single-SPA

html-entry

How do I load static resources for a child application, one way to do this is with JS-Entry

Since the js file name is different each time you pack it, the common practice in the community is to output a manifest.json file in the generated file with the webpack plugin stats-webpack-plugin. You also need to change the packaging so that CSS is not a static file on its own, but in JS at the same time.

  plugins: [
    new StatsPlugin('manifest.json', {
      chunkModules: true.exclude: [/node_modules[\\\/]react/"})"Copy the code

This manifest.json is then requested via Ajax to get the name and path of the static resource to be loaded in assets

See implementing Vue-single-SPA here for a full demo

Qiankun kept this JS Entry approach

registerMicroApps([{
    name:'subApp1'.entry: {html: ' '.scripts: ['//abc.alipay.com/index.js'].css: ['//abc.alipay.com/index.css']}}])Copy the code

HTML Entry can also be used. The author encapsulates the implementation of HTML Entry in import-html-Entry

registerMicroApps([
    name:'subApp1'.entry: '//abc.alipay.com/index.html'
])
Copy the code

The child application needs to be packaged in UMD format, which enables the code to run in both Node and browser environments. Name is the name of the subapplication in package.json.

 configureWebpack:{
     output: {
      // Package the child application into the UMD library format
      library: `${name}-[name]`.libraryTarget: 'umd'.jsonpFunction: `webpackJsonp_${name}`,}}Copy the code

Finally, the packaged file window variable will be marked with the sub-application, the main application loads the sub-application, and global export in UMD is used to obtain the export of the sub-application.

Style isolation and JS isolation

“The browser reconstructs CSSOM for all stylesheet insertions and removers to insert and unload styles. In HTML Entry mode, the HTML structure is removed after the application is uninstalled, and the style sheet is automatically removed. “This solves the problem of style interaction between sub-applications.

To isolate global variables between sub-applications, Qiankun used Proxy to create a JS sandbox that would save snapshots of global variables during bootstrap and mount, and then revert to the previous state when switching applications.

Parent-child component communication

The props parameter is provided in the registerApplication, and the child application can obtain the props value during the lifecycle

export async function mount(props) {
  console.log('props from main framework', props);
  render();
}
Copy the code

The author has a shallow understanding of the implementation principle and source code. For more details about the implementation principle of Qiankun, please refer to this article by the author: It is probably the most complete micro front-end solution you have ever seen and the source code of Qiankun.

Modifications to Qiankun Demo

Qiankun provided React, Vue and Angular demos. As the current technology stack is basically Vue, I took out the main application and sub-application as Vue demos, and made some modifications according to some problems in actual use. The demo address is here.

The modification of publicPath

Some static resources under Public could not be loaded after the uE-CLI re-built project was connected to Qiankun. This configuration did not take effect in VUE.

if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
Copy the code

When discovering issues in vue-CLI, modify the publicPath in the vue.config.js file in the demo to make resources accessible to the public in the development mode.

publicPath:'//localhost:7101'
Copy the code

Vue-router access of the primary application and sub-application

In practical applications, both the master application and the child application need routing. When the master application switches the child application using window.history.pushState, it can be hijacked by the micro-front-end framework to mount the child application.

<template> <div class="menu" @click="goto('vue app1', '/demo1')"> { goto(title, href) { window.history.pushState({}, title, href); } } </script>Copy the code

Considering that one of the portal subapplications might have a common sidebar section, a handle was added to the main application to customize the content.

const routes = [
  {
    path: '/demo1*'.name: 'demo1'.component: (a)= > import(/* webpackChunkName: "about" */ '.. /components/demo1')},]Copy the code

There is no special route processing in the child application. You need to set historyApiFallback in devServer to true to avoid 404 when the route is refreshed. The part that the micro-front-end framework takes care of for us during route switching is ensuring that the router of the child application is executed after the child application mounts.

Parent-child application communication

The method of communication between the master application and its sub-applications is provided in Qiankun, but more processing is needed to achieve the sub-application to obtain the dynamic content of the master application. Vuex is used to dynamically obtain data from the main application. The MSG passed is as follows:

let msg = {
  data: {
    userInfo: store.state.userInfo,
    fns: [function getMicro(){
        return store.state.micro
       }
    ]
  }
};
Copy the code

Mount the method globally in the child application, and then use this.$getMicro to dynamically retrieve the parent application’s data. If there is a need to communicate between sub-applications, the sub-application can emit events to the main application and then send them to the other sub-applications.

export async function mount(props) {
  console.log(props.data.userInfo)
  Array.isArray(props.data.fns) && props.data.fns.map(i= > {
    console.log(i)
    Vue.prototype[` $${i.name}`] = i
  });
  render();
}
Copy the code

More on resource transfer between parent and child, and data transfer from child to parent, a demo is given in WL-Micro-Frontends.

As for the communication between sub-applications, there is no good practice yet. A legend is given in the micro-front-end architecture to achieve communication through the main application.

Processing in IE

The demo of Qiankun could not be displayed normally under IE11. In the demo, she tried to close jsSandbox and added Pollyfill to fetch, so that the interface under IE could be displayed normally, but the JS isolation function was also closed.

Ant financial’s platform using Qiankun is not compatible with Internet Explorer and will prompt users to open it in another browser.

Rapid scaffolding

Considering that there may be many sub-applications in actual use, vuE-CLI3 plug-in can be used to quickly build and access the sub-application and parent application of Qiankun. Referring to vuE-CLI-plugin-Qiankun’s fast access, I also made two scaffolding plug-ins and included the modifications to the demo. To build a project similar to the demo above, only the following operations are required:

Main application generation mode

vue create portal
cd portal
vue add vue-cli-plugin-qiankun-portal
Copy the code

Subapplication generation mode

vue create demo1
cd demo1
vue add vue-cli-plugin-qiankun-microapp
Copy the code

Enter the port in the given prompt, for example: 7101.

Respectively NPM I, NPM run serve after the start of the demo project.

Unresolved issues

1. The way of communication between sub-applications. How can sub-applications obtain data updates from the main application without manually calling methods

2. DevTools cannot debug the content of the child application if the master application and child application are debugged together

other

If you are using Nuxt for your main application and sub-application, Nuxt access qiankun’s solution community has a team working on it, please refer to NuxT-Micro-Frontend.

Refer to articles and projects

Probably the most complete microfront-end solution you’ve ever seen

Implementation of standard microfront-end architecture in Ant

Microfront-end architecture

vue-cli-plugin-qiankun

wl-micro-frontends