Written in the beginning part, the opportunity of this article is that our team of colleagues recently implemented a set of Redux on the client side to refactor and design the functions of a certain business domain. iOS and Android both follow this set of rules, namely Redux. Why do you need a client to implement a set of Redux? The business logic of the commodity module is very responsible. There are many basic commodity information, such as multi-specification, multi-unit, price, inventory and other information, as well as corresponding store and online store models, as well as various industry capability switch controls. The early implementation has Rx As a result, the code logic is more complicated and the data flow is more chaotic. The architecture design and code maintenance are not very elegant in all aspects. In addition, there have been major business adjustments recently. The students in the middle office used Redux + one-way data flow to reconstruct the business.
Another offline often requests gateway data. iOS and Android respectively declare the DTO Model, and then parse the data to generate the data required by the client. This kind of "repetitive" behavior often occurs, so simply use TS + scripts to remove the gateway. The data model has the ability to automatically generate iOS and Android models. However, when discussing the framework design, I would like to compare React Redux, Flutter Fish Redux, Vuex, etc., and talk about one-way data flow and two-way data flow, but some students’ understanding is wrong. Therefore, the first part of this article, "Error Correction Questions", is to clarify several key concepts of the front-end.
The following part will be described in logical order: micro front end -> BFF/gateway -> micro service.
1. Error correction questions
1. Is Vue a two-way data flow?
If the answer is "yes", then you should not figure out the two-way data flow 161a58cbd9cd28" and " two-way binding ". In fact, to be precise, the two are not things of the same dimension, and one-way data flow can also achieve two-way binding.
In fact, if you have read the official Vue documentation carefully, then the official has stated that Vue is actually One-Way Data Flow . The following paragraph comes from the official
First of all, make it clear that the data flow we are talking about is the data flow between components. All props in Vue make a single downward binding between parent and child props: updates of parent props flow down to the child component, but not vice versa, so as to prevent accidental changes from the child component to the parent component State, which makes your application data flow difficult to understand.
In addition, every time the parent component changes, all props in the child component will be refreshed to the latest value, which means you should not modify the prop in the child component. If you do, the browser will A warning is output in the console. Vue and React modified props and reported the following errors:
2. Is React MVVM?
Without directly answering this question, let's talk about a few concepts first. After these concepts are clear, the answer to the question is ready to come out.
2.1 What is the difference between one-way binding and two-way binding?
When talking about MVVM, we must talk about the role of binder. That is, one-way binding and two-way binding.
Vue supports one-way binding and two-way binding. One-way binding is actually the association between Model and View, such as v-bind. Two-way binding means that the update of the Model will be synchronized to the View, and the data changes on the View will be automatically synchronized to the Model, such as v-model.
V-model is actually syntactic sugar, because Vue is tamplate, so after being parsed by webpack ast, tamplate will become render, and v-model will become v-bind and v-on
One-way binding can be used to easily achieve the effect of two-way binding, which is one-way binding + auto event binding. as follows
In fact, after reading the source code, you will find (Vue3 Proxy) that the difference between one-way binding and two-way binding is that the operation part of two-way binding changes data is implemented within the framework, and the caller does not need to perceive it.
2.2 Redux
A typical flow chart using React Redux is as follows
If we hide the implementation of action and dispatcher inside the framework, this diagram can be simplified to
If we go further, we hide the mechanism of manual notification to each other, which can be simplified to
Look carefully, is it MVVM? The answer to that question is obvious, React is not MVVM.
3. Is Vue MVVM
The official said, "Although it does not fully follow the idea of MVVM, it is inspired by MVVM. So VM is often seen during Debug." Model changes will trigger View updates. This is reflected in V-bind and View changes Synchronize to the Model, which is reflected in the V-model. The above all follow MVVM, but Vue provides the Ref attribute, allowing the use of ref to get the Dom, thereby directly operating some styles or attributes of the Dom, which breaks the MVVM specification
4. One-way binding and two-way binding usage scenarios
Let's think about another question. Why does Vue remove .sync and Angular adds <to achieve one-way binding?
When the application becomes larger and larger, the two-way data flow will bring a lot of unpredictable results, which makes debugging, debugging, and testing complicated.
So Vue and Angular are aware of this, so they removed .sync and supported one-way binding.
Talk about the question head-on:
One-way binding brings one-way data flow. The benefit is that all state changes can be recorded and tracked. The state changes must be notified through manual calls. The source can be traced back and there is no "black box operation". At the same time, component data has only a single entry and exit, making the program more intuitive and easier to understand, which is conducive to the maintainability of the application. The disadvantage is that to achieve the same requirements, the amount of code will increase, and the flow of data will become longer. At the same time, due to the strict requirements for independent management of application states (single global store), it is particularly cumbersome when dealing with scenarios with more local states (such as "rich form" applications with more user input interactions).
The advantage of two-way binding is that it will simplify a lot of business-independent code in scenarios where there are many forms interactions. The disadvantage is that because they are all "black box operations", local state changes cannot be tracked, and too many potential behaviors increase the difficulty of debugging when errors occur. At the same time, because component data changes may have more than one source entry, programmers have uneven levels, and the written code can easily mess up the direction of data flow, and the quality of the entire application is uncontrollable.
Summary: One-way binding and two-way binding are basically complementary in function, so we can use appropriate means in appropriate scenarios. For example, in UI controls (usually form-like operations), you can use two-way binding of data; while other scenarios use one-way binding
Two, micro front end
The Vue, React, one-way data flow, and two-way data flow mentioned above are all organized and designed for a single application, but when the application is large, there will be some problems. Leading to a topic of today, "micro front end"
The client-side students know that we have used componentization and modularization to split code and logic for a long time. So you can tell what is a component and what is a module?
The component is to extract the repetitive code and merge it into a component. The component emphasizes the reuse. It is located at the bottom of the system. Other functions are dependent on the component and have strong independence.
Module means that the code belonging to the same function/business is isolated into independent modules, which can run independently, divided into different modules in dimensions such as pages and functions, and are located at the business architecture layer.
These concepts are also the same in the front-end. For example, those who have written Vue and React know that components need to be split for a page, and a large page is composed of multiple UI subcomponents. The same is true for modules. The front end uses self-executing functions (IIFE) to achieve modularity, mature CommonJS, AMD, CMD, UMD specifications, and so on. For example, the iOS side uses modularity to realize the division of business domains such as commodities, inventory, and billing, and also realizes basic capability modules such as routing libraries and network libraries. The front end uses modularity to achieve the reusability of namespace and code.
In fact, it can be seen that the modularization and componentization of the front-end and client-side implementations are based on the idea of divide and conquer. It is more about splitting and organizing management at the code level. However, as front-end engineering becomes heavier and heavier, it is difficult for traditional front-end architectures to follow the "agile" thinking.
1. What is a micro front end
Those who care about technology will immediately think of micro-services when they hear micro-frontends. Microservices are a variant of service-oriented architecture. Applications are designed as a series of loosely coupled fine-grained services and organized through lightweight communication protocols. The older and heavier front-end engineering faces the same problem, and naturally the idea of microservices is borrowed from the front-end field.
Closer to home, Micro-Frontends is an architecture similar to microservices. It applies the concept of microservices to the browser side, that is, Web applications are transformed from a single monolithic application to multiple small frontend applications. Applications. Each front-end application can also run independently, develop independently, and deploy independently. micro front end is not a simple front-end framework or tool, but a set of architecture system .
2. Features
2.1 Technology has nothing to do
Toss two scenes, let's think about it:
- You are new to a company, and your boss throws you a 5-year old project. You need to continue to iterate and add features to this project.
- You have started a new project. The boss is used to the surging technology changes in the front-end, and only gave one requirement on the architecture: "How to ensure that this set of technical solutions will remain viable within 3 to 5 years, and not within 3 to 5 years. Later became another heritage project?"
For the first scene, we have a preliminary thought, yes, I just need to develop new features with React/Vue, anyway, they are just UI library, give me a Dom node how I want to render and how to render. But have you ever considered that this is just a view of floating on the surface, and engineering facilities sinking underneath? How do I package this component written in React and integrate it into the original code written in ES5? Or how can I make Webpack and Grunt coexist harmoniously and produce a bundle that meets expectations?
In the second scenario, how do you ensure that the technology stack remains alive for 3 to 5 years? Don't talk about cross-framework. Even if they are all React, 15 and 16 are incompatible. Hooks can't be used for Class component. What am I talking about? There is also a packaging plan. Fortunately, Webpack is the default. What about Webpack version upgrades, do you follow up every time? Don’t forget Babel, less, typescript and so on? Not to mention 3 years, how many people can guarantee that their project will be able to run after upgrading all dependent packages to the latest one year later?
Why do you cite these two scenarios? Because we have to count the companies that have spoken out about "micro-front-end" in the industry, we will find that adopt micro-front-end companies basically do ToB software services, and no ToC company has it. The appeal of the micro front end (there are also internal mid- and back-end systems), why is this so? It's simple, because few ToC software survives more than 3 years. For ToB applications, 3~5 years are too common! Let’s take a look at the consoles of Alibaba Cloud’s earliest products. Let’s take a look at the telecom software and banking software. Which one is not a 10-year+ lifespan? I won’t say much about how painful an enterprise software upgrade is. Therefore, most enterprise applications have a core demand, that is, ensure that my legacy code can be migrated smoothly, and how to ensure that I can still use the popular technology stack in a few years?
How to extend the life of the legacy project is our initial appeal to the micro front end. Many developments may not feel deep. After all, those projects that cannot earn millions in a year and have little value either die by themselves or are thrown away to the outsourcing team for maintenance. But you should know that for many small and medium-sized enterprises in the ToB field. In other words, such a system may be the basis for them to settle down.
Even for a new business, each technical team should be able to select the appropriate technology stack based on the technical reserves of its own team members and business characteristics, without having to pay special attention to the situation of other teams, that is, Team A can use React, and Team B can use Vue, C team can even use Angular to achieve.
2.2 Simple, loosely coupled code base
Compared with a whole piece of front-end engineering, the code base under the micro-front-end architecture is smaller and easier to develop and maintain. In addition, it is more important to avoid the increase in complexity caused by unreasonable implicit coupling between modules. Reduce the possibility of accidental coupling by defining clear application boundaries, increase the cost of logical coupling between sub-applications, and encourage developers to clarify the flow of data and events in the application
2.3 Incremental upgrade
The ideal code is naturally one with clear modules, clear dependencies, easy to extend, and easy to maintain... However, in practice, for various reasons:
- Historical items, ancestral codes
- Delivery pressure, be quick at the time
- Be familiar with it nearby, and be stable at that time...
There is always some less ideal code:
- The technology stack is backward, even forcibly mixing multiple technology stacks
- Coupling chaos, dare not move, how to stop the whole body
- Reconstruction is not complete, reconstruction-unfinished, another posture reconstruction-unfinished...
If you want to completely refactor these codes, the is that it is difficult to have sufficient resources to drastically in one step. While gradually refactoring, it is necessary to ensure a smooth transition of the intermediate version and continuous delivery. New features:
Therefore, in order to implement progressive refactoring, we need an ability to incrementally upgrade, first let the new and old code coexist harmoniously, and then gradually transform the old code until the entire refactoring is completed.
This incremental upgrade capability means that we can perform low-risk partial replacements for product features , including upgrade dependencies, replacement architecture, UI revisions, etc. On the other hand, it also brings flexibility in technology selection, which is helpful for the experimental trial and error of new technologies and new interactive modes.
2.4 Independent deployment
The ability to deploy independently is essential in the micro front-end system, which can narrow the scope of changes and reduce related risks
Therefore, each micro front end should have its own continuous delivery pipeline (including building, testing and deploying to the production environment), and it should be able to be deployed independently, without too much consideration of the current status of other code bases and delivery pipelines:
If there are three systems in the three Bizs of A, B, and C, the three can be deployed independently, and finally the main system will integrate and publish the application. This way is more independent and flexible. Think about the previous monolithic application, such as a complex business application. It is very likely that the entire application fails due to the failure of lint during the construction of B. This not only wastes the time of building A, but also makes the construction of the entire application serial , Inefficient.
2.5 Team Autonomy
In addition to decoupling the code and release cycle, the micro front end also helps to form an independent team. Different teams are responsible for an independent product function. It is best to divide it according to Biz. Because the code is independent, so The front-end business team based on Biz can design and think, provide more reasonable interfaces and capabilities. It can even abstract more basic capabilities and provide more complete capabilities based on business thinking, that is, the team is more autonomous.
3 How to achieve
The micro front end mainly adopts a combined application routing scheme. The core idea of the scheme is "master-slave" (is it familiar to students who have played Jenkins), which includes a base "MainApp" application and several micro-applications (MircroApp ), the base mostly uses a front-end SPA project, which is mainly responsible for application registration, routing mapping, message delivery, etc., while micro-applications are independent front-end projects, and these projects are not limited to the specific technologies (React, Vue, Angular, Jquery) and so on, each micro-application is registered in the base and managed by the base. Even if there is no base, these micro-applications can be accessed separately, as follows:
The problems that a micro application framework needs to solve are:
The distribution problem of route switching
As the base application of the micro front end, it is the entrance of the entire application, responsible for carrying the display of the current micro application and forwarding to other routing micro applications. The display of the current micro application generally consists of the following steps:
- As a SPA base application, it is a set of pure front-end projects. In order to display the micro-application pages in addition to the iframe, the micro-application page content must be pulled first, which requires the remote pull mechanism .
- The remote pull mechanism usually uses the fetch API to first obtain the HTML content of the micro application, and then extracts the JavaScript and CSS of the micro application through parsing, uses the eval method to run JavaScript, and appends the CSS and HTML content to the base The display area reserved for the micro-application in the application, when the micro-application is switched away, the content is uninstalled synchronously, which constitutes the display process of the current application.
- Of course, this process will involve the pollution of CSS styles and the pollution of JavaScript on global objects. This involves isolation issues will be discussed later, and the current process of remote pull mechanism has already been implemented by existing libraries, you can refer to import-html-entry and system.js .
For routing distribution, take the base SPA application developed by vue-router as an example, mainly the following process:
- When the path of the browser changes, vue-router will listen to the hashchange or popstate event to obtain the timing of route switching.
- The router that receives this change first is the router of the base, which can be obtained by querying the registration information and forwarded to the micro application. After some logical processing, the hash method or pushState method is used to modify the hash method or pushState method to route the information to the micro application. The application can manually monitor the reception of hashchange or popstate events, or use React-router, vue-router to take over the routing, and the following logic is controlled by the micro-application itself.
Isolation of main application and micro application
The application isolation problem is mainly divided into main application and micro application, JavaScript execution environment isolation between micro application and micro application, CSS style isolation, let's talk about CSS isolation first.
CSS isolation : When the main application and micro-applications are rendered on the same screen, some styles may pollute each other. If you want to completely isolate CSS pollution, you can use CSS Module or namespace to give each micro-application module a specific Prefix, you can ensure that they will not interfere with each other. You can use webpack's postcss plug-in to add a specific prefix when packaging.
The CSS isolation between micro-applications and micro-applications is very simple. Each time the application is loaded, all the link and style content of the application are marked. After the application is uninstalled, synchronize the corresponding link and style on the uninstall page.
JavaScript isolation : Whenever the JavaScript of the micro-application is loaded and running, its core is actually the modification of the global object Window and the change of some global events. For example, after the jQuery js runs, it will mount one on the Window
window.$
object, for other libraries React, Vue is no exception. For this reason, it is necessary to eliminate this conflict and influence as much as possible while loading and unloading each micro-application. The most common method is to use the sandbox mechanism (SandBox).The core of the sandbox mechanism is to make the access and modification of external objects within a controllable range when the partial JavaScript is running, that is, no matter how internally runs, it will not affect external objects. Generally, the vm module can be used on the Node.js side, but for the browser, you need to combine the with keyword and the window.Proxy object to implement the sandbox on the browser side.
Communication problem
There are many ways to communicate between applications. Of course, to allow multiple separate micro-applications to communicate, in essence, the intermediary or global object is still inseparable. Therefore, the communication mechanism of the message subscription (pub/sub) mode is very suitable. The event center Event will be defined in the base application, and each micro-application will register the event separately. When the event is triggered, the event center will distribute it uniformly. This constitutes the basic communication mechanism, the process is as follows:
Currently, many micro front-end frameworks are open sourced, such as qiankun . If you are interested, you can check the source code.
4. Whether to use micro front end
Why do you want to make a micro front end? Or what problem does the micro front end solve? It also answers whether there is a need to adopt a micro front end. The original problem that Single-spa, the originator of the micro front end, wanted to solve was to use the new technology stack in the old project. At this stage, the micro-front-end stated by Qiankun, the micro-front-end framework of Ant Financial, is another major problem to be solved, which is the difficulty of maintenance and the difficulty of collaborative development faced by the Jushi Project. If the project faces these two problems, I think the micro front end can try it. what do y'all think?
3. Thinking of building BFF based on GraphQL under the microservice platform
1. Big front-end architecture evolution
Let's tell a story
1. V1
Assuming that in early 2011, an e-commerce company completed the split of a single application, and the back-end service has been SOAized. At this time, the application form is only on the Web side. The V1 architecture diagram is as follows:
2. V2
The time has come to the beginning of 2012, and there has been a wave of wireless applications in China, and major manufacturers have begun their own wireless application development. In order to meet this demand, the architecture is adjusted to V2, as shown below
There are some problems with this architecture:
- The wireless App and internal microservices are strongly coupled, and changes on either side may affect the other side
- Wireless App needs to know internal service details
The wireless App needs to do a lot of aggregation tailoring and adaptation logic
Aggregation: A certain page may need to call several back-end APIs at the same time for combination, such as the data required by the product detail page, which cannot be completed in one call
Tailoring: The basic services provided by the back-end are relatively general, the payload returned is relatively large, and there are too many fields. The App needs to tailor the fields according to the device and business needs. Is the user's client Android or iOS, large screen or small screen, what is it? Version. For another example, which industry the business belongs to, what is the product form, in which scenario the function is deployed, who is the target user group, and so on. These factors will bring differences in the end-oriented functional logic. In the context of microservices and domain-driven design (not covered in this article), each service provides the basic functions of the current domain, such as the product domain, which provides product addition, query, and deletion functions, list functions, and details pages. Function.
But in the case of a product detail page, the data needs to call the product domain, inventory domain, and order domain. The client needs to do a lot of network interface processing and data processing.
Adaptation: Some common adaptations are usually format conversion. For example, some back-end services are relatively old and provide SOAP/XML data, but do not support JSON. At this time, some adaptation codes are needed.
- With the increase of usage types (iOS Phone/Pad, Android Phone/Pad, Hybrid, Mini Programs), the development of aggregation, tailoring and adaptation logic will cause a lot of duplication of work on the device side
- Front-ends such as iOS, Android, applets, and H5 all require business data. The earliest design was straight out of the back-end interface. This design will cause a problem, because biz1 is iteratively released, resulting in the implementation of back-end interface changes. Another requirement of Biz2 will change the design and implementation of the server side, causing the interface to be business-oriented. One can't help asking, are the basic services developed for business interfaces? This is a departure from domain-driven design
In this context, the BFF (Backend For Frontend) layer was born. Various fields provide basic data models. Each biz has its own BFF layer, which can be inquired on demand (for example, 200 basic product data, but only 5 for the mini program list page). For example, product details page may require product data, order Data, evaluation data, recommended data, inventory data, etc., the earliest design of the details page may require 6 interfaces. This is a poor experience for the client and the web page. There is a new design. The BFF of the details page Dynamically assemble the calling interface, a BFF interface will assemble the data and return it directly to the business side, the experience is very good
3. V2.1
There are too many problems with the V2 architecture, and there is no development and implementation. To solve the above problems, a new role, Mobile BFF, is introduced between external devices and internal microservices. BFF, also short for Backend for Frontend, can be considered as an adaptation service that adapts back-end microservices (mainly including logic of aggregation tailoring and format adaptation), exposing friendly and unified APIs to wireless end devices. It is convenient for wireless devices to access back-end services. The V2.1 service structure is as follows
The advantages of this architecture are:
Wireless App and internal services are not coupled. By introducing the introduction of BFF, the two sides can be changed independently:
- If the back-end changes, through BFF shielding, the front-end equipment can be unaffected
- If the front-end changes, through BFF shielding, the back-end microservices can remain unchanged for the time being
- When there are new requirements on the wireless side, BFF shielding can reduce the communication and collaboration overhead between the front and back ends. Many requirements can be handled by the front-end team on BFF.
- The wireless App only needs to know the address of Mobile BFF, and the service interface is unified, without knowing the complicated internal microservice addresses and details
- Converged tailoring and adaptation logic is implemented on Mobile BFF, and the wireless App side can simplify weight loss
4. V3
The V2.1 architecture is relatively successful. After its implementation, it has supported the company's early wireless business development for a long time. As the business volume has skyrocketed, the wireless R&D team has continued to increase, and the problems of the V2.1 architecture have also been exposed:
- Mobile BFF not only includes the aggregation/cutting/adaptation and business logic of each business line, but also introduces a lot of cross-cutting logic, such as security authentication, log monitoring, current limiting fuse, etc. As time goes by, the code becomes More and more complex, more and more technical debt, declining development efficiency, and increasing number of defects
- The Mobile BFF cluster is a single point of failure. Serious code flaws will cause traffic peaks and may cause cluster downtime, and all wireless applications are unavailable.
In order to solve the above pseudo-proposition, it was decided to build a new layer between the external device and the BFF, namely Api Gateway. The V3 architecture is as follows:
The new architecture V3 has the following adjustments:
- BFF is decoupled and split by team or business, and split into several BFF microservices. Each business line can develop and deliver its own responsible BFF microservices in parallel.
Guanguan (usually an independent framework team responsible for operation and maintenance) focuses on cross-sectional functions, including:
- Routing, routing requests from wireless devices to a microservice BFF cluster in the backend
- Authentication, centralized authentication and authentication of APIs involving sensitive data
- Monitoring, performance monitoring of Api calls
- Current-limiting fuse, when there is a traffic peak, or the back-end BFF/microservice is delayed or faulty, the gateway can actively perform current-limiting fuse to protect the back-end service and keep the front-end user experience acceptable.
- Security and anti-climbing, collect access logs, analyze malicious behaviors through the background, and block malicious requests.
- The gateway introduces another layer of indirection between the wireless device and the BFF, so that the two sides can be changed independently, especially when the background BFF is upgraded or migrated, the user-side application can be unaffected
In the new V3 architecture, the gateway plays an important role. It is a powerful tool for decoupling and subsequent upgrade and migration. With the cooperation of the gateway, a single BFF realizes decoupling and splitting, and each business team can independently develop and deliver their own The research and development efficiency of microservices has been greatly improved. In addition, after the cross-sectional logic is separated from BFF to the gateway, BFF developers can focus more on the delivery of business logic and achieve the separation of architectural concerns.
5 V4
With the continuous development of business, the technical architecture also needs continuous iteration and upgrade. In recent years, the technical team has received new business and technical requirements:
- Open up internal business capabilities and build a development platform. Further broaden the business form with the help of third-party community developers
- Abandon the traditional server-side Web application model, introduce a front-end and back-end separation architecture, and use H5 single-page technology to provide users with a better user experience
The idea of V4 is similar to that of V3, except that it expands new access channels:
- Introduce the BFF layer and supporting gateway layer for third-party open APIs to support third-party developers to develop applications on the open platform
- Introduce BFF and supporting gateway for H5 application, support front and back separation and H5 single page application mode
V4 is a relatively complete modern microservice architecture. From the outside to the inside, it is: end user experience layer -> gateway layer -> BFF layer -> microservice layer. The entire architecture has clear levels and clear responsibilities, which is a flexible and evolutionary architecture that can support continuous business innovation
Summarize:
- In the microservice architecture, BFF (Backend for Frontend) is also called the aggregation layer or adaptation layer. It mainly undertakes an adaptation role: adapt the internal complex microservices to a variety of different user experiences (wireless/Web/ H5/third-party, etc.) Friendly and unified API. Aggregation, tailoring and adaptation is the main responsibility of BFF.
- In the microservice architecture, the gateway focuses on solving cross-sectional logic, including routing, security, monitoring, and current limiting fuse. On the one hand, the gateway is a weapon for decoupling, while allowing developers to focus on the realization of business logic and achieve the separation of architectural concerns.
- The end user experience layer -> gateway layer -> BFF layer -> microservice layer is a typical layering method of modern microservice architecture. This architecture can flexibly respond to changes in business requirements and is an evolutionary architecture that supports innovation.
- Technology and business are constantly changing, and architects must constantly adjust the architecture to cope with these changes. BFF and gateways are both products of architecture evolution.
2. BFF & GraphQL
In the big front-end mode, the following two problems are often faced
- APIs that change frequently need to be forward compatible
- Not all fields returned in BFF are required by the client
So far, GraphQL was officially open sourced by Facebook in 2015. It is not a language, but an API query style. This article focuses on the design and evolution of the BFF layer in the big front-end mode, which requires the implementation of GraphQL. The following is a brief introduction to GraphQL, and you can check Node or the solution corresponding to a language for details.
1. Use GraphQL
Server description data-client request on demand-server return data
Server description data
type Project {
name: String
tagline: String
contributors: [User]
}
Client on-demand request
{
Project(name: 'GraphQL') {
tagline
}
}
Server return data
{
"project": {
tagline: "A query language for APIS"
}
}
2. Features
1. Define the data model and get it on demand
Just like writing SQL, just describe the data that needs to be queried
2. Data layering
Clear data format and strong semantics
3. Strong type, type checking
Have GraphQL's own type description, type checking
4. The agreement is not a storage
It looks similar to MongoDB, but one is data persistence and the other is interface query description.
5. No versioning required
Students who have written the client code will see that Apple will indicate the reason when discarding the api, what api is recommended to replace, etc. This is also supported by GraphQL, and when it is discarded, it also describes how to solve it and how to use it.
3. When do you need BFF
- The back-end is used by many clients, and each client has customized requirements for the same type of Api
- There are many back-end microservices, and each microservice only focuses on its own domain
- Need to do some personalization optimization for the Api used in the front end
When is not recommended to use BFF
- The back-end service is only used by one type of client
- The back-end service is relatively simple, and there are not many opportunities to provide public services (DDD, microservices)
4. Summary
In the microservice architecture, BFF (Backend for Frontend) is also called the re aggregation layer or adaptation layer. It mainly undertakes an adaptation role: adapt the internal complex microservices to a variety of different user experiences (wireless/Web /H5/Third party, etc.) Friendly and unified API. Aggregation, tailoring and adaptation is the main responsibility of BFF.
In the microservice architecture, the gateway focuses on solving cross-sectional logic, including routing, security, monitoring, and current limiting fuse. On the one hand, the gateway is a weapon for decoupling, while allowing developers to focus on the realization of business logic and achieve the separation of architectural concerns.
The end user experience layer -> gateway layer -> BFF layer -> microservice layer is a typical layering method of modern microservice architecture. This architecture can flexibly respond to changes in business requirements and is an evolutionary architecture that supports innovation.
Technology and business are constantly changing, and architects must constantly adjust the architecture to cope with these changes. BFF and gateways are both products of architecture evolution.
Fourth, the evolution of back-end architecture
1. Explanation of some common terms
Cloud Native is a method of building and running applications, and is a set of technical systems and methodology. Cloud Native is a combined word, Cloud+Native. Cloud is a cloud platform. Native means that the application is designed with the cloud environment in mind from the beginning of its design. The application is designed for the cloud and runs in the best posture on the cloud, making full use of the elasticity + distributed advantages of the cloud platform. .
Iaas: Infrastructure as a service. If you compare software development to a chef cooking, then IaaS means that others provide basic things such as kitchens, stoves, pots, etc. You use these things yourself, and make different things according to different needs. vegetable. The server is provided by the service provider, generally a cloud host, and the customer builds an environment to deploy the software. For example, Alibaba Cloud and Tencent Cloud are typical IaaS service providers.
Paas: Platform as a service, or a metaphor for cooking. For example, I make a yellow braised chicken rice. In addition to providing basic things, PaaS also provides you with ready-made chopped chicken, potatoes, and peppers. Put these things together, add some seasoning, and simmer on the stove in a small pot for 20 minutes. You only need to care about the software itself, and the environment in which the software runs is provided by the service provider. The cloud engine and cloud container we often say is PaaS.
Faas: Function as a Service, which is also used to make yellow braised chicken rice. This time I only provide soy sauce, salad oil, salt, vinegar, MSG and other seasonings. I don’t provide the others. You can add more according to different tastes. It's up to you to add some salt or more vinegar.
Saas: Software service, Software as a service, the same is still making yellow braised chicken rice. This time it is a small pot of chicken ready-made directly, all the seasonings are good, it is already a finished product, you only need to paste a brand, Just sell it directly, and simmer it on the stove for 20 minutes to make more. This is the concept of SaaS (Software as a Service), which directly purchases software that has been developed by a third-party service provider to use, thus eliminating the trouble of setting up a team for development.
Baas: You learned that you only need to change the front-end for what you want to change, and you don't need to change the back-end at all. At this time, you can use your brains. You can hire a front-end engineer, do the front-end page yourself, and use the service provider for the back-end part.
This is BaaS (Backend as a Service), you only need to develop the front-end part, and all the rest is handed over to the service provider. The "back-end cloud" that is often said is the meaning of BaaS. For example, LeanCloud, Bomb, etc. are typical BaaS service providers.
MicroService vs Severless: MicroService is a microservice, a small service focusing on a single responsibility and function. Serverless is equivalent to a more fine-grained and fragmented single responsibility and function small service. They are all a specific small service. At this level, Serverless=MicroService.
MicroService vs Service Mesh: Before the absence of ServiceMesh, microservice communication and data exchange synchronization also existed, and there are also better solutions, such as Spring Clould, OSS, Double, but their biggest feature is that they require you to write the code. , And need to write a lot of logic operation code in depth, which is intrusive. The biggest feature of ServiceMesh is that it is non-intrusive and does not require you to write specific code. You can only enjoy the communication between microservices, data exchange synchronization and other operations at the level of cloud services. The representatives here are such as docker+K8s, istio, linkerd Wait.
2. Architecture evolution
The entire evolution of the back-end can be as shown in the figure above, which has undergone constant iterations, and the specific explanation will not be expanded here. Compared with SOA, there is also an ESB (Enterprise Service Bus). Simply put, ESB is a pipe that connects various service nodes. In order to integrate different systems and services of different protocols, ESB can be simply understood as: it does message conversion, interpretation and routing, so that different services are interconnected; ESB is used to decouple the dependencies between services
The difference between SOA and microservice architecture
- Decentralization of microservices, removing the ESB enterprise bus. Microservices no longer emphasize the heavy ESB enterprise service bus in the traditional SOA architecture. At the same time, the SOA idea enters into a single business system to achieve true componentization
- The emergence of Docker container technology provides more convenient conditions for microservices, such as smaller deployment units, and each service can run in its own process through technologies such as Node or Spring Boot.
- SOA focuses on system integration, while microservices focus on complete separation
REST API: Each business logic is decomposed into a microservice, and the microservices communicate through the REST API.
API Gateway: Responsible for tasks such as service routing, load balancing, caching, access control, and authentication, and develop API interfaces for end users or clients.
Some common design patterns of front-end, BFF, and back-end
Written in the beginning part, the opportunity of this article is that our team of colleagues recently implemented a set of Redux on the client side to refactor and design the functions of a certain business domain. iOS and Android both follow this set of rules, namely Redux. Why do you need a client to implement a set of Redux? The business logic of the commodity module is very responsible. There are many basic commodity information, such as multi-specification, multi-unit, price, inventory and other information, as well as corresponding store and online store models, as well as various industry capability switch controls. The early implementation has Rx As a result, the code logic is more complicated and the data flow is more chaotic. The architecture design and code maintenance are not very elegant in all aspects. In addition, there have been major business adjustments recently. The students in the middle office used Redux + one-way data flow to reconstruct the business.
Another offline often requests gateway data. iOS and Android respectively declare the DTO Model, and then parse the data to generate the data required by the client. This kind of "repetitive" behavior often occurs, so simply use TS + scripts to remove the gateway. The data model has the ability to automatically generate iOS and Android models. However, when discussing the framework design, I would like to compare React Redux, Flutter Fish Redux, Vuex, etc., and talk about one-way data flow and two-way data flow, but some students’ understanding is wrong. Therefore, the first part of this article, "Error Correction Questions", is to clarify several key concepts of the front-end.
The following part will be described in logical order: micro front end -> BFF/gateway -> micro service.
1. Error correction questions
1. Is Vue a two-way data flow?
If the answer is "yes", then you should have not figured out the two-way data flow 161a58cbdccce5" and " two-way binding ". In fact, to be precise, the two are not things of the same dimension, and one-way data flow can also achieve two-way binding.
In fact, if you have read the official Vue documentation carefully, then the official has stated that Vue is actually One-Way Data Flow . The following paragraph comes from the official
First of all, make it clear that the data flow we are talking about is the data flow between components. All props in Vue make a single downward binding between parent and child props: updates of parent props flow down to the child component, but not vice versa, so as to prevent accidental changes from the child component to the parent component State, which makes your application data flow difficult to understand.
In addition, every time the parent component changes, all props in the child component will be refreshed to the latest value, which means you should not modify the prop in the child component. If you do, the browser will A warning is output in the console. Vue and React modified props and reported the following errors:
2. Is React MVVM?
Without directly answering this question, let's talk about a few concepts first. After these concepts are clear, the answer to the question is ready to come out.
2.1 What is the difference between one-way binding and two-way binding?
When talking about MVVM, we must talk about the role of binder. That is, one-way binding and two-way binding.
Vue supports one-way binding and two-way binding. One-way binding is actually the association between Model and View, such as v-bind. Two-way binding means that the update of the Model will be synchronized to the View, and the data changes on the View will be automatically synchronized to the Model, such as v-model.
V-model is actually syntactic sugar, because Vue is tamplate, so after being parsed by webpack ast, tamplate will become render, and v-model will become v-bind and v-on
One-way binding can be used to easily achieve the effect of two-way binding, which is one-way binding + auto event binding. as follows
In fact, after reading the source code, you will find (Vue3 Proxy) that the difference between one-way binding and two-way binding is that the operation part of two-way binding changes data is implemented within the framework, and the caller does not need to perceive it.
2.2 Redux
A typical flow chart using React Redux is as follows
If we hide the implementation of action and dispatcher inside the framework, this diagram can be simplified to
If we go further, we hide the mechanism of manual notification to each other, which can be simplified to
Look carefully, is it MVVM? The answer to that question is obvious, React is not MVVM.
3. Is Vue MVVM
The official said, "Although it does not fully follow the idea of MVVM, it is inspired by MVVM. So VM is often seen during Debug." Model changes will trigger View updates. This is reflected in V-bind and View changes Synchronize to the Model, which is reflected in the V-model. The above all follow MVVM, but Vue provides the Ref attribute, allowing the use of ref to get the Dom, thereby directly operating some styles or attributes of the Dom, which breaks the MVVM specification
4. One-way binding and two-way binding usage scenarios
Let's think about another question. Why does Vue remove .sync and Angular adds <to achieve one-way binding?
When the application becomes larger and larger, the two-way data flow will bring a lot of unpredictable results, which makes debugging, debugging, and testing complicated.
So Vue and Angular are aware of this, so they removed .sync and supported one-way binding.
Talk about the question head-on:
One-way binding brings one-way data flow. The benefit is that all state changes can be recorded and tracked. The state changes must be notified through manual calls. The source can be traced back and there is no "black box operation". At the same time, component data has only a single entry and exit, making the program more intuitive and easier to understand, which is conducive to the maintainability of the application. The disadvantage is that to achieve the same requirements, the amount of code will increase, and the flow of data will become longer. At the same time, due to the strict requirements for independent management of application states (single global store), it is particularly cumbersome when dealing with scenarios with more local states (such as "rich form" applications with more user input interactions).
The advantage of two-way binding is that it will simplify a lot of business-independent code in scenarios where there are many forms interactions. The disadvantage is that because they are all "black box operations", local state changes cannot be tracked, and too many potential behaviors increase the difficulty of debugging when errors occur. At the same time, because component data changes may have more than one source entry, programmers have uneven levels, and the written code can easily mess up the direction of data flow, and the quality of the entire application is uncontrollable.
Summary: One-way binding and two-way binding are basically complementary in function, so we can use appropriate means in appropriate scenarios. For example, in UI controls (usually form-like operations), you can use two-way binding of data; while other scenarios use one-way binding
Two, micro front end
The Vue, React, one-way data flow, and two-way data flow mentioned above are all organized and designed for a single application, but when the application is large, there will be some problems. Leading to a topic of today, "micro front end"
The client-side students know that we have used componentization and modularization to split code and logic for a long time. So you can tell what is a component and what is a module?
The component is to extract the repetitive code and merge it into a component. The component emphasizes the reuse. It is located at the bottom of the system. Other functions are dependent on the component and have strong independence.
Module means that the code belonging to the same function/business is isolated into independent modules, which can run independently, divided into different modules in dimensions such as pages and functions, and are located at the business architecture layer.
These concepts are also the same in the front-end. For example, those who have written Vue and React know that components need to be split for a page, and a large page is composed of multiple UI subcomponents. The same is true for modules. The front end uses self-executing functions (IIFE) to achieve modularity, mature CommonJS, AMD, CMD, UMD specifications, and so on. For example, the iOS side uses modularity to realize the division of business domains such as commodities, inventory, and billing, and also realizes basic capability modules such as routing libraries and network libraries. The front end uses modularity to achieve the reusability of namespace and code.
In fact, it can be seen that the modularization and componentization of the front-end and client-side implementations are based on the idea of divide and conquer. It is more about splitting and organizing management at the code level. However, as front-end engineering becomes heavier and heavier, it is difficult for traditional front-end architectures to follow the "agile" thinking.
1. What is a micro front end
Those who care about technology will immediately think of micro-services when they hear micro-frontends. Microservices are a variant of service-oriented architecture. Applications are designed as a series of loosely coupled fine-grained services and organized through lightweight communication protocols. The older and heavier front-end engineering faces the same problem, and naturally the idea of microservices is borrowed from the front-end field.
Closer to home, Micro-Frontends is an architecture similar to microservices. It applies the concept of microservices to the browser side, that is, Web applications are transformed from a single monolithic application to multiple small frontend applications. Applications. Each front-end application can also run independently, develop independently, and deploy independently. micro front end is not a simple front-end framework or tool, but a set of architecture system .
2. Features
2.1 Technology has nothing to do
Toss two scenes, let's think about it:
- You are new to a company, and your boss throws you a 5-year old project. You need to continue to iterate and add features to this project.
- You have started a new project. The boss is used to the surging technology changes in the front-end, and only gave one requirement on the architecture: "How to ensure that this set of technical solutions will remain viable within 3 to 5 years, and not within 3 to 5 years. Later became another heritage project?"
For the first scene, we have a preliminary thought, yes, I just need to develop new features with React/Vue, anyway, they are just UI library, give me a Dom node how I want to render and how to render. But have you ever considered that this is just a view of floating on the surface, and engineering facilities sinking underneath? How do I package this component written in React and integrate it into the original code written in ES5? Or how can I make Webpack and Grunt coexist harmoniously and produce a bundle that meets expectations?
In the second scenario, how do you ensure that the technology stack remains alive for 3 to 5 years? Don't talk about cross-framework. Even if they are all React, 15 and 16 are incompatible. Hooks can't be used for Class component. What am I talking about? There is also a packaging plan. Fortunately, Webpack is the default. What about Webpack version upgrades, do you follow up every time? Don’t forget Babel, less, typescript and so on? Not to mention 3 years, how many people can guarantee that their project will be able to run after upgrading all dependent packages to the latest one year later?
Why do you cite these two scenarios? Because we have to count the companies that have spoken out about "micro-front-end" in the industry, we will find that adopt micro-front-end companies basically do ToB software services, and no ToC company has it. The appeal of the micro front end (there are also internal mid- and back-end systems), why is this so? It's simple, because few ToC software survives more than 3 years. For ToB applications, 3~5 years are too common! Let’s take a look at the consoles of Alibaba Cloud’s earliest products. Let’s take a look at the telecom software and banking software. Which one is not a 10-year+ lifespan? I won’t say much about how painful an enterprise software upgrade is. Therefore, most enterprise applications have a core demand, that is, ensure that my legacy code can be migrated smoothly, and how to ensure that I can still use the popular technology stack in a few years?
How to extend the life of the legacy project is our initial appeal to the micro front end. Many developments may not feel deep. After all, those projects that cannot earn millions in a year and have little value either die by themselves or are thrown away to the outsourcing team for maintenance. But you should know that for many small and medium-sized enterprises in the ToB field. In other words, such a system may be the basis for them to settle down.
Even for a new business, each technical team should be able to select the appropriate technology stack based on the technical reserves of its own team members and business characteristics, without having to pay special attention to the situation of other teams, that is, Team A can use React, and Team B can use Vue, C team can even use Angular to achieve.
2.2 Simple, loosely coupled code base
Compared with a whole piece of front-end engineering, the code base under the micro-front-end architecture is smaller and easier to develop and maintain. In addition, it is more importan
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。