Hello, I’m Yuko. Recently in my work, I encountered a problem about how to realize the main application and sub-application in the micro front-end. I also consulted relevant information. But in fact, there are a variety of answers on the network, the feeling is not particularly clear after seeing. So I hereby write an article. One is to share it with others so that they don’t have to be like me. Less detours. The second is to record, if they forget later convenient access.

About the concept of micro front end, some partners may be relatively strange. Here is a brief introduction to the micro front end for those who do not understand

What is a micro front end

Getting the front end right is hard, and getting multiple teams working on large front-end applications is even harder. There is a trend towards breaking up front-end applications into smaller, more manageable gadgets. This is called a micro front end. To put it simply, an application relies on a lot of sub-applications, and the sub-applications can be started separately to form an application, which is better to manage the code.

Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. — Micro Frontends

The micro front end is a kind of technical means and method strategy that multiple teams jointly build modern Web applications by releasing functions independently.

The micro front-end architecture has the following core values:

  • Technology stack independent main framework does not limit access to the application stack, microapplications have full autonomy

  • Independent development, independent deployment of micro application warehouse independent, the front and back end can be independently developed, after the deployment of the main framework automatically complete synchronization update

  • The incremental upgrade

    In the face of a variety of complex scenarios, it is usually difficult to upgrade or reconstruct the existing system completely, and the micro front end is a very good means and strategy to implement the gradual reconstruction

  • Independent run time States are isolated between each microapplication and run time states are not shared

The micro front-end architecture is designed to solve the problem of unmaintainable application in a relatively long time span, when a single application evolves from a common application to a Frontend Monolith due to the increase and change of the number of people and teams involved. This type of problem is especially common in enterprise Web applications.

Currently, there are many ways to implement a micro front end. In the project I am doing now, I refer to the scheme of Qiankun.

Qiankun (around)

Qiankun is a single-SPa-based microfront-end implementation library that aims to make it easier and painless to build a production-ready microfront-end architecture system.

Why Not iframe

Why not use iframe? This is the first question that almost any microfront-end solution will be challenged. But most of the micro front-end solutions have abandoned the IFrame solution, naturally for a reason, not to “show off” or deliberately pursue “maverick”.

Iframe is pretty much the perfect microfront-end solution, if you leave aside the experience issues.

The most important feature of iframe is that it provides a browser native hard isolation scheme, no matter the style isolation, JS isolation and other problems can be solved perfectly. However, its biggest problem is that its isolation can not be broken, leading to the application context can not be shared, resulting in the development experience, product experience problems.

  1. The URL is not synchronized. The browser refresh iframe URL status is lost, and the back forward button is unavailable.
  2. The UI is not synchronized and the DOM structure is not shared. Imagine a pop-up with a mask layer in the bottom right corner of the iframe, and we want the pop-up to center the browser and automatically center the browser when resize.
  3. The global context is completely isolated and memory variables are not shared. Iframe internal and external system communication, data synchronization and other requirements, the cookie of the main application should be transparently transmitted to the sub-applications with different root domain names to achieve the effect of free registration.
  4. Slow. Each child application entry is a process of browser context reconstruction and resource reloading.

Some problems better solve the problem of (1), some problems we can turn a blind eye (question 4), but some problems we are difficult to solve the problem of (3) even unable to solve the problem of (2), and these can’t solve the problem it will bring very serious to product experience problems, finally lead us to abandon the iframe solution.

The main application sub-application communication was realized in Qiankun

Here is an example of a scenario that requires inter-application communication

The red box is the primary application and the green box is the child application. When I want to switch routes by clicking version, I close the sidebar. The control sidebar shows hidden code in the main application, and click-version-to-route switching code in the child application. This is where the communication between the master and child applications comes in.

There are many ways to communicate between main applications and sub-applications. Here, I would like to talk about two ways. One is the mainstream framework of the market. For example react,vue. The second is the internal framework of Bigfish to implement the communication between main application and sub-application

React vue Implements application communication

InitGlobalState returns a MicroAppStateActions object with three properties:

  • onGlobalStateChange: (callback: OnGlobalStateChangeCallback, fireImmediately? : boolean) => voidFireImmediately = true Triggers a callback
  • setGlobalState: (state: Record<string, any>) => boolean, set the global status according to the level 1 attribute. Only the existing level 1 attribute can be modified in the micro application
  • offGlobalStateChange: () => booleanTo remove status listening for the current application, which is called by default when the microapplication is umount

What does the parent application do

