The Garfish microfront-end solution mentioned in this article is open source: github.com/modern-js-d… Garfish is the most widely used micro front-end solution in byteDance’s various departments, serving more than 100+ front-end teams and 400+ projects. In addition, ByteDance’s Modern Web engineering system will be open source (modern.js), and Garfish provides native support for the micro front-end with deep integration. More out of the box capabilities, stay tuned!

Background and significance of the emergence of micro front end

What a microfront is: A microservice-like architecture, a microfront is an architectural style that consists of several independently delivered front-end applications, breaking up front-end applications into smaller, simpler applications that can be developed, tested, and deployed independently, but remain cohesive as a single product to the user.

The micro-front-end was born in two broad backgrounds. The front-end community that advocates embracing change can see new frameworks, technologies and concepts emerge in an endless stream. And with the evolution of Web standards, front-end applications have better performance and faster development efficiency. However, as applications become more complex, involve larger teams, and have higher performance requirements, application complexity has become an important bottleneck blocking business development.

The micro front end is born in the increasingly complicated scene of Web applications, because with the improvement of network speed, computer hardware level and the evolution of Web standards, the user experience of Web applications is far worse than that of traditional application software. The gap in user experience between the two is shrinking. In addition, due to the fast development speed of Web applications and the characteristics of disposable, an ultimate result is that “applications that can be realized with Web technology will be realized through The Web”. In recent years, a large number of excellent products have emerged that can only be seen in traditional PC software, such as: Photoshop, Web Office, Web IDE. Although with the evolution of Web standards, front-end engineering is constantly evolving, from modularization to componentization to the present engineering, but in the face of large-scale cross-team development, cross-team enterprise-level application collaboration, the existing divide and conquer design mode is still powerless.

The dilemma of large-scale Web applications

Despite the explosive growth in the complexity and number of participants of Web applications, there is no new architectural model to solve the existing dilemmas and address both DX (Developer Experience) and UX (User Experience).

Taking the “R&D center” of Bytedance as an example, many R&D systems need to be used in daily r&d work, such as code management, code construction, domain name management, application publishing, CDN resource management, object storage, etc. The standing in the whole company’s point of view, the best product shape is placing all the r&d system in the same product, the user is unable to perceive him in the use of different products, for users don’t have any sense of fragmentation is a single product, also do not need to learn to multiple platforms, just need to learn and understand bytes to beat in the research and development of “China”.

In bytes to beat this kind of application can be seen everywhere, due to the existence in bytes to beat a large number of business lines, each line of business gets a lot of middle office system, and also in the exponential growth, beating in bytes in electric business, for example, for electrical business operation of daily work, actually with research and development work, daily around: Goods, merchants, brand, risk control, marketing and other work, so what was the most efficient for electricity operation electricity operation system, due to the whole system has a wide range, inevitably in the process of the actual research and development capabilities or business requirements of vertical split into smaller subsystems, cut into all sorts of small system although due to the design idea of improving the developer experience partition, But the user experience is reduced to some extent. Can a new architectural model not only protect the developer experience, but also improve the user experience?

Advantages and disadvantages of traditional Web applications

Here simply analyze the traditional Web application in the development of large scale and involves much research and development team encountered some difficulties, in the above case, the “electricity business operating platform”, for example, goods for electrical business operations, businesses and brands are part of the electricity business operating platform capability, rather than independence between the island. In the case of traditional front-end development, there are two project design strategies:

  1. Multiple systems within the platform are maintained in the same code repository, adopting SPA (single-page Application) single-page Application mode
  2. The system is divided into multiple warehouses for maintenance, and the portal of all platforms is aggregated on the home page, adopting the multi-page Application mode (MPA)

If multiple systems are placed in the same project for maintenance:

  • Advantage:
    • Unified permission control, unified Open API development capabilities
    • Better code reuse, base library reuse
    • Unified operation management ability
    • Different systems can communicate well
    • SPA application has unique advantages:
      • Better performance
      • With partial updates, seamless user experience
      • Preload the user’s next page of content in advance
  • Disadvantage:
    • Code permission control problem
    • Projects take a long time to build
    • Requirement publishing blocks each other
    • Code commit mess, branch mess
    • The technical system requires unity
    • Unable to gray multiple product functions at the same time
    • Code rollback affects each other
    • Error monitoring cannot be fine-grained

