Recently, netease Smart Enterprise has produced phased results in the access of Node.js (hereinafter referred to as Node), so it hereby publishes this series of articles, hoping to share some solutions in the access process with you, so as to provide help. The series mainly includes the following contents.

1. Node application architecture design

2. The React isomorphism

3. Health check and smooth release

4. CDN and code discovery on front-end code

5. Monitor applications

6. Grayscale environment

As the first of a series of articles, this paper mainly introduces the access process of netease smart enterprise Node from 0 to 1, mainly involving the application architecture and isomorphic rendering of Node, namely 1 and 2. Content related to Node engineering practice will be shared later (3, 4, 5, 6).

On the Node

Node is a JavaScript runtime based on the Chrome V8 engine. Created in 2009, Node was the first to bring JavaScript to back-end server development, as well as authoring tools such as code packaging tools, but it was originally intended to be a high-performance Web server. Its internal implementation of asynchronous IO, event-driven is designed for high-performance Web services.

Over the years, Node has developed very mature application patterns. For example, BFF (back-end For front-end) — Node serves as a layer of the Back end, providing data clipping and formatting, aggregation and orchestration For the Front end. There is also the Serverless service based on Node implementation, which is very popular these days. So specifically, how do we use Node for smart enterprises? Let’s first introduce the background of our requirements.

Demand background

At the end of 2019, netease Smart Enterprise is building an SCRM product — netease Huke (https://huke.163.com), which initially has three requirements:

1. Mutual customer platform.

2. Mutual customer operation system (for internal use).

3, mutual visitors official website.

The first two sections are more interactive, with some requirements that technically favor the single-page application format. The official website also needs SEO, so it needs isomorphic rendering capability (use React framework at the front end); Also given the technical architecture to promote the efficiency of development has formed the bottleneck, so consider using the new technology, to complete before and after the liberation of productive forces and eventually consider before and after using the Node to achieve the complete separation, thoroughly solved before the front-end to write Java template file and the end of the page data before and after understanding inconsistent embarrassing situation.

After deciding to use Node, the first problem we had to solve was how to work with the Java side, that is, the new front and back end division of labor. Since this was our first Node project for external services, as an initial experiment, we considered using the progressive development mode, starting with the integration. So the initial tasks we assigned to Node were relatively simple, including:

1. Page rendering.

2. User login verification.

3. Fill in the initial necessary data of the page.

4, functional interface implementation.

Another goal is to gradually improve the Node engineering tool system of smart enterprises through this project, and eventually form their own Node ecology.

Design and implementation

After determining how to cooperate with the Java terminal, another problem is to choose the Node framework. After investigation, we choose egg.js as the Node framework scheme, because it should be the most widely used and ecological Node enterprise framework in China at present. Once the division of tasks and the framework are finalized, the overall architecture of our application is created, as shown below:

Architecture diagram

Briefly describe the access path for the next complete user request. First, the user requests to the gateway, which forwards the request to Node or Java application according to the URL forwarding rules, thus completing a page visit or interface request. This involves routing design, and the URL of the page and interface should be able to be distinguished by path.

Take our customer list page for example. The URL path of the customer list is’ /admin/customer/all ‘. Our rule is that ‘/admin*’ corresponds to the page request, so the request will be forwarded to Node by the gateway. The Node uses HTTP request to obtain the initial page data from the Java side, puts it into the page template, and returns it to the user to complete the page access request.

Another important problem is the user’s login information. We use a more traditional scheme. The user login function is implemented in the Java side. Redirect the user to the login page. When the user fills in the information and clicks the login button, the login interface on the Java side is called for login. After the login request succeeds, the Java side will attach cookies to the response, so that the login information on the front-end, Node and Java side can be connected.

Of course, these are just Node’s capabilities as a page service, but we also need React’s isomorphism capabilities.

About the isomorphism

A set of code that can be run on both the server side and the client side, executed once on the server side to implement server-side rendering and again on the client side to take over page interaction is an isomorphic application. In short, it is a combination of server-side direct output and client-side rendering that fully combines the advantages of both and effectively avoids the disadvantages of both.

Isomorphism can not only solve the SEO problem mentioned above, but also effectively reduce the page white screen time, because it can reduce the previous three serial HTTP requests to one, and the effect of white screen time on the user is also very large.

How do React render objects in Node? This is because React introduced the virtual DOM. The virtual DOM is a JavaScript object mapping of the real DOM. When React does page operations, it doesn’t actually manipulate the DOM directly. That’s what made SSR possible. React outputs the virtual DOM as a string on the Node side, and maps the virtual DOM to the real DOM on the browser side to complete the page rendering.

How to render the React page as a string on Node? The React framework provides four apis for different usage scenarios:

* renderToString()

* renderToStaticMarkup()

* renderToNodeStream()

* renderToStaticNodeStream()

We chose the ‘renderToString’ method based on the requirements.

RenderToString (renderToString) is used to render the initial data in the React component, and the string is placed in the React mount node of the page template. However, implementing an egg.js plug-in that can automatically render the corresponding components according to the route is still a bit complicated, so we implemented the ‘pp-Fishssr’ server-side rendering plug-in to meet the need to render the corresponding pages according to the route.

Let’s introduce the differences of our implementation, first of all, configuration:

Json fishssr: {routes: [{path: '/admin/*', Component: () => (require(' @/page/admin ').default), controller: 'page. Admin'}, {path: '/ user / *, Component: () = > (the require (' @ / page/user). The default), the controller: 'user.h5Page',},], // page template file path template: 'screen/index.html', // server render packed JS file serverJs: ResolvePath (' dist/Page. Server. Js'),} ` ` `Copy the code
This section describes configuration items:

Path: ‘/admin/*’ and ‘/user/*’ correspond to a single page application respectively.

Component: The React Component of the page processes the initial data internally and converts it to the store’s preloadedState or props, which uses front-end routing.

Controller: the corresponding is an Egg. The controller of js, the initial data used to retrieve the page, and then use the ` enclosing CTX. Fishssr. RenderPage (initData) ` page rendering.

Template: a template file for the React page. The internal ‘stream’ is the string generated after Node renders the React page component.

```html <! DOCTYPE HTML > < HTML lang= 'zh-CN' > <head> <title> <link rel= 'stylesheet' href= '/ CSS/page.css' /> </head> The < body > < div id = "app" > {{stream | safe}} < / div > < script > window. __INITIAL_DATA__ = {{initialData | safe}}; < / script > < script SRC = "/ js/runtime - Page. The js" > < / script > < script SRC = "/ js/Page. Js" > < / script > < / body > < / HTML > ` ` `Copy the code
ServerJs: is the Node side packaged version corresponding to the portal file. The main code of the portal file is as follows:

```
const clientRender = async () => {
  ReactDOM.hydrate(
    <>
      {
        Routes.map(route => {
          const { path, Component } = route
          const isMatch = matchPath(window.location.pathname, route)
          if ( !isMatch ) {
            return null
          }
          const ActiveComponent = Component()
          const WrappedComponent = GetInitialProps(ActiveComponent)
          return <WrappedComponent key={path} />
        })
      }
    </>, document.getElementById('app'))
}
 
const serverRender = async (params) => {
  const { initData, path, url } = params
  const ActiveComponent = getComponent(Routes, path)()
  return (
    <StaticRouter location={url} context={initData}>
      <ActiveComponent {... initData} />
    </StaticRouter>
  )
}
 
export default __isBrowser__ ? clientRender() : serverRender
```
 Copy the code
This code renders the corresponding page component according to the route, and outputs the corresponding Node side and browser side rendering code according to the different packaging environment.

conclusion

As a complete enterprise-class Node framework, egg.js can be very smooth in the access process, and the main energy can be focused on solving its own business needs and back-end coordination.

At present, the product ** netease Huke ** using this solution has been launched. This solution has solved the technical and business requirements mentioned at the beginning of the article. At the same time, the new front and back end cooperation mode brought by this solution has greatly improved the development efficiency of not only the front end, but also very friendly to the back end. At the same time, the front end can also broaden its boundaries and accept more demands. For example, our operating system and functional API, such as wechat JS-SDK authentication, can only be put in the back end before, but now it is put in the Node end. The front end development is more flexible and reduces a lot of communication costs. However, as an external service Node application, only these are not enough, and still need the support of many engineering tools.

In the following sections, I will introduce some of our Node project practices to make Node applications more stable and provide faster and easier troubleshooting.



More technical dry goods, welcome to pay attention to the VX public account “netease smart Enterprise technology +”. Series of courses in advance, free gifts, but also direct conversations with CTO.

Listen to netease CTO talk about cutting-edge observation, see the most valuable technology dry goods, learn the latest practical experience of netease. Netease Smart Enterprise technology + will accompany you to grow from a thinker to a technical expert.