primers

Students who are familiar with the micro front end direction may have seen the documents of Qiankun, and those who are in-depth may also read its code and the source code of Single-SPA. A year ago, I was also influenced by the idea of a micro front end, which happened to be facing a business that was constantly changing and needed to support hot plug and standalone deployment of online functions. After fully investigating the micro front end and Qiankun, I found it was suitable for the current business, so I started to practice the micro front end. Since single-SPA is too simple, we adopted [email protected] as the micro front-end driver. Today, I would like to share with you the problems and solutions encountered during this period of time.

Possible business scenarios

Suppose you are currently maintaining or developing such a project, business changes frequently, page functions are repeated, but the style is consistent, temporarily only on the PC side. Once you get the design, you can split your business into multiple layouts provided by the base (main application). Functionally independent modules are integrated into sub-applications, and each sub-application has a special routerBase.

Kaka cut, have you finished all the tasks, under two or three applications also can online configuration, support hot plug and independent deployment. Great curled her ~

A few days later, the following new business scenarios pop up and you get lost in thought…

Scenario 1: As services change, mobile devices must be supported.

You create a new child application with routerBase set to H5. Automatically jump to/H5 / XXX if it is a mobile terminal. If the PC accesses /h5/ XXX and automatically redirects to/XXX, it can get by, but mobile rendering is slow due to the heavy base, and using the “forward/Back” button on mobile can be confusing due to too much redirection, sometimes rendering the page as PC or not rendering.

Scenario 2: The page is responsive. After you click login on the mobile terminal, the login mode can be shared.

Responsive page is active page, there is activity registration, it requires login state sharing. When a user clicks login on the mobile terminal, the user is redirected to the login page of the mobile terminal. After login, the user is redirected to the active page only when the login is successful. If each child application has a routerBase, it jumps back and forth several times and has to figure out how to share logins.

Scenario 3: The boss requires the same URL on the PC and mobile devices…

RouterBase naturally eliminates this possibility. It just can’t be done!

Scenario 4: The boss asks for a four year old project to be aggregated into a portal site…

Many of the project’s dependencies, especially scaffolding, were severely outdated, locking the level 1 dependencies but not the level 2 versions, causing the build release to fail. Not to add the bootstrap program code/mount/unmount to… !

Qiankun’s “Kun” (Trapped) landscape

The positioning of Qiankun may be a convergence of middle – and back-end projects. Such projects are rarely dependent on each other, and the control of the login state can be done in a pedestal, belonging to multiple series under a pedestal. But when faced with the above scenario, it seems powerless.

In addition, the above scenes also exposed many problems in Qiankun:

  • The base is generally carried by real business applications and provides login functions as well as multiple sets of layouts.
  • The dock is easy to couple with a lot of PC-side UI libraries and feature code;
  • The dock can easily become a gathering place for common data and logic, even though these are not the responsibilities of the dock application;
  • Relying heavily on routerBase, the framework makes judgment easier but sacrifices flexibility.
  • There is insufficient support for coexistence of multiple instances. Currently, only microApp is supported, and routing system is not recommended for such applications.
  • Heavily dependent on life cycle bootstrap/mount/unmount;

The way of broken

@ICATJS/Micro is a new generation of micro front-end framework that I have implemented in the past four months and put into practice in actual projects. It can not only easily cope with the above “dilemma”, but also has other good features. Currently there are only two methods registerSubapps and start. The other thing to be aware of is the configuration of the child application. How did he or she cope with this dilemma? Listen to me share one by one:

End application (or Layout application)

If you look at this new term, don’t assume that there is a mandatory classification of sub-applications. Application A can be considered an “end application” as long as a child application A provides layouts or has paths that are used as layouts and are relied on by other child applications B. A is not the end application, I do not know, it will be normal according to the sub-application load. B will render to the page after A provides a mount point. Let’s take an example

This is the configuration of the end application

{
    "name": "a"."entry": "aaa"."history": "browser"."props": {},
    "rules": [{"rule": "/"."container": "#mountNode"."endType": "pc"}}]Copy the code

As a PC application, the path rule is configured with wildcard (/). In this way, all routes are matched by the application. Of course, the endType is used to determine which end is first, and then to deal with the “dependency chain” of the application. Currently, only one dependency chain is supported under each route because the scenario is relatively simple. Theoretically, it can support multiple dependency chains, that is, multiple chains and instances coexist simultaneously.

This is the configuration of the child application

{
    "name": "b"."entry": "bbb"."history": "browser"."props": {},
    "rootVars": {
      "externals": {
        "@react": "React"."@react-dom": "ReactDOM"."userInfo": "userInfo"}},"rules": [{"rule": "/b/activities/1520"."layout": "a > /layout/headless"."endType": "none"
      },
      {
        "rule": "/b/tec-support"."container": "#mountNode"."endType": "none"
      },
      {
        "rule": "/development"."layout": "a > /layout/basic"."endType": "pc"}}]Copy the code