Adopts the scheme of a disadvantage is very obvious, research and development: in the daily development code to build more than half an hour, release demand when the demand obstruction, unable to local grayscale local upgrade, project rollback affect other business have a problem, can’t rapid introduction of new technology system to improve productivity, iterative and maintenance project is a nightmare for research students.

Although the development experience is reduced, if the overall code of the project is split and lazy loading is properly controlled, the experience of users using the platform is actually improved. All this is attributed to the advantages brought by SPA application. SPA application does not need to refresh the whole page when jumping to the page, and only updates part of the route when changing. There is no need to make users feel jitter when the whole page is refreshed during MPA application switching, and the non-refreshing feature of the page can reuse resources between pages to a great extent, reduce the performance loss caused by page switching, and users will not feel that they are using different platforms.

If the use of divided into multiple warehouse maintenance

  • advantage
    • You can split code by project dimension to solve permission control problems
    • Only build this project code, build fast
    • Different technical systems can be used
    • There is no commit clutter and branch clutter when maintaining the same repository
    • Function grayscale does not affect each other
  • disadvantage
    • The user experience is fragmented and will jump between different platforms, failing to achieve the user experience brought by SPA application
    • The partition can only be divided by page dimension, not by block, but by service dimension
    • Multiple systems with the same gray strategy is difficult
    • The common package base library is loaded repeatedly
    • Different systems cannot communicate with each other directly
    • The common part can only be independently implemented by each system, so it is difficult to notify the same operation and maintenance
    • Product permissions cannot be converged uniformly

Scheme 2 improves the development experience to a certain extent, but reduces the user experience. R&d needs to use a large number of platforms in daily development, but it needs to jump to different platforms for daily RESEARCH and development, resulting in poor overall use experience. Experience because due to poor through project dimension split the overall research and development of “China” such a product, make each product is independent of the island, between each other between system jump are traditional in the sense of MPA, jump to reload the entire page of resources, in addition to performance is far less SPA cannot direct communication between application and application, This further enhances the sense of fragmentation that users feel when using the product.

Summary of background and significance

Through the above two cases, it can be found that large-scale Web applications cannot guarantee DX and UX at the same time in the face of high complexity and large number of team members when Web applications are gradually replacing traditional PC software. The traditional divide-and-conquer strategy is no longer able to cope with the complexity of modern Web applications, so a new architectural pattern, microfront-end, has been developed. Like back-end microservices, it is a continuation of the divide-and-conquer design pattern, but it is implemented in a new way.

Micro front-end solutions

The previous section summarized the background and significance of the emergence of the micro front end and looked at two traditional Web application development models: SPA (Single-Page Application) and MPA (Multi-Page Application) bring disadvantages in the scenario of large number of people involved and high project complexity, so it is expected that a new architecture can have the advantages of SPA and MPA at the same time. And improve both DX (Developer Experience) and UX (User Experience)?

Ideally, it would be desirable to take a complex monolithic application and vertically slice it into smaller subsystems based on functional or business requirements, and achieve the following capabilities:

  • The development and release of subsystems are separated from each other in space
  • Subsystems can use different technical architectures
  • The code reuse of the base library can be completed among subsystems
  • Communication between subsystems can be completed quickly
  • Requirement iteration between subsystems does not block each other
  • Sub-applications can be incrementally upgraded
  • Subsystems can move towards the same grayscale versioning
  • Provides centralized subsystem permission control
  • Users experience the entire system as a single product, not as an island of each other
  • Project monitoring can be refined down to subsystems

So based on the above ideal situation, how to design a set of new architecture from scratch to solve the dilemma of modern Web applications in the face of enterprise system?

The overall architecture of the micro front end

So how to provide a solution that not only has the user experience of SPA, but also can have the flexibility brought by MPA applications, and can realize the same gray level between applications, monitoring may also be refined to subsystems? Garfish, the micro front-end solution currently applied in ByteDance, is mainly divided into three layers: deployment side, framework runtime, debugging tool, and SPA architecture.

Overall solution architecture

Micro front-end deployment platform

Deployment platform as the front a important part of the research and development process, mainly provides: micro front-end service discovery, service registration, application version control, more child with gray level between applications, incremental upgrades, distributed application information list, analysis the son applications rely on information extraction of public library different applications rely on repeated load reduction.

