I have introduced how I manage a large B-side system with dozens of sub-business domain systems by means of micro front end in several articles. Today, I would like to introduce how I manage a “monolith” single-page sub-business system in such a large B-end system.
Let’s talk about the background
As a front end, we have all experienced the experience pleasure of the early MPA application evolving into SPA application, and I believe we have all experienced the pain of simple SPA evolving into boulder SPA. I am currently in charge of a sub-business of a large B-side system, which is a large SPA with 8W+ lines of code and 10+ sub-page entries. And because of the similarity of business attributes, this sub-business system also serves the other two system platforms as a subsystem. Based on my daily iterative development, such applications are “too big to maintain” and are extremely expensive to develop and maintain.
Next, I will briefly introduce to you how I split the project step by step to optimize governance after getting such a “Monolith” single page application.
Analyzing business boundaries
First of all, I think what we need to do is to clarify the business boundary. Although our business is a sub-business of the large-scale B-end system, our system can also be divided into multiple sub-subsystems according to the business boundary. Next, I will start with an example.
Suppose our current business looks something like this, with business functions aggregated under sub-tabs, complex business logic under each TAB, and our system serving platforms A, B, and C as sub-businesses.
At this time, when doing system splitting, it is intuitive to think of splitting our system into three business subsystems according to platform A, B and C. If our business platform is very different, then it is understandable to split the system according to platform attributes. However, I believe that feers in the industry are more inclined to “one code, any platform”, so our business is not very different on these platforms, even the difference is only the theme color, so it is not reasonable to split the system according to the platform.
Next, we can consider breaking up the system in terms of the page structure. We can see that the structure we are currently using is aggregated separately in the form of tabs. If there is no complex event communication between tabs, we can consider splitting our submodules.
Finally, we need to analyze the business attributes. We can further start from the current product logic and put together some product functions that are more compatible or highly coupled with each other as a sub-module, which will be more conducive to the expansion and maintenance of future codes.
When we do business are often faced with trade-offs, there are a lot of finely small business do not know to which sub module, here I said I often use a method: I’ll try to keep the independence of the core business module, split the relatively independent child business together, can’t think of anything to do because a business affect the core business of everyone don’t want to…
Here is a brief summary:
- Analysis of platform differences, platform differences can be divided according to the platform;
- Analyze the page structure, if the structure is clear, can be divided according to the structure;
- Analyze the product business and combine the functions with high coupling degree of product logic.
Split common dependencies
After we have sorted out the business boundaries and divided the business modules, do not rush to split the modules, at this time we can find common dependencies from the sub-business modules to be split.
Next, I will briefly talk about a dependency separation idea in the current business:
-
According to the view layer, we fell to the ground within the group of business component library, in addition to the UI component library already out of some atoms with the business characteristics of business component, and is based on the atomic components encapsulation complex business domain business component, the business component service with our own business, not only in other business domain and the intersection of our business can also be used.
-
For the logical layer, we implemented the business function library, which contains the common function functions of our business domain, interface data structure to various Adapter functions of component data structure, and so on.
Then our system will look like the figure below:
Dismantle the molecular service module
After teasing out the separation of business boundaries and common dependencies, the true separation of sub-modules is the main thing I want to talk about here is how to “aggregate” the pieces together.
Unlike the governance of the B-side system discussed earlier, there are not many constraints on the aggregation of sub-business modules in our subsystem:
- The service volume is not large enough for the whole B-end system, which does not require complex routing design.
- Regardless of the impact with other business domains, the host environment is already sandboxed for us;
- It can design its own communication scheme, or appropriately reuse the communication scheme of the host environment (because of the division of business boundary, there should not be complex communication scenes between sub-business modules in theory);
But we also need an architectural solution for the host environment to develop our own aggregation solution. Here are some of the feasible solutions we have tried so far:
Based on the NPM package architecture
This architecture aims to break down common layout components into NPM packages for sub-applications. Such an architecture has the following advantages:
- The development is simple, the sub-application is developed and deployed separately, and only the layout components need to be introduced.
- Independent of the host environment, the host environment can adopt any architecture, and this solution will not be affected too much;
However, it also has the following disadvantages:
- Layout components should not contain excessive business logic, and frequent business changes will cause child applications to synchronize component versions frequently.
- After all, it is based on MPA, which is worse than the brushless experience of the other two schemes.
Based on iframe architecture
I will not repeat this scenario, as the previous article has provided a more detailed analysis of the architecture. Here are some of the weaknesses that differ from the current scenario:
- Depending on the architecture of the host environment, if the host environment is also an IFrame architecture, then layer upon layer of iframe nesting is more painful;
Based on the micro front-end architecture
Similarly, I will not repeat this scenario, as previous articles have provided a more detailed architecture analysis. Here are some of the weaknesses that differ from the current scenario:
- Depending on the architecture of the host environment, if the host is also a micro-front-end architecture, because I have not tried micro-front-end nesting scenarios, the feasibility and future risks are not controllable. If the host is iframe architecture, in fact, this is also a good solution (complete sandbox isolation). Currently, we have tried and implemented such a solution in our group.
Finally, our application is split according to the following hierarchy:
conclusion
The above is some of my thoughts on the layered governance of large SPA, of course, WHAT I have introduced is only one of the thousands of applications, and the real separation of successful problems are much more than described in the paper, there are many ways, I hope everyone can find the architecture design suitable for their application.
Recommended reading
- Deciphering the Micro Front end: The Birth of the Boulder App