Micro Frontend

2022-07-17  本文已影响0人  张Piers

[toc]

1. What Is MFE(Micro Frontend)

When I first heard the concept of Micro Frontend, it made me feel it's a Buzzword, like Microservices.But as the pace of usage of that, I knew that's a powerful architecture in our daily development

The term Micro Frontends first came up in ThoughtWorks Technology Radar at the end of 2016.

The Micro Frontends official website defines the concept of micro frontends:

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

translate to Chinese:

构建一个现代web应用所需的技术、策略和方法,具备多个团队独立开发、部署的特性

translate to human language:

We can learn that the concept of micro frontends is extended from the concept of microservices . It abandons the large-scale monolithic approach and decomposes the front-end as a whole into small and simple blocks. These blocks can be independently developed, tested and deployed , while still Aggregate as a product to appear in front of customers. It can be understood that micro-frontend is an architectural style that aggregates multiple small front-end applications that can be delivered independently into a whole.

A few points worth noting:

2. From Monolithic Frontend to Micro Frontend

2.1 Monolithic Frontend Structure

As you can see, from the traditional Monolith structure to Microserve structure. Each Microservices in the backend operates independently of each other, each team can have its own deployment and development technology, communication can be achieved through various API interfaces, and various services can be connected to the frontend only by HTTP request.
Under such a structure, the frontend team's code still coexists in a Monolithic structure. When the website functions become more complex and the team grows stronger, the entire frontend structure will become more and more difficult to maintain, not to mention the advanced technology With each passing day, it is easy to generate legacy code, and if you want to update it, it will be troublesome.

2.2 Micro Frontend Structure

As someone slowly realized this kind of problem, the idea of Micro Frontends was put forward:


It is not difficult to find from the figure that Frontend's modules are divided into various teams, each team independently manages its own front-end and back-end services, has its own deployment environment and tech stack, low coupling between teams, and high cohesion among teams.
In addition, the front-end modules produced by each team must be able to be effectively "collaged" in the same SPA page, so that the user experience of the product is consistent with the original SPA.

2.3 The core idea of Micro Frontend

3. Pain points to implement Micro Frontend(how to)

3.1 Isolation

3.1.1 JS Isolation

Each Micro frontend has its own variables and functions, but when they are embed into portal, these variables and functions might conflict with portal. So we need a JS sandbox with individual scope to isolate each micro frontend. There are 2 classical approches to resolve this:

  active() {
    if (this.sandboxRunning) {
      return;
    }


    this.windowSnapshot = {} as Window;
    // iter will traverse target object, and then call the callback
    // recording current window snapshot
    iter(window, prop => {
      this.windowSnapshot[prop] = window[prop];
    });

    Object.keys(this.modifyPropsMap).forEach((p: any) => {
      window[p] = this.modifyPropsMap[p];
    });

    this.sandboxRunning = true;
  }

  inactive() {
    this.modifyPropsMap = {};

    iter(window, prop => {
      if (window[prop] !== this.windowSnapshot[prop]) {
        // recover the window
        this.modifyPropsMap[prop] = window[prop];
        window[prop] = this.windowSnapshot[prop];
      }
    });

    this.sandboxRunning = false;
  }

3.1.2 CSS Isolation

Same as JS isolation, class names of ids of css in each micro frontend may be conflict.

3.2 Low Coupling(how to load common dependencies)

3.3 Version Control

3.4 Communication

3.5 Hijack Route

3.6 etc...

4. Workaround of Micro frontend

4.1 iframe

In the module of the Team product, the other two modules can be loaded by embedding the iframe. Since the iframe has the characteristic of isolating the running environment, the modules of each team will not interfere with each other. Under the domain, we can use window.postMessage.

<body> 
    <!-- in Team Product --> 
    <iframe width="100%" height="200" src="https://microfrontends-checkout.com/"></iframe> 
    <iframe width="100%" height="200" src="https://microfrontends-inspire.com/"></iframe> 
</body>

Disadvantages:

There are many disadvantages of using iframe.
For example: because the application modules are separated, the shared dependent modules cannot be taken out, resulting in the page may be loaded at the same time. code; in addition, the presentation of the UI will become difficult to control, and if it also contains functions such as forms, it will be even more troublesome.

And iframe only resolve the isolation issue, if we do create a micro frontend, we might also need to pay more effort.

4.2 Web component

The same as iframe, web component is born with the js and css isolation, but it can not be compatible with all browsers. Moreover, when facing high complex componet or system, I think web component cannot handle this easily.

4.3 Single-SPA/Qiankun

Regarding single-SPA, it's only a scheduling of child application lifecycle. It only do 2 things:

single-SPA hopes main application would be very very simple and lite, only need a index.html and a main.js is enough. Even webpack it doesn't require

5. Module Federation

Multiple separate builds should form a single application. These separate builds should not have dependencies between each other, so they can be developed and deployed individually. This is often known as Micro-Frontends, but is not limited to that.

// todo pic MF的图 host remote

const HtmlWebpackPlugin = require("html-webpack-plugin"); 
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin"); 
module.exports = { 
// 其他webpack配置... 
    plugins: [ 
        new ModuleFederationPlugin({ 
            name: 'empBase', 
            library: { type: 'var', name: 'empBase' }, 
            filename: 'emp.js', 
            remotes: { 
                app_two: "app_two_remote", 
                app_three: "app_three_remote" 
            }, 
            exposes: { 
                './Component1': 'src/components/Component1', 
                './Component2': 'src/components/Component2', 
            }, 
            shared: ["react", "react-dom","react-router-dom"] 
        }) 
    ] 
}
字段名 类型 含义
name string 必传值,即输出的模块名,被远程引用时路径为${name}/${expose}
library object 声明全局变量的方式,name为umd的name
filename string 构建输出的文件名
remotes object 远程引用的应用名及其别名的映射,使用时以key值作为name
exposes object 被远程引用时可暴露的资源路径及其别名
shared object 与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖
上一篇下一篇

猜你喜欢

热点阅读