It is used to solve the independent deployment, version control and sub-application information management of micro-front-end sub applications. The HTML content of the main application delivered through the interface provided by Serverless platform or in rendering service contains sub-application list information, which includes detailed information of sub-applications. For example: Application ID, activation path, dependency information, entry resources and other information, and through the analysis of the public dependency of the sub-application, deliver the public dependency of the sub-application, obtain the information of the sub-application at runtime and register it with the framework, and then control the sub-application on the main application for rendering and destruction.

Microfront runtimes

Why not iframe

When it comes to the micro front end, the topic is why it is not suitable for iframe to be used as a container to host micro front terminal applications. In fact, iframe is almost the most reliable micro front end solution from the perspective of experience. The main application uses iframe to load its child applications. Iframe has a natural sandbox mechanism due to its inherent style and environment isolation mechanism, but it is also not suitable as a loader for loading sub-applications due to its isolation. The characteristics of IFrame will not only lead to the decline of user experience, but also cause many troubles in the daily work of r&d. Here are some of the disadvantages of iframe as a child application:

  • Using an Iframe can significantly increase memory and computing resources because pages hosted within an Iframe require a new and complete documentation environment
  • Iframe is not in the same document context as the upper-layer application
    • Event bubbles do not penetrate the main document tree, and events cannot be delivered to the previous document flow when the focus is on the child application
      • Master application hijacking shortcut key operation
      • Events cannot bubble up to the top layer, and the processing time is uniform for the entire application
    • The forward path failed to synchronize with the upper-layer document, and the lost route status was updated. Procedure
    • Iframe elements can be restricted to the document tree, window width limit issues
    • Iframe login status cannot be shared. Sub-applications need to log in again
    • Iframe If third-party cookies are disabled, the Iframe platform service is unavailable
    • The Iframe application fails to be loaded, and the active application cannot detect the content error
    • It is difficult to calculate iframe performance as part of a page
  • Unable to preload cached IFrame content
  • The inability to share base libraries further reduces package size
  • Event communication is cumbersome and restrictive

Spa-based micro front-end architecture

Although it is difficult to use Iframe as a loader for micro front-end applications, it is useful to consider the design idea. A traditional Iframe’s ability to load documents can be divided into four layers: document loading capability, HTML rendering, JavaScript execution, isolated styles, and JavaScript runtime environment. Then the basic capability of micro front-end library can also refer to its design idea.

Taken from the design level is the base + the concept, application of partition deployment platform responsible for service discovery and service registration, registration application list information issued to the base, through the base to dynamically control subsystem of the rendering and destruction, and to provide a centralized model to complete the communication between the application and the application of public dependency management, So Garfish provides four core capabilities at the Runtime level:

  • Loader
    • Register the application list provided by the platform
    • Responsible for loading and parsing sub-application entry resources
      • HTML entry type, break down HTML Dom, Script, Style
      • JS entry type that provides the underlying Dom container
    • Preloading capacity
    • Parses the exported content of sub-applications
  • Sandbox isolation
    • Provides code execution capabilities and collects side effects when executing code
    • Provides the ability to destroy collection side effects
    • Support sandbox multiple instances, collect side effects of different instances
  • Router
    • Solve the problem of route synchronization between different applications
    • Provides the route hijacking capability to control the routes of sub-applications on the primary application
    • The ability to provide routing-driven capabilities to assemble complete platforms
  • Sub-application Communication (Store)
    • Building communication Bridges
    • Providing a sharing mechanism

Application life cycle

The whole life cycle of micro front terminal application can be summarized as follows:

  • Rendering phase
    • The master application triggers child application rendering by routing drivers or manual mounting
    • Starts loading the application’s resource content and initializes the child application’s sandbox runtime environment
    • Determine entry type
      • If the entry type is HTML, parsing and dismantling the child application resources will begin
      • If the entry type is JS, create a DOM for the child application
    • Sandbox “side effects” (content that might affect the current page) from your child app
    • Start rendering the DOM tree of the child application
    • Trigger the child application’s render Hook
  • Destruction of phase
    • If the route changes out of the activation range of the child application or the destruction function is actively triggered, the application destruction is triggered
    • Clear application side effects at render time and runtime
    • Removes the child application’s DOM element

