preface

After graduation in 2019, I worked as a front-end developer in a Mid-Taiwan department of Huawei that supported the downstream product line and made network operation and maintenance products. At that time, the front-end system in the department was based on a micro-front-end framework left several years ago. Our group was responsible for maintaining menus developed based on this framework, and material applications such as dashboard were used by other business groups. At that time, the concept of micro front end was not widely discussed in the industry as it is now, and the micro front end framework in the department was basically developed and used in the business department as early as 2015, which can be said to be very avant-garde (the author of this framework later became the CTO of our large department). However, the API design was very counter-intuitive, the code was very unreadable, and the documentation was completely ambiguous. Whoever took over the maintenance did not continue to develop the framework, and by 2019, when I joined the company, the framework had become a cancer, making developers complain.

I had a hard time learning the framework when I was hired, but when I got a rough idea of how to use it, IT turned out to be a very rudimentary publish-subscribe model. So in December, 19, I tried to redesign the API by myself and realized the basic functions of the framework from scratch. At that time, I named it “Obvious” and posted it on Github. Then, I explained it to my colleagues as a teaching project to help them understand the core ideas and principles of internal projects in the department.

Let me for the first time I realized this process made the wheels of pleasure, although later in the work, but also not idle, the project work is not the time for very busy thinking how to improve the framework, sometimes inspired by other libraries sudden inspiration, will begin to design and implement a new feature, and so have been developed for two years, Compared with the initial teaching imitation project, both the usage and the idea have changed greatly. The project name is changed to Rallie, which means assembly, because it does not want to be the same as the existing NPM package and does not want to add the prefix of personal NPM account. It implies that large-scale front-end application is a collection of front-end micro-services.

Some time ago, I submitted a draft to Teacher Ruan Yifeng’s weekly, which was adopted and attracted a wave of small peak traffic. Although the friends of star just marked it and no one put it into practice, I was still encouraged. Recently the company’s business is not particularly busy, more free time, so I wrote a document to Rallie. Looking back at the development process of this project in the past two years, I feel that I have gained a lot. I have practiced many technologies that I did not have the chance to try in the company’s projects. Now, I think it is also a micro front-end library with my own ideas and characteristics.

Therefore, I decided to write a series of blog posts on nuggets to explain the core principles of this project, which can be regarded as a promotion of this work and a periodic summary of this development process.

First of all, here are the project and document addresses for your reference and study:

  • Github: ralliejs/rallie
  • Documents: rallie. Js. Cool

The main body of this paper will briefly introduce the selection of the project, the overall architecture and other general content. The subsequent articles will mainly explain the implementation principle by module, and the specific way of using Api can be referred to the document. I hope this project can inspire readers. If you think it is helpful, you can give a small star. You are also welcome to point out or help improve the deficiencies of the project through issue and PR.

The body of the

The selection

typescript

Rallie has been working with typescript development from the start as a target for developing large projects, and static type checking helps identify problems ahead of time. Working with typescript also made me think about how to provide good typescript support for users when designing Rallie’s features. For example, the state management of Rallie was realized based on keyPath in the early stage. Later, it was found that this way could not provide good TS support, so it was changed to @vue/reactivity for state management in the later stage. In addition, the traditional implementation of the event publish and subscribe model is not friendly enough to support TS, so I later introduced Proxy forwarding to implement publish and subscribe.

Of course, due to my shallow understanding of typescript, there are a lot of things in the project that are not standard enough to use TS, and there may even be mistakes. I will have time to learn more about TS and improve it later in the project

Packaging tools

Rallie chose Rollup as the packaging tool, and there was no fuss about the selection. In fact, only Webpack was used at the beginning of selection, but I have heard that rollup is more suitable for packaging JS libraries, so I learned rollup quickly and started to use it. Rollup is indeed much simpler than Webpack, and the packaged code is even directly readable. It’s a great packaging tool for developing third-party libraries. It’s also worth noting that if I had to remodel now, I would probably use vite’s library mode. Vite was also rollup based for production builds, but it had the advantage of making it very easy to write test pages in index.html at development time, which was very useful for quickly validating functionality.

Of course, since I used monorepo subcontracting, it was also easy to quickly see the effects in my sample project, so I didn’t have to fiddle with the build tools.

monorepo

