DEV Community

Faure Wu
Faure Wu

Posted on

Why do we need to maintain our own front-end engineering system?

We are creating a framework based on experiential Inter-App communications design, welcome everyone to discuss together

Currently, my team wisdesign is gradually completing the front-end engineering infrastructure construction. I hope to continuously share the key issues encountered during this process and our final solutions through the community, hoping to gain everyone's recognition, discuss together, and grow together.

We are currently facing several problems, which constantly give rise to our ideas and existing infrastructure. Our team consists of several front-ends, several designers, and hundreds of business back-ends. We need to complete the development and maintenance of hundreds of business modules. Correspondingly, a cooperation model has emerged, where the front-end and design parts have become the supporting departments of the business. Most of the requirements are directly connected between the product and the back-end R & D personnel. When the back-end developers cannot complete the code writing of the front-end part, they actively seek the assistance of the front-end. Under this model, R & D personnel face several difficult problems to solve.

  1. There are so many business teams working together to maintain a large software system delivered to customers. It is necessary to consider how to effectively split the project, allowing each project to be independently developed, debugged, and launched, reducing communication costs between teams. At the same time, it is necessary to consider how to effectively control the consistency of product interaction specifications.

  2. Backend developers are not professional frontend developers. They can easily learn and understand the logic writing of JavaScript, but it is difficult for them to handle the writing of style layout.

  3. For PC CRUD pages, it is not a difficult task for backend R & D, but business is often not so easy to meet. The client base involved in our business not only completes work on the PC side, but also requires users to quickly complete convenient tasks on the mobile side. This means that the same function needs to be ported to the mobile end. Writing on the mobile end will also make backend R & D feel distressed.

Seamless collaboration and integration between departments

In order to solve the problem of multiple teams collaborating to complete the R & D of an entire project, we need to consider what technologies are currently available in the front-end community. Obviously, the "micro frontend" solution is a technical solution that can solve our problems. We have investigated most of the micro frontend technologies in the community, which focus on integrating and upgrading some ancient projects, as well as integrating cross-technology stack projects. These are not necessary for us. We can maintain a set of technical systems. For some historical projects, in order to maintain overall consistency, we are determined and willing to spend time deduplicating and iterating. The micro frontend of the community has a common feature that we are somewhat concerned about. Although the sub-application has achieved independent research and development debugging, when we need to integrate the sub-application, we need to try to communicate and register with the shell application, and release the sub-application project and the parent application project at the same time to complete the integration. This means that the front-end team maintaining the parent application often needs to be convened by other departments to communicate the launch method. I think this is not a very good model, especially when it often needs to be launched late at night. Finally, we decided to construct our own micro frontend architecture system to solve the problems we face.

Our overall micro frontend cornerstone adopts the Webpack Module Federation solution. However, unlike the existing solution, we modified the Module Federation plugin and removed the registration step of remotes. Whether it is the integration and nesting of pages or the sharing of public resources between projects, there is no need to register the corresponding reference project address at compile runtime, eliminating the need for communication and coordination to complete the sharing. At this time, when we need to use public resource projects maintained by other teams (public_components) in business projects (apps), a simple code case is as follows:

import WareSelect from "remote:public_components/wareSelect"

export default function WarePage() {
    return (
        <WareSelect />
    )
}

Enter fullscreen mode Exit fullscreen mode

Through this method, we can maintain our component library in the form of a project as easily as maintaining the project's own components, eliminating the tedious release process of npm package management. I think this is great and saves a lot of mental burden of maintaining public resources.

After solving the problem of sharing public resources, the next step is to consider how to solve the integration problem across project pages. Since our page uses the same file system mapping routing method as other frameworks in the community, we consider solving it by accessing the URL address and dividing the URL into the following structures:

https://host#[layout]/[application]/route/route

In order to understand the composition of the entire URL, we need to first understand two concepts.

  1. Layout the common part of an application, is used to carry the application menu, breadcrumbs, user information, language switching, and other common parts between these pages. At the same time, an application can support multiple Layouts at the same time, and support online switching according to the scene, such as the login page, which usually does not require any layout. For example, when your application is nested into other applications, in order to better integrate, a separate layout is often implemented for the scene.

  2. Application represents the application project to which the current page belongs, often consistent with the application name, and subsequent routing addresses point to the application.

According to the above routing method, it is found that integrating a complete project becomes easy. True separation is achieved between teams, and tedious communication and coordination are no longer needed. All we need is to maintain the menu, establish menu permissions, and the public project team will uniformly maintain public resources and documents, which can be provided for consumption and use by various business departments.

