preface

Our business is mainly to do some front-end projects in the middle and background, which has two characteristics: long life cycle and huge amount of code, which brings two problems: backward technology stack and slow compilation and deployment. Although we had made some efforts to build the cache, the compilation time was not ideal in the case of large projects. Therefore, the micro front end should be the only solution.

So we did some research on micro front-end technologies, mainly the two frameworks of Qiankun and Single-SPA. At first, we thought that the Qiankun based on Single-SPA would meet our needs better than single-SPA itself, but after further exploration, we found that the situation was far from as simple as we thought.

Two microfronts

After doing some research, one question has been nagging me: What exactly is a micro front end?

heaven and earth

From the perspective of Qiankun, the micro front end is the “micro application loader”, which mainly solves the problem of how to safely and quickly centralize a number of scattered projects, which can be seen from qiankun’s own points:

All of these features serve the purpose of being a microapplication loader.

single-spa

From the perspective of Single-SPA, the microfront end is a “micromodule loader”. It mainly solves the problem of how to “microservialize” the front end so that applications, components, and logic become shareable microservices. This can be seen from the overview of Single-SPA’s microfront end:

In single-SPA’s view, there are three types of microfront-end: microapplications, microcomponents, and micromodules. In fact, Single-SPA requires that they all be packaged as SystemJS. In other words, they are essentially micromodules.

SystemJS is a runtime Module loading tool. It is a complete replacement for the native ES Module at this stage (browsers do not officially support importMap).

Who is the micro front end?

To discuss this question, we need to think about the differences between the following two points:

  • Microapp loader: The granularity of microapp is application, that is HTML (or main.js), which can only be shared at the application level
  • Micro module loader: the granularity of micro is module, i.e. JS module, which can be shared at the module level

So, the difference is the granularity of microservices, where the granularity of services available is at the application level and single-SPA is at the module level.

So who is the micro front end? The answer is: both. Because they can both split the front end, just at different granularity. But if anyone’s microfront is the ultimate, it’s single-SPA.

But be careful not to go for single-SPA without thinking it’s more extreme. The final choice should be decided according to the future planning of the project and our real needs. We will continue to analyze it below.

Just remember this: what’s right is best.

Impact of service granularity

With the question of “what exactly is that?” out of the way, we have a basic understanding of the universe and single-spa, so what should we choose?

What impact can a micro front end have

The micro front end is attractive because it offers a lot of transformative things that open up a lot of imagination for the front end:

  1. The micro front end can do application integration, which can integrate multiple technology-independent applications together, so as to unify UI and user experience
  2. The micro front end can do module federation, distribute the micro module, and load the micro module dynamically at run time
  3. The micro front end can do dependency sharing. Based on module federation, modules can be fully analyzed at run time and reasonably shared according to requirements

The first point is generally understood as a micro front end, while the second and third points are less well known and less practiced in the community, so I can only give a few examples to broaden my thinking:

Module federal

Managing libraries in the form of NPM packages can sometimes be a headache because users have to go through them all again every time the library is updated: Update library -> project recompile -> project republish, but if our library is released as a micromodule and users use the library by loading modules at run time, then we just need to refresh the browser every time the library is updated

Depend on the Shared

Most of the previous micro-application integration methods, no matter iframe, ICestark, or World, cannot solve the problem of dependence on sharing. The only thing they can do is to use the externals function of the packaging tool to share vendor level, but they cannot share the components and modules inside the micro-application. If you have multiple applications that use common components and modules, it can be cumbersome to either have a copy of each microapplication or maintain it as an NPM package.

In addition, more fatal is externals function weak. Externals essentially allows the packaging tool to skip vendor compilation and instead load vendor at runtime using . The problem here is that there can only be one version of a vendor. In other words, if you want to share dependencies, you can only use the same version; If you don’t have the same version, you can’t share it.

As a practical example, you have two ANTD3 projects, two ANTD4 projects, and one host project. If you use a traditional microfront-end framework, you have only two options:

  1. Host project writing<script src="xxx/antd3.js"/>, 2 ANTD3 projects externals replaced ANTD, and 2 ANTD4 projects are not externals (i.e. antD4 is packaged into the output JS)
  2. Host project writing<script src="xxx/antd4.js"/>, 2 ANTD3 projects are not externals, and 2 ANTD4 projects are externals instead of ANTD

That’s not an extreme micro front end, right? Read on.

Service granularity is microapplication

Service granularity is the microfront-end framework of microapplications, which can only achieve application integration, but not module federation and dependency sharing. But you may ask: the world also supports Webpack5 module federation, so can not do it?

This understanding is problematic, qiankun does not support Webpack5, qiankun actually can not see Webpack5, so the essence of the question here is: what is the relationship between qiankun and Webpack5 module federation?