Loader design

The overall design concept of the loader is very similar to that of react-Loadable, with the following capabilities:

  • Load component resources asynchronously
  • Resources can be preloaded
  • Component resources can be cached
  • Caching component instances

Unlike components micro front as a way to apply monomer dissected into more child application architecture model, different from components, these be split out a child of the application of the best development pattern is in the development, testing, deployment, separated from the host environment, application itself should possess autonomy ability, then at this point with the Iframe’s ability to provide very similar, Iframe loads the resources of the entire sub-application in the form of loading HTML documents, so the sub-application itself can be an independent site, naturally with independent development and testing capabilities. So Garfish’s loader provides two types of application entry: HTML type and JS entry type, but it is important to note that Garfish does not divide it into a separate document stream like Iframe. Instead, Garfish treats it as the same document stream as the main application to avoid the experience of disconnecting it from the same document stream.

Because HTML entry type natural features, development, testing, independently in micro front-end overall architecture design, for cross team collaboration, can reduce the communication cost is the best development pattern, and the best way to reduce the communication cost is not communication, so the general project types are recommended as possible user types of entry using HTML.

So what do you need to do for an HTML entry type loader? Here’s a picture of the browser rendering process:

The rendering process for browsers can also be divided into: HTML text download, HTML disassembly into syntax tree, disassembly of contents with “side effects” (contents that may affect the current page) in syntax tree, such as Script, Style and Link, and submit to sandbox processing for rendering. Different from general sub-applications, sub-applications need to provide provider. Provider includes the life cycle of child application rendering and destruction. These two hooks can further enhance application rendering speed and performance in application cache mode.

Sandbox design

Why a sandbox

In fact, in the past, the concept of sandbox was rarely mentioned in Web applications, because the development of components is usually done by the developer through the development of specifications to avoid the side effects of components on the current application environment, such as: Components are rendered with timers, global variables, scrolling events, global styles, and a timely cleanup of the child’s effects on the current environment after the component is destroyed.

In contrast to components, a microfront-end is an architectural style consisting of multiple applications running independently, possibly from different technical architectures. Project development and testing are separated from each other in space and time. Without the isolation of Iframe, it is difficult to avoid conflicts between applications, which may lead to exceptions, errors and even unavailability of applications.

Take Webpack4 JsonpFunction as an example

Module Federation is an important feature provided in Webpack5. One important configuration change from Webpack 4 is that the JsonpFunction property has changed to chunkLoadingGlobal, And instead of the default webpack ‘ ‘J’ ‘sonp, the default package name uses either the output.library name or package.json in context (name) as the only value webpack.js.org/issues/3940).

If you know Webpack’s build products, you will know that Webpack stores the products of the sub-chunks through global variables, which are used to solve the loading problem of sub-chunks. Since Webpack 5 introduced the possibility of having two or more Webpack build artifacts in the Module Federation page at the same time, it is inevitable that the artifacts will interact with each other if the chunk to be loaded is stored in the same variable.

As you can see from Webpack 4 to Webpack 5 support for Module Federation, using a base library as a multi-instance is likely to cause the application to fail to perform as expected in a scenario where the base library is not already multi-instance compliant by default. Even more serious is the fact that you think it is running properly, but the application has a serious memory leak or unexpected situation, if you run the Webpack build product in the page several times dynamically, you will find that it has caused a serious memory leak. Because Webpack incrementally mounts modules and dependencies to variables in the global chunk, in short, every time the child application code built by Webpack is executed pushes a large amount of data into the webpackJsonp array, causing memory leaks until the page crashes.

The core capabilities of the sandbox

To ensure stable running of applications without affecting each other, it is necessary to provide a secure operating environment that can effectively isolate, collect, and clear side effects generated during application running. What are the main side effects generated during application running? They can be classified into the following categories: Global variables, global events, timers, network requests, localStorage, Style styles, DOM elements.

The main capabilities of the Sandbox in Garfish Runtime also focus on capacity building in this area. There are two main types of side effects that may occur for sub-applications: static side effects and dynamic side effects. What are static side effects and dynamic side effects? Static side effects are static tag content in HTML. Script tags, Style tags, Link tags, these are included in HTML document flows, and the other side effects are dynamic side effects, which are created dynamically by JavaScript. For example, JavaScript can dynamically create styles, scripts, links, code execution, DOM elements, global variables, timers, network requests, localStorage, etc., which have side effects on the current page.

