There are few words about the instrumental value of Node, while the servitization value needs to be explored for a long time. The front-end of small dishes is still a primary school student on the road of servitization. The current attempt is the Cross framework, which has tasted some sweetness.

I don’t think there’s a lot of front-end engineers who wouldn’t be interested in Node, but everyone has a different answer to what it’s good for. For example, our in-depth experiment with Node can be found here: Why Node is the Core Technology Stack for front-end Teams [1], but few teams have the courage to make Node the server.

Is lack of confidence and courage, the reason is that the nature of the Node is not a comfortable enough framework to put you to quickly prove that drive business value, also is the Node is a lack of enough knowledge and confidence, as well as the strong relative to the server, often front when erosion in the field of the service side, face so that challenges and difficulties, This has become a common resistance to the promotion of Node in the team, and I hope you can find some answers from the team. Part of the answer is to have a sufficient understanding and cognition of Node, so as to abstract a general solution for the implementation of general problems. In the team, it is the encapsulation of the Node framework. The framework, which is not yet open source, is called Cross, meaning there is no technological threshold that cannot be overcome.


Distinguish Node boundaries

Slay before and after the team itself is love relationship, is both double folded, both the interface position alignment on the upstream and downstream data, there are also have to cooperate with each other to again and again win battle of the project, and in the service of this thing, the front is directly involved in the service areas, and from the point of the whole industry, This intervention in large and medium-sized companies has become an unstoppable trend. Whether taobao, Tmall, pay treasure, tencent, netease, baidu, including venture unicorn big search cars, beibei, Rokid, many companies at home and abroad in the field of nationality and have each team in depth, so here is the before and after the first boundary.

A thousand companies may have a thousand business models, a thousand user portraits, and a thousand business characteristics. There are not only blowout access scenarios with high real-time computing and high dependence on algorithms, but also toB big customer products with tens of UV and hundreds of PV per day. What scenes are appropriate and inappropriate to use Node? This second boundary is Node’s service boundary in the business domain.

Only by making clear these two boundaries can we have the survival soil of Node. If we break away from these two boundaries, it will inevitably hit walls everywhere and fail to land. For the front and back end boundaries, I once wrote such a paragraph:

The data control right and the API that the view depends on are the boundary of the front and back ends. The data control right belongs to the back end, and the API belongs to the back end. The front and back ends are simply regarded as a complete system, in which the back end is naturally from THE API down, and the front end belongs to the API up.

Below THE API, the business flow of data flow logic, above the data call and assembly, which is the natural demarcating point of the data level, and Node implantation, must also maintain the uniform and compatible specification with Java in the API layer, through RPC seamless call to talk about the boundary. And the border I understand it is the coupling of the strong business, such as independent internal coordination system, can also be high computational, can be relatively independent asynchronous high concurrency modules, such as message stack of frequent pull push, such as the collection of the log, etc., to sum up is a complex business processes, This place, which is not highly computational, can be used as a Node entry boundary.

As for the service boundary of the business, as long as the small and beautiful relatively independent system, as long as it is not the core business, Node can be used for rapid development, such as xiaodishes here have report system, packaging system, release system, market research system, log system, visual platform, recruitment interview system, Bug tracking system and so on.

The above two boundaries, when evaluating carefully, must not forget your team’s ability configuration, can Hold Node, Node technical experts, otherwise hasty use may backfire.


Why encapsulate Cross

After making clear the above boundary, Xiaocai front-end made in-depth use of Node in more than a year, from infrastructure system to relatively independent business system. As the whole process went on, more students in the team mastered the use of Node. At the same time, the differences between each system became bigger and bigger, some used Koa, others Koa2. There are Thinkjs, Express, and native NodeJS.

Obviously everyone’s preferences are different, the code quality is different also, engineering architecture was also different, this is the late maintenance bring great trouble, especially for the Node monitoring, found that can not do batch deployment with a plan, also can’t do level rapidly expand, need to choose a framework based on it to make uniform encapsulation, To the front to participate in all of the construction of a service can be unified, and the reality is that our front end and the Node applications due to the different methods of construction and service deployment for the whole project, already scattered on each server, and lead to maintenance has become a bottleneck, must also be time to make a change, this is the part of the scattered application diagram:




Why Eggjs

Before using Eggjs as the basic service framework of Nodejs, Xiaocai front-end used frameworks such as Koa, Express, Koa2 and Thinkjs, among which the closest thing to Eggjs is The open source Thinkjs of Qiwutuan [2]. The same convention is more than configuration. The same packaging based on Koa2 and the same multi-level and layered design (Controller, Service, etc.) make application development clearer. Interestingly, Thinkjs was open source earlier than Eggjs (2013). The growth rate of Its Star on Github is far behind that of Eggjs, and the number of NPM downloads is also far behind that of Eggjs. Although ThinkJS development experience is not bad, Eggjs is finally chosen as the Nodejs service framework for the following reasons:

  • Highly extensible plug-in mechanism

  • Easy to customize the upper frame

  • Rich and active community ecology

  • Incremental development

  • Multi-process Management