In fact, universe doesn’t care what technology the microapplication uses, or whether you’re Webpack4 or Webpack5, because it doesn’t see the details inside the microapplication. The reason why Webpack5 can do micro module, is pure micro application of their own credit, with nothing to do with the universe.

Therefore, it should be said that service granularity is the micro-front-end framework of micro-applications. After the federation of Webpack5 modules, the sharing of micro-modules can be realized. The service granularity of the framework itself remains microapplication.

In fact, this has both advantages and disadvantages, and we will discuss it later.

The service granularity is micromodule

The service granularity is the micro-front-end framework of the micro-module. The above three points can be achieved, so our micro-front-end project has a large imagination space.

Back to the micro front end

Based on the above description of service granularity, the micro front end can be expressed as follows: Micro front end = Micro application lifecycle management + module federation (optional)

Where module federation is optional, if implemented, service granularity is micromodule; If not, service granularity is a microapplication.

Microapplication lifecycle management

This is easy to understand, but it provides the ability to parse, mount, unload, lifecycle hooks, and so on. According to the characteristics of different micro-front-end frameworks, there will be CSS isolation, sandbox, Prefetch and other functions.

Module federal

The module federation here does not specifically refer to the module federation of Webpack5, but as long as the distribution and sharing of modules are realized, it can be called “module federation”. There are currently two ways to achieve module federation:

  1. SystemJS
  2. Webpack5 module federation

On the surface, both load modules dynamically at runtime, but there are big differences:

  1. SystemJS dynamically loaded modules must be SystemJS modules or UMD modules; The Webpack5 module federation has no such restrictions.
  2. Module dependencies of SystemJS are determined at run time, that is, throughimportMap; The dependencies of the Webpack5 module federation are determined at compile time, that is, generated at read compile timeremoteEntry.jsTo analyze dependencies.

The webPackage 5 module federation is much easier to use than SystemJS. The only problem is that only Webpackage 5 projects are supported, while SystemJS supports webpackage 4/5.

How to implement a micro front end

According to the above formula, to implement a micro front end is clear, the options are:

The serial number Life cycle management Module federal describe
1 heaven and earth There is no Application of particle size
2 heaven and earth Webpack5 module federation Module granularity, which only supports module federation in Webpack5 projects
3 single-spa There is no Application of particle size
4 single-spa SystemJS Module granularity, commonly used in Webpackage 4 projects
5 single-spa SystemJS + Webpack5 module federation Module granularity, using SystemJS to load the Webpack5 module. That is, Webpack4 project uses SystemJS to load the SystemJS module, and Webpack5 project uses SystemJS to load the Webpack5 module. This allows both new and old projects to be federated

Again, the difference between The Universe and single-spa

Qianqian built on single-SPA to enhance the microapplication integration capability, but abandoned the micromodule capability. Why do that? We need to think about the context in which these two frameworks appear:

** ** ** Ali has a large number of projects in disrepair, and the business side is in urgent need of tools to integrate them quickly and safely. From this point of view, Universe has no requirement for module federation at all, its requirement is only how to integrate projects quickly and safely. So Qiankun wants to do a micro front-end tool.

** Single-SPA: ** Learn the back-end microservices, realize the front-end microservitization, make the application, components and logic become shareable microservices, realize the true sense of micro front-end. So single-SPA wanted to make a game-changer.

I’ve also compiled a diagram to make it easier to understand:

What fits is best

Micro front end is not a silver bullet, think about these issues before doing micro front end transformation:

Afterword.

Back to the beginning, the original intention of our micro front-end transformation was to solve the two problems: backward technology stack and slow compilation and deployment. In fact, objectively we should choose the universe through the above link. However, subjectively, as a person with pursuit, Qiankun really cannot achieve the extreme micro front end at present, so we tried single-SPA, but found that single-SPA had too much transformation to the project, which brought severe challenges to the maintainability of the project.

From the perspective of the micro front-end transformation effect and the maintainability of the project, the current schemes seem to be not ideal, either the transformation effect is not ideal, or the maintainability is poor. As a person who pursues perfection, I chose to give up temporarily.

I think the only perfect solution is to transfer the universe + old project to Webpack5 + new project to use Webpack5, because only in this way can the transformation ideal be achieved and maintainability be guaranteed.

Pay attention to

Here, it is very important to migrate the old project to Webpack5. I believe that everyone’s project is Webpack4 now, and most of our micro front-end in the future will be Webpack4 old projects. The module federation of Webpack5 only supports Webpack5 projects, so if you have 9 old projects and 2 new projects, if you don’t do the migration of the old project, then your module federation can only be used for the 2 new projects, which is not meaningful.

But what if old projects just can’t migrate to Webpack5? The only solution is to use SystemJS, but single-SPA +SystemJS is too cumbersome to use, too expensive to maintain, and too difficult. In this case, a new framework based on Single-SPA +SystemJS would probably do.