The consistency of product interaction specifications solves the problem that the backend cannot get started with style writing

To truly solve this problem is a difficult problem. The solution we can think of is to output a standardized component library to the business department. However, there are already so many component libraries in the community, and the product specifications implemented by different developers and products vary greatly. This cannot solve our problem. We cannot rely on manual standardization. We need to further abstract the components. Since backend developers cannot write styles, let backend developers have no styles to write. We abstract the layout components and can complete the layout and interaction that meets our specifications through quick nesting of tags. This is a theory that is difficult to explain in words. Let me give a simple example.

At this point, we start to think about how to make the product focus on functional requirements, rather than worrying about layout specifications and styles. For example, what kind of layout should a display list page have, or when buttons need to be highlighted. At this point, the description of a requirement begins to gradually change. "The customer needs a page (Page), the title of the page is the purchase item list (Table), displaying the name of the purchaser (Cell), the purchase time (Cell), the purchase item (Cell), and supporting the quick search (Form) of the purchaser (Item), the purchase time (Item), and the purchase item (Item). It also needs to support the creation of purchase items (Button) and batch import functions (Button)." Miraculous discovery, Product Manager no longer needs to describe the layout method, no longer needs to help develop or design prototypes for products, only needs to focus on describing the required functions.

Product Manager omits the description of prototype specification interaction, which does not mean that the specification disappears or can be written casually by R & D. It is just that we have raised the rules of the product to a new dimension, which is carried by global specifications and component specifications. The code written by R & D expresses the functions described in the above product. For example, the code mapped by the above example

function PurchaseManagePage() {
    return (
        <Page title="Purchase Items List">
            <Actions>
                <Button text="Import" />
                <Button text="Create" />
            </Actions>

            <Form type="search">
                <Item label="Purchase Name" name="name" as={<Input />} />
                <Item label="Datetime" name="time" as={<DatePicker />} />
                <Item label="Purchase Items" name="ware" as={<Input />} />
            </Form>

            <Table>
                <Cell label="Purchase Name">{rowData.name}</Cell>
                <Cell label="Datetime">{rowData.time}</Cell>
                <Cell label="Purchase Items">{rowData.ware}</Cell>
            </Table>
        </Page>
    )
}
Enter fullscreen mode Exit fullscreen mode

Through this form, we gradually found that the problem was well solved, and R & D no longer needed to care about styles. Basically, we bid farewell to the writing of styles, and also solved the problem of product consistency among multiple teams. When we need to continuously improve the interaction of our products, we no longer need to focus on adjusting and aligning the details of each page, but only need to start from adjusting and extracting global rules and component rules. During this period, we did a lot of things, including limiting nested rules between components and customizing specifications. This is a goal that requires a long time to accumulate.

Make code written in one place run on multiple ends

In order to solve the last problem, the same function needs to be used on both PC and mobile ends. We do not want our application to achieve a superficial form that only "looks like" the mobile end. What we pursue is truly experiential cross-end mobile end interaction, such as fully adapting to the mobile end of the layout, and transforming the Select of components such as PC into a Picker component with the same function at the mobile end. This is no longer achieved through simple responsive adaptation. We need to establish an Inter-App communications mechanism, which can also be said to be a loading mechanism for Inter-App communications resources.

We map the resources involved in the tags that appear in front of the R & D team into two completely independent resources, one for PC component implementation and the other for mobile component implementation. The two component libraries have a common tag definition that is relatively open to the R & D team. Our engineering system implements the mechanism of switching resource loading at runtime on the browser side, achieving the ability to write the same code in one place and run on multiple ends. As the two component libraries at the bottom are independent, they are like free birds, which can fly freely within the range of not flying out of the team. This is insensitive to business-level R & D because they have always maintained a set of code to meet the access needs of users on different ends.

Similarly, we found that this pattern is no longer limited to the implementation of the Inter-App communications component library. It can solve more problems for us, such as loading only the current resources when switching between multiple themes and languages, and not loading multiple sets of resources at the same time, resulting in resource waste.

Conclusion

Short language cannot express it well. Our attempts and efforts are more about conveying what we are thinking about solving the problems we face. If what I have written can help you and you want to learn more about design and coding details, please follow us atwisdesign. Let more people see it and help more people who want to learn and discuss. At some point in the future, we will open source it and hope to do more things that are helpful to the community.

Top comments (0)