According to the side effects of the static son collected is simpler, Loader son already provides a core module in application gateways, taken apart on the analysis of the resource type and can be easily disassembled for DOM tree from the application side effects, so for the static side effects can collect, effectively remove, but has not yet have the ability to isolate. Dynamically created side effects are created dynamically through JavaScript, and need to collect side effects generated by JavaScript runtime and provide side effects isolation and destruction capabilities.

Two ideas of sandbox design

In Garfish microfront-end, how to effectively collect, isolate, and remove application side effects is one of the core capabilities to ensure smooth operation of applications. The main capability of the sandbox is also the ability to capture dynamically created side effects, isolate and clean up application side effects.

So how can you effectively capture, collect, and isolate the side effects of dynamic creation? Currently Garfish offers two design ideas, one is snapshot mode and the other is VM mode.

The snapshot sandbox

As the name implies, the current execution environment is saved in snapshot mode before the application runs. After the application is destroyed, the application is restored to the original execution environment, which is used to isolate and remove side effects between applications. Similar to “SL method”, save the environment and load the environment mode.

Code implementation ideas

Brief introduction of core design idea:

  1. Provide a Patch class for each side effect that provides both save and load methods
  2. Save corresponds to the environment snapshot store for the side effect, Load corresponds to the destruction recovery environment for the side effect
  3. In addition, for each Patch, changes occurring during operation can also be stored. In the optimization of the scene, not all codes are used and only the execution environment can be restored

The VM sandbox

As you can see from the simplest core implementation of the snapshot sandbox, its design concept relies on the entire code executing in a linear process, namely: Storage execution environment = > code execution have side-effects = > resume execution environment, but in the actual scene for the division of application is based on the dimensions of the page, the same page there may be multiple applications, so its execution order is not linear, may, at the same time, there are multiple snapshots sandbox instance environment is also more than snapshot sandbox instance, with the following code example:

Through the above code can be found, at the same time run multiple snapshots sandbox instance, under the scenarios of code execution order nonlinear, and can not effectively collection and processing of the application of side effects, and based on this snapshot sandbox scenario cannot be used in the nonlinear multiple instances, which further to launch the VM (virtual machine) sandbox.

A VM, in computer science architecture, is a special piece of software that creates an environment between the computer platform and the end user, who operates other software based on the environment created by the VM. Virtual machine (VM) is an emulator of a computer system. It can provide the functions of a physical computer by simulating a complete computer system with the functions of a complete hardware system and running in a completely isolated environment through software.

The VM module is also provided in Node, but unlike a traditional VM, it is not as isolated as a virtual machine. Instead of emulating a complete hardware system, it only compilers and executes code in a specific context, so it cannot be used with code from untrusted sources.

It is possible to design a VM sandbox by referring to the design of the VM module in Node and the nature of JavaScript lexical scope, but it is also different from a traditional VM in that it cannot execute untrusted code because its isolation is limited to running it in a specific context.

Thus the following design is obtained

What contexts are required to isolate the environment

New execution contexts are provided for the types of side effects: global variables, global events, timers, network requests, localStorage, Style styles, DOM elements, respectively:

  • Window
    • Used to isolate the global environment
  • document
    • Used to capture dynamically created DOM nodes, styles, and scripts
      • Collecting DOM Side effects
      • Collect Style side effects and process them
      • Collect the Script and continue sandbox processing
  • The timeout interval,
    • Processing timer
  • localstorage
    • Isolate the localStorage
  • listener
    • Collecting Global Events

Where does the new execution context come from

The new execution context comes from two sources,

  • From the current environment
  • Execution environment from Iframe

Since Iframe creation requires a lot of memory and computing resources, and the VM sandbox in the micro front end does not require a complete execution context, it can be based on the current environment.

Comparison between snapshot sandbox and VM sandbox capabilities

Design of routing system

The most classic capability provided by modern Web front-end frameworks is to transform a Constroller in MVC into a Router. At present, almost mainstream front-end frameworks support route-driven view. Only one Router Map routing table is provided. You can complete route update after a jump without controlling any route status.