import { initGlobalState } from 'qiankun'; // Initializing communication pool const actions = initGlobalState(state); / / to monitor communications pool actions change onGlobalStateChange ((state, prev) = > {/ / state: changed status; Prev Status before change console.log(state, prev); }); Copy the codeCopy the code

How does a child application do that

1. Create action. Js

Function emptyAction() {"Current execute action is empty!" ); } class Actions {// default is emptyAction Actions = {onGlobalStateChange: emptyAction, setGlobalState: emptyAction,}; /** * setActions */ setActions(actions) {this.actions = actions; } / * * * * / onGlobalStateChange mapping () {return this. Actions. OnGlobalStateChange (... arguments); } / * * * * / setGlobalState mapping () {return this. Actions. SetGlobalState (... arguments); } } const actions = new Actions(); export default actions; Copy the codeCopy the code

2. In the main.js mount method, accept the props of the parent application

import action from './qiankun/action' export async function mount(props) { console.log('[vue] props from main framework', props); action.setActions(props) render(props); } Duplicate codeCopy the code

3. Reference action.js where you need to receive arguments passed by the parent application

import action from '@/qiankun/action' export default { name: 'Home', mounted () {/ / receiving state action. OnGlobalStateChange ((state) = > {the console. The log (state)}, true); }, methods:{changeValue(){// Modify state action.setGlobalState({ABC :789})}}} copy codeCopy the code

The child application can modify the communication pool, and the modification will be monitored by the master application.

React vue

This is the same method I used in BigFish,react and Vue. It just hangs the method on the window and has a global function

The second method is relatively simple. In the main application file, attach the method to the window. In this way, the application can retrieve the desired properties and methods from the window

First, let’s save the state of the control sidebar from the previous example to Redux for component communication

Then, in the main.js file of the main application, you will modify the methods in the sidebar. Hang on to the global function

Next, the easiest step. Where does the child application need to use, just go to window

At this point, application communication is complete. Of course, since we are a micro front end project, sub-applications can be launched separately. So make a judgment call. Avoid if the launcher is applied separately. An error is reported when there is no corresponding function.

Bigfish implements application communication

Use with useModel (recommended)

Ensure that @umijs/plugin-model or @umijs/preset- React is installed

  1. The main application uses either of the following methods to pass through data:
  1. If you are using the MicroApp component mode to consume microapplications, the data is passed just as the react component communicates with functions:

    function MyPage() {
      const [name, setName] = useState(null);
      return (
        <MicroApp name={name} onNameChange={(newName) => setName(newName)} />
      );
    }
    Copy the code
  1. If you are using a route-bound consumer microapplication, you need to export the useQiankunStateForSlave function in SRC /app.ts. The return value of the function will be passed as props to the microapplication, as follows:

    // src/app.ts
    export function useQiankunStateForSlave() {
      const [masterState, setMasterState] = useState({});
    
      return {
        masterState,
        setMasterState,
      };
    }
    Copy the code
  1. A global model is automatically generated in a microapplication, and the props of the main application can be obtained from any component.

    import { useModel } from '@alipay/bigfish';
    
    function MyPage() {
      const masterProps = useModel('@@qiankunStateFromMaster');
      return <div>{JSON.stringify(masterProps)}</div>;
    }
    Copy the code

    Alternatively, the higher-order connectMaster component can be used to obtain the props of the main application passthrough

    import { connectMaster } from '@alipay/bigfish';
    
    function MyPage(props) {
      return <div>{JSON.stringify(props)}</div>;
    }
    
    export default connectMaster(MyPage);
    Copy the code
  1. and&lt; MicroApp /&gt;When used together with, an additional setLoading property is passed to the child application, which is executed at an appropriate time in the child applicationmasterProps.setLoading(false), you can mark the loading state of the micro-module as complete.

Pass based on props

React is similar to the communication between components

  1. When configuring apps in the main application, pass the data as props

    // src/app.js
    
    export const qiankun = fetch('/config').then((config) => {
      return {
        apps: [
          {
            name: 'app1',
            entry: '//localhost:2222',
            props: {
              onClick: (event) => console.log(event),
              name: 'xx',
              age: 1,
            },
          },
        ],
      };
    });
    Copy the code
  1. The child application gets the PROPS consumption data in the lifecycle hook

At this point, the qiankun application communication is over. If there is anything do not understand words have the mistake. Feel free to point it out in the comments

References:

Bigfish.antfin-inc.com/doc/plugin-… Juejin. Cn/post / 704929…