Front-end early chat conference, a new starting point for front-end growth, jointly held with the Nuggets. Add wechat Codingdreamer into the conference exclusive micro front group, to win at the new starting line.
The 14th | front-end growth promotion, 8-29 will be broadcast live, 9 lecturer (ant gold suit/tax friends, etc.), point I get on the bus 👉 (registration address) :
The text is as follows
This is the front end early chat 39, the seventh micro front end, from the front end team of Taobao – Kun Chen’s share – brief summary of the speech version (complete version including the demo please see the video and PPT) :
One, foreword
Hello, everyone. I am Kun Chen from the front end team of Taobao. I am mainly responsible for the construction of the backstage architecture system of Taobao Department. My main topic today is “How to design a Micro front end solution in a large application Architecture”.
Ii. Content introduction
The core will be introduced in four parts:
1. First of all, I will briefly introduce the concept of micro front end. Today is a special session of micro front end. 2. Based on the internal business background of Amoy, including the needs of the community, I will introduce how to design a set of micro front-end architecture 3. The third part will talk about what the micro front end needs to be capable of, including some of our design concepts and thinking. 4. I will conclude with an introduction to the current value of the micro front-end solution to the business and the typical business scenarios it can cover.
2.1. Micro front end concept
The microfront was first proposed as a technology radar by ThoughtWorks back in 2016, and it was born out of the concept of back-end microservices. In the past, a single Web application was generally handled by a team, including the front-end and back-end parts. With the development of technology and the division of responsibilities more specific to the field, the responsible team of a project will be divided into front-end team and back-end team. Backend capability in this scenario, it’s actually aggregated.
With the emergence of the concept of microservices, the back-end will split some capabilities of the back-end according to the functional dimension, and then set an aggregation layer in the middle layer during the interaction, such as ** **graphQL or rely on some BFF layers to do data aggregation, including some gateway processing.
As an architecture similar to microservice, the micro front end actually applies the concept of microservice to the browser side. We split a single front-end Web application according to functional dimensions, and then aggregate it into an overall application architecture. Here is the concept of the micro front end.
2.2 Business Background
What kind of scenario would require such a technical architecture? There are two main scenarios:
- The first scenario is a workbench scenario based on the latitude of product experience
- The second scenario is large single application, which is more focused on optimization from the technical dimension
Workbench scenario actually refers to the fact that there are many system platforms in some companies, and the daily operation process involves cross-system operation, so there will be inconsistent experience and interaction between different systems, and some unnecessary page jumps will also lead to low operation efficiency.
Moreover, there will be a lot of duplication in multi-independent systems, whether in the BFF layer or some intermediate gateway processing layer, or some basic capabilities of the front end. Many systems are independent of each other, and most of them are actually unable to control their specific implementation logic. From the perspective of a whole product, repeated construction and uncontrollable situations are undoubtedly unacceptable.
The second scenario is a little bit more common, the large monolithic applications that we usually talk about are the monolith applications. The characteristics of this kind of application are obvious, its system volume is very large. For example, if you look at the size of the files that bundles build, they can be larger than 10M. This amount of build can seriously affect the development experience and efficiency during daily debugging and development.
Another critical issue is the high cost of development and collaboration for a megalithic application when it comes to functional iterations, or technical architecture upgrades. Because of the large volume, the impact of changes is also very wide. Finally, if there are some requirements and functions of two parties, it is difficult to directly reuse this capability based on the current SPA architecture. Basically, the same code logic needs to be implemented on the existing system.
Based on the above two scenarios, we hope to have an appropriate technical architecture to help businesses build a system with good experience and sustainable maintenance.
2.3. Technology selection
Based on some of the above demands, what are the technical solutions in front of us
2.3.1 Megalithic application
Stonehenge applications are SPA/MPA technical architecture. Here I would like to mention separately that for the product experience scenario, a simple SPA application can certainly give an overall system experience and control the technical complexity of the system. But as the system becomes more and more bloated, you run into the problem of the technical latitude above.
2.3.2, iframe
Iframe was actually a better solution before microfront-end solutions became popular. Whether it’s some kind of two-party or three-party access, it works well. But it has a fatal problem: the user experience. For example, iframes can be very unfriendly in terms of experience dimensions if they are not handled in a special way, such as embedded page double scrollbar problems, route synchronization problems, and some pop-up mask interactions within iframes. User experience problems can be fatal for some products, so we have also rejected the iframe solution.
2.3.3 Framework components
Framework component scenarios, usually in some common head or ceiling logic shared scenarios. Common logic is packaged as a component, which is introduced in the form of an NPM package.
The problems of this approach are obvious. In essence, it does not solve the problems mentioned above, including the upgrading of technical architecture and the optimization of user experience. A generic Layout component, for example, may ensure that the system has a unified interactive visual Layout layer. Although the two systems look the same, they are actually different systems and require jumping across systems.
2.3.4 Advantages and disadvantages of the four schemes
To summarize briefly, each of the four ways has its own advantages and disadvantages. The core of the micro front-end solution is to find a balance between experience and efficiency.
Based on the above investigation and comparison, we finally decided to choose the technical solution of micro front end to upgrade the business architecture.
2.3.5. Micro front-end solution
The above is Amoy internal landing of a micro front-end architecture, more representative of the scene. Because this platform is planned to do a lot of functions, and will output a lot of pages, the scene is more consistent with the large single application we just mentioned, that is, the scene of boulder application. When designing the architecture, we split the whole system according to the functional dimension. For example, according to its entry, account management, including content related ability, data related ability and so on, it is divided into about 20 independent applications, which are unified access to a platform. This actually completes an upgrade based on the micro front-end architecture, making the maintainability of the platform a qualitative improvement.
3. Architecture design
So why can the micro front-end architecture achieve this ability to integrate multiple systems? Next, I will introduce the capabilities and thinking of icestark in the architecture design.
This content is divided into six large First I will introduce the next whole micro front plan what needs to be included in, and we are doing this set of technology solutions the core architecture design concept, will introduce micro behind the front to introduce the core concepts, including the working principle of the micro front end finally is you two of the biggest concerns of technical points: Isolation scheme and micro-module scheme.
3.1. Micro front end scheme
Let’s take a look at what the overall solution of the micro front end involves. This is a big picture of the overall micro front end solution, and our focus today is on the capabilities that ICestark provides. The micro front end ICestark mainly distributes applications based on routing changes, including application lifecycle management, application loading, communication, isolation, and sandbox operation. When the framework application is connected to the micro front end, there is no need to care about the processing related to the micro application. The core only needs to complete the configuration of the micro application. Besides microapplication configuration, it may also involve some authentication logic or application buried point logic and other business practices. Today our core will be breaking down the capabilities provided by the ICestark architecture.
3.2. Design concept
As a micro front-end solution, icestark’s architectural design is based on four concepts.
The first point is that the technology stack doesn’t matter. We don’t care what the technology stack is when a micro application is connected to it. It doesn’t matter if you use React or Vue, or Angular, or even if it’s ancient code (jQuery), the application can be connected. But why is it recommended to unify the stack of a single technology system in practice? It may seem like two contradictory concepts, but actually the idea is that the micro front end can integrate a number of independent systems, or applications, into a single system through the ability to be stack independent. In the process of integration, it is more hoped that it can do some technical unification, rather than not do any control, let it wild growth. Therefore, in the practical process of micro-front-end architecture, we uphold the idea that under a single system, we need to unify the technology. Even if we do not migrate based on cost considerations at present, in the long run, we will definitely gradually converge the technology system.
For example, The technical architecture of Ali Group requires the use of React. If there are some existing Vue systems, they will be integrated into the system, but in the subsequent incremental demand development, they will be gradually upgraded by the React technical system iteratively. In the past, it is necessary to consider the coexistence of multiple technology stacks to do this, but the natural support of the micro-front-end architecture provides a basic guarantee for the smooth migration of the system.
The second design concept is the consistency of development experience. The introduction of a set of micro front-end solutions in today’s technical architecture does not mean that there will be a lot of new concepts to learn, including new syntax, construction logic, and even a change in the overall way of coding, which we do not expect to see. Therefore, one of the core propositions in the design is low-cost or even zero-cost migration, where developers do not need to learn new concepts and processes to stay consistent with the original development logic.
In icestARK, routing is actually a centralized management. All routing information is maintained in the framework application, and routes are distributed and managed according to the changes of routes.
Fourth, independent development deployments, to some extent, reflect the consistency of the development experience mentioned above. Previously, the application was developed and deployed independently, and remains the same as before the micro-front-end architecture was added.
3.3. Core Concepts
Icestark introduces two core concepts: framework applications and microapplications. The framework application is responsible for the overall Layout and micro-application configuration and registration rendering. As you can see from the above figure, the framework application has a general Header, siderBar, in addition to Layout, you also need to configure the micro-application information, such as bundle URL, baseline routing information. Microapplications are applications that are broken down by business dimension, usually a SPA application, and contain at least one to more pages or routes.
3.4. Micro-application registration
This is how framework applications register microapplication information at the code level. In the configuration information, path represents the base route, which states what route address the micro-application will load, and the URL represents the bundle resource of the application. Bundle resources can be of a variety of types. They can be JS resources or contain CSS bundles. In addition to JS and CSS, frameworks like Angular rely heavily on HTML content logic at runtime. We also provide a way to set entry directly to bring in HTML.
3.5. Working principle
3.5.1 track of, process,
First let’s take a look at the overall workflow of incorporating the micro front-end architecture. There are two ways to look at this graph. One is the development pattern of microapplications on the right. Microapplication development has independent warehouse, independent development, testing, deployment process. After the development test is deployed, the release artifacts of the application are registered with the framework application. These artifacts may be JS bundles or HTML resources.
On the left is the overall flow of a framework application, which maintains the micro-application registration information. When a user accesses the system, it can accurately match the application information to be loaded according to the route information registered before, load application resources according to the corresponding information, and finally render the application.
When a user clicks to trigger a redirect, if the route change triggers an internal app redirect, the app will render the page based on the internal app routing logic. If some cross-application hops are involved, it’s back to the route lookup process above.
3.5.2 Routing Rules
We’ll break down some of the core processes in the framework application, starting with a look at how route hijacking works. Route hijacking is an important capability in micro front-end solutions. Without hijacking application routes, it is impossible to determine which application resources need to be loaded and which interface to render.
The routing rules in ICestark are relatively simple. If you are familiar with the React-Router, you will find that there are many similarities between them in configuration. For example, the configuration rules of Path and exact are similar to those of the React-router.
When we visit the framework application page, icestark does a route distribution internally. The first registration message is matched when accessing the/Seller route. The second registration message is matched when accessing /data or /message. What about/Seller /a? As a result, the third route is matched, noting the EXCAT property in the first registration configuration. If you set a microapplication with a path of/in the microapplication architecture, it acts as a bottom-pocket route for the entire system, and any mismatched route configuration will be rendered by the bottom-pocket route. The bottom of the pocket route will be used as the rendering bottom of the landing page, 404 page or exit page in the used scene. In general, it will be a general page, and there will be a strong coupling with the framework application. So in practice above we also use the bottom of the pocket route as a framework to apply its own route rendering.
Why can I complete this route distribution operation? Through a URL change, how is the internal hijacking process, how to determine the need to load is registered which application? This is where our route-hijacking principle comes in.
3.5.3 Route hijacking
Icestark touches two types of routing events: popState and hashChange in the History API, and pushState and replaceState on the window. Both events are triggered when the browser moves forward or backward.
Once a jump occurs between applications, the hijacking of the above events can get the corresponding routing information, and then determine which micro-application to mount according to the route matching.
A micro-application may have multiple route Settings. If there is no inter-application jump, resources will not be loaded again because the current micro-application is matched, and the internal route jump logic decides to render according to the route configuration of the micro-application itself.
If the microapplication configuration of the entire framework application is uninstalled, the hijacked content will be removed and restored to the original state, thus completing the entire application from routing basis to URL change monitoring and then to the microapplication loading process.
3.6. Microapplication loading rendering
How does the microapp actually load and render. That this code is icestark for the application of micro a transformation logic, the transformation cost is not high, only on the core do two things, a mount is application life cycle, load application resources after the completion of execution, the other one is application uninstall life cycle, once the application has changed, will carry out the registration function.
Generally speaking, when we make a SPA application, we don’t need to care about the loading and unloading time. Because the application resources load, they load, and when the application unloads, either the entire application jumps or the entire browser shuts down.
However, in the micro-front-end architecture, it is necessary to know the unloading logic of micro-applications. In the React scenario alone, if the unloading logic is not defined, there may be many cyclic events and functions of component unmount life cycle that cannot be triggered during the micro-application switchover. This has some side effects on the execution of other applications.
So in addition to the core render logic, there’s also the uninstall logic for microapplications. The lifecycle of the registration is coordinated with the logic of resource loading to complete the rendering or switching of the microapplication.
When the micro-application is loaded, it will make a judgment of resource cache. If the resource is not cached, ICestark will conduct resource analysis according to the configuration information registered with the framework application. Generally, resources can be configured in two ways. One is url, which may include JS resources and CSS resources. The other is HTML entry, which involves more resources. There may be separate JS, separate CSS, and even some inline script tags and style tags. Once the resources are loaded, ICestark inserts them into the framework application.
Resources of applications are identified before resource labels are inserted. When switching between micro-applications, you need to know which resources are associated with the application. Therefore, resource labels can be used to correctly find the corresponding resource information. Once you’ve identified it, you finally go to the application’s mount process, which executes the logic in the registered appenter lifecycle. Application uninstallation is relatively simple. Locate all resources to be uninstalled based on the resource id of the application. And execute the functions registered in the registerAppLeave lifecycle, thus completing the entire microapplication uninstallation.
In addition, there is a judgment of resource cache during the loading process of micro-application resources. In some business scenarios, some low-end performance scenarios will be encountered. If you reload resources every time for execution, it will cause a great burden on the performance of the browser.
So we added a resource caching process in between. The loaded resources and executed logic are saved in memory. Every time a cached microapplication is entered, the cached microapplication mount function is executed immediately, which eliminates the process of resource loading and execution. However, there will be a problem in this process, if the micro-application resources are not unloaded, it will actually cause resource pollution, including CSS pollution and JS pollution. So it’s up to the developer to make sure that if the microapplication is cached, it’s up to the developer to properly evaluate whether other incoming microapplications are contaminated.
3.7. Inter-application communication
Next, let’s talk briefly about the application communication scheme. A lot of you were concerned about that.
Is it possible for framework applications to communicate with micro-applications, or micro-applications to micro-applications, or do some event monitoring? In fact, from the micro front end design principle, we do not want to rely too much on the capabilities provided by framework applications or other micro applications for micro applications. There have been some cases where developers want to share functions between applications using heavy logic, such as the common utils logic, through communication between applications. Technically it works, but such a design can have a significant impact on the maintainability of the application.
As we mentioned earlier, every microapplication wants to be independently developed, independently deployed, and independently distributed. If a microapplication relies heavily on external capabilities, you’ll need to mock out a development environment when you’re developing independently, which increases the development experience and costs.
Icestark provides an application communication mechanism, which is recommended to be used more lightly in the actual development process. For example, this communication mechanism only keeps the multilingual Settings of the framework application and the micro-application consistent, and the micro-application can listen when the multilingual Settings change. Another is event communication between applications, where microapplication systems inform framework applications to proactively obtain data. Based on this scenario, we can leverage the ability of application communication to accomplish some lightweight notifications.
3.8. Implementation logic
We provide application communication capabilities in the @ICE/Stark-Data NPM package. The core is actually an EventBus mechanism, which communicates between framework applications and micro-applications, using a global variable like Window as a bridge. In this way, both events and data added by microapplications and those added by framework applications can be accessed.
3.9 micro-front-end isolation
Next, I’ll talk about isolation schemes in ICestark. Before going into the implementation, I’d like to share with you some of icestark’s thoughts when designing isolation solutions. One is that we think the R&D experience is above isolation. If I introduce a perfect isolation scenario, but it requires me to do a lot of extra processing logic, that scenario is definitely not acceptable. Both the transformation cost and the development experience effect will be greatly affected.
Another rule is that two-party scenarios are superior to three-party scenarios. Because most of the microfront-end application scenarios are two-party scenarios, a unified independent system, rarely encounter to be connected to a completely uncontrolled three-party product. The logic and security of access in a two-party scenario are controllable.
Because of these two factors, we don’t necessarily have to implement a perfect isolation solution before we do this. In scenarios where the underlying business needs are met, a simple isolation solution can better allow the business to take the lead.
Back to the isolation scheme, here is mainly divided into two isolation scenarios, one is CSS isolation, the other is JS isolation.
3.9.1 style isolation
Style isolation is more about convention based isolation, using low-cost isolation so that styles do not affect each other.
Style isolation is split into two pieces, one of which is usually the developer’s own style isolation in the business code. The business code isolation recommendation is implemented in the CSSModule, which automatically generates hash suffix style names and is naturally isolated based on the style built for each different application.
The other is base component style isolation. Some of the base components in most communities are designed with style prefixes in mind. The base component can support CSS prefix by adding a prefix to all styles. In practice, the prefix applied by the framework is separated from the prefix applied by the microprefix to complete the style isolation. If there are styles that do not support CSS prefix, we can also use the community’s PostCSS capabilities to give component styles a namespace. Framework applications and micro-applications are styled separately through different namespaces.
Let’s look at the shadow DOM scheme again and see why we didn’t use shadow DOM directly. The essence of the problem is that the shadow DOM scheme is not ready to use out of the box, and we are constantly exploring the experience of shadow DOM in the actual development process. Currently, shadow DOM has some business costs. For example, if you use a component library based on which the pop-up layer, such as Dialog, is not designed to insert structures into the specified DOM node, the pop-up layer will escape your current Shadow DOM. After escaping, it’s just an unstyled popbox. This kind of unstyled frame is not acceptable for business, so the frame logic needs to do some compatibility, and even need to change the underlying components.
Another problem is that in the React scenario, the use of the Shadow DOM involves the event mechanism. The React event mechanism is proxying to the document, but with shadow DOM processing, it may block the event to its host layer. The layer where you render the Shadow DOM. There are packages in the community to do some compatibility, but there are some implementation costs to the business. There are other problems as well. For example CSS @font-face, or some font properties, SVG will have an incompatible scene.
Although there are still many problems with shadow DOM, we will continue to explore this aspect and gradually improve it. At least we can provide an out-of-the-box solution to enable shadow DOM without too much cost.
3.9.2 Script isolation
It is easy to pollute global variables when multiple application bundles are executed multiple times. Icestark implements script isolation through proxy sandbox mechanism.
The basic principle of Prxoy sandbox is to block the direct access to the window in the code in the form of with + new Function, and intercept the access and write to the Window variable in the way of Proxy. The isolation of the sandbox prevents code from directly accessing the Window object. Proxy, a new feature of ES6, can customize the get/set logic, so that some global variable changes on the Window can be taken a snapshot, so that the microapplication can be recovered when switching.
In addition, setTimeout and setInterval will be set on window during the initialization of some applications. If there is no good processing in the uninstallation stage, the execution of the next mounted micro-application will be affected. So in the sandbox for this kind of method special treatment, the corresponding method is hijacked before the sandbox is mounted, at the time of unloading, it is restored.
3.9.3 Tripartite isolation
Finally, tripartite quarantine, the simplest and safest form of quarantine for untrusted three parties is actually iframe. In ICestark, you can simply define the benchmark route path, and then render the iframe related content through the custom render method.
3.10. Micro module
Finally, as a complement to the micro front-end capability, the micro module. Some of the technical solutions, technical architectures and solutions mentioned above are more in the way of loading a micro-application. Its core solution is to connect a single SPA application to the framework application. What about the micro module?
3.10.1 Micro-module three service scenarios
The first scenario is the scenario of multi-module coexistence, for example, a practical requirement, if you need a micro-front-end technical system to achieve a multi-tab scheme. On top of the loaded microapplication, a new TAB page is opened, and the content inside is rendered by a separate bundle resource. What would a lowest-cost solution look like? Should multiple modules be able to render properly in different locations? This is actually a core appeal of the coexistence of multiple modules.
The second scenario is modular construction. A page will have an information module, a form module, and a list module. In some external output reuse scenarios, if the whole page is directly connected, its universality is not particularly strong, but if each module can be freely combined, it can be combined according to the needs of different needs of the page.
The last one is the dynamic rendering module. The content of the page is determined by the data returned by the interface. The data will give the module content to be rendered, such as the wireless building scene, which is also the application scene of a micro module.
3.10.2 Micro-module architecture
Icestark will have a clear definition for the application scenarios of micro-modules, which will no longer de-couple routes. The interior of the micro-application mentioned earlier is basically a SPA with at least one route or page, but we want to keep the use of micro-modules as simple as possible, because once multiple modules are coupled with a large number of routes, it complicates routing processing.
In the module standard, the micro module is packaged directly in the way of UMD, through this standard mode, even in the form of NPM package can be used normally. In addition to the default export module method, the mount and unmount life cycles need to be defined inside the micro-module.
The application scenario of micro-module is actually a supplement to micro-application, which is more suitable for more fine-grained function splitting and dynamic construction scenarios.
Fourth, business value
There are many architectural designs and schemes mentioned above. Can the introduction of micro-front-end architecture solve the problems initially mentioned in business?
4.1 Analysis of two scenarios
The first is a large single application scenario, which has a high page size and development efficiency, including high stack migration costs. With the micro-front-end architecture, we can break it down into individual applications by functional dimension. Both incremental business and technical architecture upgrades can be done inexpensively in separate applications.
The second is the workbench scenario, which is more about product experience and operational efficiency. The micro front-end architecture can bring the experience of an independent SPA without breaking its independent development and deployment process. At the same time, different applications are unified access to the framework application, which also makes the access application have a certain control, avoiding some repetitive construction and uncontrolled technology selection.
Based on both of these scenarios, the micro-front-end architecture can provide its answer.
4.2. Business landing
In fact, ICestark has been verified by a large number of businesses in Alibaba Group, and has been implemented into 20 + platform level applications, covering taobao, Cainiao, Feizhu, business platform and other departments. Meanwhile, we also welcome the community to provide more suggestions on business practice scenarios for ICestark.
4.3,
Finally, the technical architecture of the micro-front-end is summarized. It brings technical architecture optimization solutions to large single application scenarios and workbench scenarios (Portal system). By introducing the technical architecture of the micro-front-end to solve the problems and bottlenecks encountered in the current system, the system can be maintained and iterated for a long time.
4.4 contact information
If you are interested in the front-end architecture scheme of Flying Ice and the technical architecture of micro front-end, you can join this community group and communicate with each other. Welcome to ICestark: github.com/ice-lab/ice…
Question and answer
How does ICestark judge the resources that need to be loaded for the corresponding micro application by hijacking the route?
Icestark listens for route changes through route hijacking, including pushState and replaceState in the History API, and popState and hashChange in the Window browser. Once the route changes, the URL change information can be hijacked and then matched according to the routing rules registered by micro-application. If the match is successful, read the resource information set by the micro-application for loading.
I also used with to implement sandbox, but the Babel packaging will keep error, strict mode is not allowed to request, how do you solve?
The sandbox of ICestark is implemented based on the form of with + new Function. At present, no error is found in strict mode, and the error scenario can be seen in detail.
This article is formatted using MDNICE