Rallie was called Obvious at the beginning, but it was actually just a single project. Later, the project gradually became a core, based on which the later Rallie was derived. Later, Rallie wanted to provide support for React and Vue. Therefore, two projects, @rallie/ React and @rallie/ Vue, were opened. After having the middleware function, if you want to provide some independently maintained middleware, you need to open a separate project. Sometimes changes made in one package will affect the functions of another package. After a period of sub-project development, I found it troublesome to manually track dependent versions, so I decided to put these projects into the same warehouse and organize them in the way of Monorepo. After some research, I found that Lerna basically provided the functions I needed, so I chose Lerna as the monorePO management tool.

The benefits of using Lerna are clear: dependency management between projects is no longer a concern, and publishing is automated.

State management

As an important part of Rallie servitization, state management has undergone several evolutions. As mentioned in the preface, this project imitates huawei’s internal framework at the beginning, realizing status monitoring based on the simple publish and subscribe mode. Therefore, the initial status management function is similar to this way of using

store.initState('key', value)
store.getState('key')
store.setState('key', value)
store.watchState('key', callback)
Copy the code

I decided that this was too crude for state management, so I extended it a bit to allow key values to be passed into the object’s keyPath, something like that

store.initState('key', {
  a: {
    b: {
      c: value
    }
  }
})
store.getState('key.a.b.c')
store.setState('key.a.b.c', value)
store.watchState('key.a.b.c', callback)
Copy the code

But this is all string-oriented programming, and typescript support is too unfriendly, so we decided to do state management in a mobx-like way. I originally thought about imitating Vue3 and realizing reactive state based on Proxy. Later, I found that Vue had published the reactive module separately as NPM package @vue/reactivity, so I directly used it.

Unit testing

The unit testing framework is straightforward and uses the well-known JEST. It’s worth mentioning that when I write single tests for @rallie/vue and @rallie/ React, INSTEAD of using @vue/test-utils and enzyme, Instead, we used @testing-library/react and @testing-library/vue under Testing Library. The @vue/test-utils and the enzyme are closer to vue and React, respectively, and can test component states and other information, while the Testing Library is closer to users. The idea is to focus not on the details of Testing components, but on the content rendered by components. The Vue single-test code written using Testing Library will be very similar to the React single-test code, which can reduce my learning cost and mental burden during Testing.

Tesing Library is recommended for those who need component unit testing.

The sample project

After the functionality of each package is developed, I also need to develop a sample project for people learning my library to get hands-on with. My idea is to build a MPA project, which is divided into three pages. One page uses Vue, the other uses React, and the other page displays the contents of the first two pages together. After research, I think vite’s multi-page application model is the most satisfying to my needs. Vite is much simpler to configure than webPack for multi-page applications with React and Vue.

The project structure

|---packages
    |---core
    |---rallie
    |---react
    |---vue
    |---load-html
    |---playground
Copy the code

Rallie is managed by Monorepo and is currently divided into the following packages

  • Core: realize the core application choreography and application communication functions. Published as @ rallie/core
  • Rallie: There is a layer of encapsulation based on core, which helps users to focus on the development of their own applications without paying attention to the architecture of the entire application cluster. Published as rallie
  • React: Based on Rallie, using hooks to combine services provided by Rallie with the React framework. Published as @ rallie/react
  • Vue: Based on Rallie, the services provided by Rallie are combined with the VUE framework through compositionAPI and mixin. Published as @ rallie/vue
  • Load-html: A relatively independent package. Provides a middleware that loads resources from HTML. Published as @ rallie/load – HTML
  • Playground: Sample project. Do not publish as NPM packages

After the Clone project, run NPM Install to install the dependencies for the root project, then run NPM Run bootstrap to install the dependencies for each package, and you can start development

The overall architecture

Rallie was not a difficult project. After further study, you will find that the code design of @rallie/core follows this architecture

Rallie encapsulates such architecture on the basis of @rallie/core

Stay tuned for

Personally, I think the homogenization of the micro front-end frameworks on the market is a bit serious. Since Qiankun, every framework is keen to study the application isolation function. In addition to introducing concepts, about 80% of the articles related to the code operation are about the implementation of JS sandbox. As I mentioned in the comparison section of the document, it feels like the microfront-end frameworks of the major manufacturers are becoming another form of IFrame. Because of this, in fact, there are a lot of people feel that the micro front end is nothing to find things, the simple things complicated. Rallie is characterized by the idea of servitization and decentralization, and strives to help developers improve the reusability and portability of front-end pages or modules through micro-front-end architecture.

Perhaps after studying Rallie, you can glimpse other possibilities of microfront-end architecture from a different perspective.