The first rule depends on /layout/headless of application A, the second rule does not depend on any application, and the third rule depends on /layout/basic of application A.

Don’t configure the path of the container, if it is applied by default is # subappMountNodeWrapper, if is the end applications do not rely on any default is # appMountNodeAndDoNotCover layout. This way, if any of these nodes appear on the page, the child application will render to that node.

As you can see, the activation of a child application depends only on the path rules that follow single-SPA’s activeWhen rules, which can be strings, functions, or arrays. Each path rule has its own Container, endType, and layout. Such a subapplication can be either an end application on the dependency chain or an independent subapplication. Flexible combination based on path rules to adapt to multiple scenarios.

Attention! An end application can also depend on other end applications. You only need to configure the dependent path on the path rule of the end application.

entry

It can be an HTML file path or an array containing multiple JS, CSS, and HTML. When the mount point is initialized, fill it with the contents of the last HTML.

Global routing system

Built-in handle react/ Vue multiple sub-applications are activated at the same time, multiple routing systems conflict. There is no need to configure the routing of the child application into the master application to prevent conflicts, as with Qiankun. Global routing intercepts route changes and distributes the real path and layout path to each child application so that it can render normally. Also, all child applications can have their own separate 404 pages. The child application can be treated as an independent application, without worrying about the default match of the route, and without worrying about the 404 page of the application if the route does not match.

The sandbox

Built-in IFrame sandbox, child application code is run in iframe. In this way, the state of the code will be saved in iframe, so there is no need to provide a snapshot, naturally have snapshot capability. There is also a built-in garbage collection queue that releases iframe when a subapplication is not activated for 5 minutes. Attention! These ifRames are blank Iframes and consume very few rendering resources. However, the framework provides a virtual BOM in the IFrame, so that the results of these word applications can be correctly rendered to the real rendering layer outside the IFrame. Note 2! All manipulation of the DOM by the child application is restricted to the mount point; in other words, document.body points to the mount point rather than the actual body of the rendering layer. This tight control is also present in methods such as getElementById.

Of course, there are other features such as third-party library sharing, global data sharing, component-method-state flow sharing, and caching mechanisms that I won’t go into at first. The official website will be prepared later to fully introduce these features.

Here, let’s sort out the solution to the dilemma:

  • Scenario 1: Mobile devices are required. By removing the dependency of routerBase and supporting end applications, it naturally solves the rendering problems caused by base redirection and jump problems caused by repeated redirection.
  • Scenario 2, the page is responsive to the need to share login state. With the support for layout dependency chains, one end application can centralize the logon logic while the other end application can rely on the functions provided by it. Logic can be distributed to multiple subapplications in a stream sharing mode or global data sharing. Responsive pages belong to a node in the dependency chain and can naturally get the login state in time.
  • Scenario 3: URL consistency. By removing the Dependency of routerBase, the framework determines which terminal is located during initialization and activates different applications. The path rules of the end application can be configured as wildcards/, which makes it easy to ensure consistent urls.
  • Scenario 4, four year old project integration. The framework supports non-lifecycle projects that can be seamlessly rendered into a portal site. Here is a screenshot of my test, if you are interested, you can take a look:

This is the integrated seeconf website for 2018:

This is the official website of integrated Word of mouth:

Has it solved the dilemma of Qiankun?

Because common logic and layout are distributed among layers of “end applications,” the base only needs to reference the framework and obtain and parse the rules to drive the whole site to run. The child application does not have to worry about conflicting routes, but consider a copy in the master application. The base can be thin, with each side loading only the UI libraries or components it needs. For example, if ANTD is used on PC, the mobile terminal can use ANTD-Mobile, and the framework will not load ANTD into the mobile terminal.

What are the shortcomings?

  • It is not recommended that the base have a routing system, so far there has not been a case where base routing conflicts with sub-application routing.
  • Multiple routing system conflicts, currently no Angular support, vUE support may be a bit buggy.
  • Multiple dependency chains are not supported. Currently, only the first dependency chain is processed.
  • For example, var is a global variable defined in eval. Global variables defined by var cannot be correctly mounted to virtual Windows. There may be some project loading errors.
  • Twenty-one routing conflict scenarios are sorted out, with possible exceptions.

Browser compatibility

Mainstream browsers chrome, Safari, Edge, Firefox and other compatible, domestic niche browsers 360, QQ browser and other compatible. Proxy is preferred. If not, Object. DefineProperty is degraded.

Who is using

The tot IoT team is currently working on the Chip Open Community (OCC), a framework created to meet their changing business needs. You can see that the urls on the PC and mobile are the same, but the activated subapplications are different.

I also hope that those of you reading this article will use @ICATJS/Micro framework to make wonderful works at some point in the future!

In response to the feedback of some students, we made a demo, please have a preliminary understanding of the use of this framework.