Through the background and significance of the emergence of micro front end, we can know that the micro front end is mainly used to solve the following problems: incremental upgrade of applications, coexistence of multi-technology systems, and the construction of large-scale enterprise-level Web applications. It can also be seen from the SPa-based micro-front-end architecture that the current micro-front-end mainly adopts the mode of application divide and conquer + dynamic loading + SPA application to solve a series of problems caused by large-scale applications. In the SPA application with component granularity, there is no need to care about routing inside the component, but in the micro front end, the split application is mainly divided by application dimension, so the split application may also be an independent SPA application, then how to arrange the relationship between the main application and sub-application?

Ideal routing scheduling in micro – front-end applications

Suppose there is a Garfish site, which is composed of the main application and three sub-applications. The basename of the main application is /demo, and there are three tabs pointing to different applications. The ideal routing effect is as follows:

  1. Click on vue-app Tab to jump to/demo/vue-appAfter routing, activate the routes respectivelyvue-appBelow, Vue application A and APPLICATION B, and activate the Home component of application A and application B
  2. Click the React-app Tab to enter/demo/react-appAfter routing, activate the routes respectivelyreact-appRun the React-type C application and activate the Home component of the C application
  3. After activating the C application, click the Detail button to jump to/demo/react-app/detailAnd activate the detail component of the C application.
  4. Click the browser back button to display, jump/demo/react-app/detailAnd activate the Home component of the C application, thus completing the basic route jump capability of the browser.

Do not consider any routing processing scenarios

Suppose you have a Garfish site that consists of a main application and a sub-application. Since Garfish adopts SPA architecture, the sub-application and the master application are in the same execution context, and the routes of the sub-application are reflected on the master application as-is.

What are the problems with the /home and /detail routes?

  • Assuming that the jump method can trigger the update of the master and subapplication routes at the same time, preemption of the master and subapplication routes will occur at the same time, and the later rendered component will overwrite the first rendered component
  • After the hop side is triggered, only the primary application view is refreshed, only the sub-application view is refreshed, or none is refreshed
    • “View routing state is maintained inside the frame” and view updates cannot be triggered by native jumps

At this point, jump to: The component views of /home, /detail, and /test routes are triggered respectively. However, if the /detail view also exists in the sub-application routes, application development is separated in space and time due to the divide-and-conquer mode. Therefore, route preemption between applications cannot be guaranteed.

If A React application is redirected using the History API, the application view cannot be updated. If A React application is redirected using the History API, the application view cannot be updated. Observe the route route hops provided by React and the native route hops respectively:

Hash and History routing modes

At present, the mainstream SPA front-end applications basically support two routing modes. One is: The advantages and disadvantages of hash mode and History routing mode are not within the scope of this paper. This paper only introduces the separate development mode of micro front end. In the separate SPA application development mode of micro front end, which routing mode should be selected. And how their routing should be arranged for multiple SPA applications:

Normal Routing Conditions

Assuming that site address is: http://garfish.bytedance.net

  • The history mode is applied in the primary mode and the history mode is applied in the sub-mode

    • (basename: /example)

      • All routes for the active application are based on:http://garfish.bytedance.net``/example
      • For example jump to: /appA,http://garfish.bytedance.net``/example/appA/
    • Subapplication (basename: /example/appA) :

      • Subapplications all routes are based on:http://garfish.bytedance.net``/example/appA
      • Jump to the /detail page of the child application,http://garfish.bytedance.net``/example/appA/detail
    • Features:

      • When the master and sub-applications are in history mode, the routes of the sub-applications are based on the basic routes of the master application and carry their own service routes
      • Routes are synchronized to the primary application route, route conflicts between the primary application and other applications are isolated through the subapplication scope namespace (subapplication A provides appA’s scope), and the subapplication is synchronized to the primary application route
      • The path conforms to user and developer cognition and understanding
      • Nested hierarchies are supported and routes continue to be readable through scope’s namespace
  • The history mode is used as the primary mode and the hash mode is used as the sub-mode

    • (basename: /example)

      • All routes for the active application are based on:http://garfish.bytedance.net``/example
      • For example jump to: /appA,http://garfish.bytedance.net``/example/appA/
    • Subapplication (basename: /example/appA) :

      • Subapplications all routes are based on:http://garfish.bytedance.net``/example/appA
      • Secondary application:http://garfish.bytedance.net``/example/appAJump to the /detail page of the child application,http://garfish.bytedance.net``/example/appA#/detail
    • Features:

      • To some extent, it has the advantage that the host and child applications are in history mode, and does not support the use of nested levels
      • Most frameworks do not support basename with a hash value
      • Fair to read