Xiaocai front-end has been using Eggjs since the beginning of 2018. Many of our projects are built based on Eggjs, including our report system, GraphQL gateway, small program background service, etc. In the process of using Eggjs to develop these projects, we gradually formed our own set of eggJs-based upper Framework suitable for Song Xiaocai. The Framework developed based on specific business scenarios of Xiaocai has a high degree of customization. You can refer to the skills and methods we used to implement this Framework. These routines should be universal.


What is the design concept

It is better to teach people to fish than to teach people to fish. Let’s first share our design concept, which is the simplest but also the most important beginning part. Our goal is to unify the style, easy to use and easy to maintain:



Then it is the collation of the overall requirements and development integration, and in the process of development integration, continuous tuning:



image.png

After setting the goal and designing the process, it is necessary to prepare specific implementation. Our implementation involves the process, mainly from the following four aspects:

  • Framework relationship

  • Generic API

  • Plug-in custom

  • Engineering management


How to Design the Framework


Framework relationship

We integrate all common APIS, common tool functions and common plug-ins (Redis, Gateway) into the basic framework baseFramework. As Egg supports multi-level framework inheritance, So we can derive other frameworks from the baseFramework, such as GraphQL related framework, microservices related framework, which is like a framework seed that can be customized in different directions:



image.png


Generic API


1. Request parameters are uniformly obtained

Given that a HomeController has a member function testAction that handles both POST and GET requests, the following situation might occur:

const { Controller } = require('egg');

module.exports = class HomeController extends Controller {
	testAction(){
    const { ctx } = this;
    const { method } = ctx.request;
    const id = method === 'GET'? ctx.request.query.id : ctx.request.body.id; . }}Copy the code

We can optimize it as:

/* yourapp/app/controller/home.js */
const { BaseController } = require('egg'); // const {BaseController} = require('your-egg-framework');

module.exports = class HomeController extends BaseController {
	testAction(){
    const id = this.getParam('id'); / /... } } /* egg-baseframework/core/base_controller.js */ const { Controller } = require('egg')

module.exports = class BaseController extends Controller {
	getParam(key) {
  	const { ctx } = this;
    const { method } = ctx.request;
    if (method === 'GET') {
    	if(key) {
      	...
      } else{... }}else{... } } } /* your-egg-baseframework/lib/index.js */ const { BaseController } = require('.. /core/base_controller');

module.exports = {
  BaseController,
  ...
}

/* your-egg-framework/app.js */
module.exports = (app) => {
	require('egg').BaseController = BaseController
}Copy the code


2. Returns data formatting

Similarly, we can define a uniform call success and call failure return function in BaseController, and handle the returned data in the function to avoid the return data problem


3. General utility functions

We can define the built-in object helper functions that may be used in business development in the form of framework extensions, which can be integrated in the way of framework extensions, such as parameter conversion, error message formatting, and so on.


4. Add a parameter verification layer

We can isolate the parameter verification step into the Logic layer. There are two ways to do this:

  • App.loader. loadToContext is called when the framework is loaded to mount all of the controller’s parameter verification functions to the context and is called when the controller executes the corresponding handler functions

  • Overrides the loadController of EggJS in your framework’s inherited appWorkerLoader, proxying each controller handler with the corresponding logic


Plug-in custom

Egg has a rich plugin ecosystem, but there are always some plugins we need that don’t fit our requirements. For example:

  • Egg-redis has long failed to support sentinel mode

  • Egg-graphql does not support connecting to other GraphQL services

  • Egg-kafka has not been maintained for a long time

At this point, we need to write or modify the corresponding plug-ins ourselves, and some common functions at the company level are like: Java server gateway request (egg-gateway), user authentication (egg-Auth), etc. We also packaged them as plug-ins and integrated them into the infrastructure. To be honest, the most enjoyable and fulfilling part of the whole framework development was when we wrote the plug-in:



image.png


Engineering management

Because of the interdependent relationship between plug-ins and plug-ins, plug-ins and frameworks, frameworks and frameworks, code management has become a headache, recommended to use the current popular Monorepo to manage. Standardize the release process to avoid incompatibility issues.


conclusion

We invested more than a month in the construction of Cross, which is a cost-effective attempt in terms of the input-output ratio. However, there will be many problems in the implementation. From the perspective of both people and the team, such a Framework needs students with certain Node programming ability to better use it. Still have certain mental cost for all people, is it possible to put the costs continue to reduce, to Pass with high order only care about the business logic behind the don’t care about the implementation phase, it is a very worthy of research topic, the other is from the perspective of things, if don’t have much of the business scenario to host this framework, In fact, it’s hard to go further because there aren’t enough applications and test scenarios to expose the problem, which is a real difficulty we’re having right now. The lack of Node has held us back, but the good news is that the next business scenario has been rolled out and the team has just added a Node player. Let’s see how the aftershock works.