Abnormal Routing

  • The hash mode is used as the primary mode and the history mode is used as the sub-mode

    • (basename: /example)

      • All routes for the active application are based on:http://garfish.bytedance.net``/example
      • For example, go to: /detail,http://garfish.bytedance.net``/example#/appA
    • Subapplication (basename: /example/appA) :

      • Subapplications all routes are based on:http://garfish.bytedance.net``/example#/appA
      • Jump to the /detail page of the child application,http://garfish.bytedance.net``/example/detail#/appA
    • Features:

      • “Routing chaos” is not intuitive for users and developers
      • Most frameworks do not support basename with a hash value
  • The primary hash mode is applied, and the sub-hash mode is applied

    • (basename: /example)

      • All routes for the active application are based on:http://garfish.bytedance.net``/example
      • For example, go to: /detail,http://garfish.bytedance.net``/example#/appA
    • Subapplication (basename: /example/appA) :

      • Subapplications all routes are based on:http://garfish.bytedance.net``/example#/appA
      • Jump to the /detail page of the child application,http://garfish.bytedance.net``/example#/detail
    • Features:

      • “Routing chaos” is not intuitive for users and developers
      • Most frameworks do not support basename with a hash value
      • Routing conflicts may occur with the primary application or other child applications

How does Garfish Router handle routing

Through the above ideal routing mode case, it can be found that after the micro-front-end application is divided into sub-applications, the sub-application routing should have autonomous capability and can make full use of the development advantages after the decoupling of applications. However, the routing between applications may conflict, the routing state in two routing modes may be difficult for users to understand, and the view cannot be updated due to the failure to activate different front-end frameworks.

Garfish currently offers the following four strategies

  • Router Map is provided to reduce developer understanding costs for typical Chinese applications
  • Different basename is provided for different subapplications to isolate route preemption between applications
  • The app view update is activated and triggered when the route changes
The Router Map reduces developer understanding costs

In typical mid-stage applications, the application structure can usually be divided into two parts, one is the menu and the other is the content area. Inspired by the design concept of modern front-end Web applications, routing tables are provided to automate the scheduling of sub-applications, and the common part is taken as the sub-application rendering area after separation.

Automatically calculates the basename required by the child application

When the application is in active state, the basic path required by the application is automatically calculated according to the activation conditions of the application, and told to the framework during rendering, so that there is no conflict between the application routes.

How to effectively trigger view updates between different applications

At present, the mainstream framework does not monitor routing changes to trigger component updates. Developers are allowed to jump through API wrapped by the framework and maintain the routing state internally. When routing updates occur using API methods provided by the framework, component updates are triggered by changes in the internal state.

Since the routing state of the framework is maintained internally, how to ensure that the view update of the application can be triggered in time and effectively when the routing changes? Yes, there are two main implementation strategies at present:

  1. Collect popState events that the framework listens to
  2. Actively raises the PopState event

Because the front-end framework that supports SPA applications at present listens for browser back events and triggers the update of the application view according to the routing state when the browser backs up, this capability can also be used to actively trigger the update of the application view. By collecting the listening events of the framework, Popstate can also be triggered in response to an application’s PopState event

Microfront-end best practices based on “modern Web Frameworks”

As a new type of Web application, micro front end is different from traditional Web application development. It needs to adopt the development mode of divide and conquer of master and sub-application, which brings a series of new challenges, including but not limited to: Master and sub-application development and debugging, how to change the common Web application into micro-front-end application quickly, how to support micro-front-end application SSR, master and sub-application data communication trigger view update. Modern.js, the Modern Web framework on top of Garfish, solves these problems and provides an out-of-the-box development experience.

Debugging and development of micro front-end applications

Due to micro front-end applications using development strategy of divide and conquer, application maintenance and development between may in time and space are separated, so during the development environment start the whole the front all master the application of the project, is a not sensible strategy, not only need to clone application and complete the other warehouse operation, and ensure that the timing of the code. Modern.js provides a better strategy:

  • When some subapplications need to be updated
    • Main application online environment
    • Sub-application offline environment to be developed
    • Child applications that don’t need to be developed come online
  • When the main application needs to be updated
    • Offline environment of the main application
    • All child online environments

With this better debugging strategy, you can ensure that developers only run the applications they care about. So how to achieve this better, we can adopt the mode of application list delivery. When the framework runs, it loads the list of applications to be delivered, pulls the list of applications on the line when the main application is developed, and the resources in the agent list are the list of sub-applications when a sub-application is developed.

Traditional Web applications support the micro-front-end pattern

According to the section of micro-front-end runtime, it can be found that the cost of switching between traditional Web applications and micro-front-end applications is not high, but it requires research and development to pay attention to the scheduling of application routes, the export of application life cycle, additional construction configuration, and the view update triggered by application communication data. There are some learning and understanding costs in switching between micro-front-end applications and traditional Web applications.

In Modern. Js, Garfish is integrated as the upper-layer framework, which supports micro-front-end applications. It can complete the conversion of micro-front-end application types through simple configuration, helping users to quickly build application infrastructure, reduce their learning costs, and quickly generate micro-front-end applications.

How do microfront-end applications support SSR

Micro front end as a kind of brand-new architecture mode, the partition design patterns in addition to bring a lot of advantage, but with the matching is introducing a new problem, how to support the traditional Web applications provided by SSR ability, the adoption of the micro front partition mode of development, split into multiple child application, you need to achieve the overall application of SSR ability, It needs to be combined with the specific Web framework, through the development of micro front-end application loading rules, to achieve micro front-end application can effectively achieve SSR capability.

Modern.js, as the upper-layer framework of Garfish, provides more out-of-the-box upper-layer capabilities and solves the drawbacks of the above micro-front-end that are different from traditional Web application development. At the end of this article, you can check out the release notice about modern.js.

Advantages of a micro front end

  • Suitable for large-scale Web application development
  • Faster development
  • Support iterative developable and enhanced upgrades
  • The disassembly reduces the cost of understanding for developers
  • Have both UX and DX development mode

Disadvantages of the micro front end

  • Complexity shifts from code to infrastructure
  • The stability and security of the entire application becomes more uncontrollable
  • There is a certain cost of learning and understanding
  • In order to give full play to the advantages of its architecture, it is necessary to establish a comprehensive micro-front-end peripheral facilities
    • A debugging tool
    • The monitoring system
    • Upper-layer Web Framework
    • Deployment platform

When to use a micro front end

  • Large-scale enterprise Web application development
  • Collaborative development across teams and enterprise applications
  • Long-term returns are higher than short-term ones
  • Different technology selection projects
  • Part of a cohesive single product needs independent publishing, grayscale and other capabilities
  • The goal of the microfront is not to replace Iframe
    • The source of the application must be trusted
    • User experience requirements are higher

conclusion

Micro front the emergence of the concept is the necessity of developing the front stage, the PC to the mobile Internet era, the Internet PC scene has not fully been eliminated, instead turned to derive a more immersive experience higher, stronger, and the matching should be a new architectural pattern to deal with the scale of growth.

The microfront end is not a silver bullet. Complexity does not disappear with the adoption of the microfront end. Instead, it shifts from code to infrastructure, which poses a greater challenge to architecture design.

This paper is more about the background and design of the micro front-end solution should have what capabilities, as well as the design of the core module. Each section does not go into too much detail, but for a detailed design of the “micro front run time”, you can visit github.com/modern-js-d… The warehouse knows the details.

reference

  • How to design the micro master routing scheduling in the front-end: mp.weixin.qq.com/s/TAXP7ipDd…
  • How to implement a sandbox opportunistic: mp.weixin.qq.com/s/Mg3fU0WvZ…
  • Microservices Architecture and its 10 most important design patterns: www.infoq.cn/article/kdw…
  • Single-spa:github.com/single-spa/…

Modern.js open source preview

Modern. Js and Garfish are both “Modern Web Engineering Architecture” open source projects initiated by ByteDance Web Infra. Modern.

Modern.js is scheduled to launch version 1.0.0 on October 14th.