Netease smart enterprise Node.js Practice (1) isomorphism of node application architecture design and react

Time:2020-6-25

Introduction:

Recently, Netease smart Enterprises Node.js (hereinafter referred to as node) has output phased results in the access. This series of articles is specially launched, hoping to share some access process schemes with you, so as to provide help. The series mainly includes the following contents.

1. Node application architecture design

2. React isomorphism

3. Health examination and smooth release

4. CDN and code discovery on front-end code

5. Application monitoring

6. Gray environment

As the first part of this series, 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, that is, 1 and 2. Later, we will share the relevant contents about node engineering practice (3, 4, 5, 6).

About node
Netease smart enterprise Node.js Practice (1) isomorphism of node application architecture design and react

Node is a JavaScript runtime based on the chrome V8 engine. It was born in 2009. Node first brought JavaScript into the back-end server development. In addition, it can also write tools, such as code packaging tools, but its original purpose is to achieve high-performance web server. Its internal implementation of asynchronous IO, event driven is for high-performance web services.

After so many years of development, node has formed a very mature application mode, such as BFF (back-end for front-end) – serving the back-end of the front-end, taking node as a layer of the back-end, providing data cutting, formatting, aggregation and arrangement and other functions for the front-end. In addition, there is a very hot server less service based on node implementation recently. So how do we use node in our smart enterprise? Let’s first introduce our demand background.

Demand background

At the end of 2019, Netease smart enterprise is building a SCRM product – Netease mutual customer( https://huke.163.com )At first, it has three main requirements:

1. Mutual customer platform.

2. Mutual customer operation system (internal use).

3. Mutual guest official website.

The first two parts have high requirements for interaction, and some requirements determine that the form of single page application should be used preferentially in technology. The official website also needs SEO, so it needs to have the ability of isomorphic rendering (the front-end uses react framework); in addition, considering that the current technical architecture has become a bottleneck for the improvement of development efficiency, it is considered to use new technical solutions to completely liberate the productivity of the front and rear end, and finally consider using node To realize the complete separation of the front and back ends, completely solve the awkward situation that the front end has to write java template files and the front and back ends have inconsistent understanding of page data.

After deciding to use node, the first problem to be solved is how to cooperate with the Java end, that is, the new front and back end division of labor,Since this is our first external service node project, as a first attempt, we consider using the progressive development mode, starting from the pick-up, so the tasks we initially assigned to node are relatively simple, including:

1. Page rendering.

2. User login verification.

3. Page initial necessary data fill.

4. Functional interface implementation.

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

Design and Implementation

After determining how to cooperate with the Java side, another problem is to choose the Node framework Egg.js As a node framework scheme, the reason for choosing it is that it should be the most widely used and ecological node enterprise framework in China. After the task division and framework are determined, the overall architecture of our application will come out, as shown in the following figure:
Netease smart enterprise Node.js Practice (1) isomorphism of node application architecture design and react

[structure diagram]

Briefly describes the access path for the next full user request. First, the user requests to the gateway, which forwards the request to the node or Java application according to the URL forwarding rules, so as to complete a page access or interface request. This involves the design of routing, and the URL of page and interface can be distinguished by path.

Take our customer list page for example. The path of the URL of the customer list is ` / admin / customer / all ‘. Our rule is ` / Admin *’ corresponding page request, so the request will be forwarded to node by the gateway. In node, use HTTP request to obtain the initial data of the page from Java side, put it into the page template, return it to the user, and complete the page access request.

Another important problem is the user’s login information. We use a more traditional scheme. The user’s login function is implemented in the Java side. When the user visits the page, the node will check the login token in the cookie and verify it. If the token does not exist or is not correct, the user will be redirected On the login page, when the user fills in the information and clicks the login button, the login interface of the Java terminal is called to log in. After the success, the Java terminal will bring a cookie to the response of the login request, so that the login information of the front end, the node end and the Java terminal can be strung up.

Of course, these are only the capabilities provided by node as a page service, but we also need the isomorphism of react.

On isomorphism
Netease smart enterprise Node.js Practice (1) isomorphism of node application architecture design and react

A set of code can be run on both the server side and the client side. It can be executed once on the server side to achieve server-side rendering, and once again on the client side to take over page interaction. This is isomorphic application.In short, the combination of server-side direct out and client-side rendering can fully combine the advantages of both and effectively avoid the disadvantages of both.

Isomorphism can not only solve the previous SEO problem, but also effectively reduce the white screen time of the page, because it can reduce the previous three serial HTTP requests to one time, and the white screen time has a great impact on users.

Generally, the front-end framework needs to operate the dom. Of course, there is no problem in the browser environment, but there is no concept of DOM in node. How does react realize rendering at node end? This is because the virtual DOM introduced in react is a JavaScript object mapping of the real dom. In fact, when react does page operations, it does not directly operate the DOM, but operates the virtual DOM, that is, operates ordinary JavaScript objects, which makes SSR possible. The virtual DOM is output as a string by react on the node side, and the virtual DOM is mapped as a real DOM by react on the browser side to complete the page rendering.

So how to render the react page as a string on the node side? The react framework provides four APIs for different use scenarios, namely:

*  renderToString()

*  renderToStaticMarkup()

*  renderToNodeStream()

*  renderToStaticNodeStream()

According to the requirements, we choose the ‘rendertostring’ method.

In fact, the rendering logic of the whole server is very simple. Pass the initial data to the react component to use ‘rendertostring’ for rendering, and get a string. Just put the string into the react mount node in the page template. However, it is necessary to implement a system that can automatically render the corresponding components according to the route Egg.js The plug-in is still a little complex, so we implemented the ‘PP fishssr’ server rendering plug-in to meet the needs of rendering the corresponding page according to the route.

It mainly introduces the different aspects of our implementation. First, the configuration mode:

“`json

fishssr: {

routes: [

{

  path: ‘/admin/*’,

  Component: () => (require(‘@/page/admin’).default),

  controller: ‘page.admin’

},

{

  path: ‘/user/*’,

  Component: () => (require(‘@/page/user’).default),

  controller: ‘user.h5Page’,

},

],

//Page template file path

template: ‘screen/index.html’,

//The server renders the packaged JS file

serverJs: resolvePath(‘dist/Page.server.js’),

}

“`

Describe configuration items:

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

Component: corresponding to the react component of the page, the initial data will be processed internally and converted to the preloadedstate or props of the store, in which the front-end routing is used.

controller: corresponding to Egg.js The controller in to get the initial data of the page, and then use the` this.ctx.fishssr . renderpage (initdata) ` implements page rendering.

template: for the template file of the page, the internal ‘stream’ is the string obtained after node renders the react page component. The content of the file is roughly as follows:

“`html

<!DOCTYPE html>

<html lang=‘zh-CN’>

<head>

< title > Netease mutual customers < / Title >

  <link rel=‘stylesheet’ href=‘/css/Page.css’ />

</head>

<body>

  <div id=‘app’>

    {{stream | safe}}

  </div>

<script>

  window.__INITIAL_DATA__ = {{ initialData | safe}};

  </script>

  <script src=‘/js/runtime~Page.js’></script>

  <script src=‘/js/Page.js’></script>

</body>

</html>

“`

serverJs: is the node side package version corresponding to the page entry file. The main code of the entry 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

“`

This code will render the corresponding page components according to the route, and output the rendering code corresponding to the node end and browser end according to different packaging environment.

summary

Egg.js As a complete enterprise node framework, it can be said that the access process is very smooth, and the main focus is to solve their own business needs and back-end cooperation.

At present, the product * * Netease mutual customer * * using this solution has been launched. This solution solves the technical and business requirements mentioned at the beginning of the article. At the same time, the new front-end and back-end cooperation mode it brings has greatly improved not only the development efficiency of the front-end, but also the friendliness to the back-end. At the same time, the front-end can also broaden its own boundaries and meet more needs, such as our operating system and functional API, such as wechat js-sdk certification, which can only be put on the back-end before, but now on the node end. The front-end development is more flexible and reduces a lot of communication costs. But at present, as an external service node application, only these are not enough. It still needs the support of many engineering tools.

Later, I will introduce some of our practices in node engineering, so that node applications can provide more stable services, as well as faster and more convenient troubleshooting.

Recommended Today

Deeply analyze the principle and practice of RSA key

1、 Preface After experiencing many dark moments in life, when you read this article, you will regret and even be angry: why didn’t you write this article earlier?! Your darkest moments include: 1. Your project needs to be connected with the bank, and the other party needs you to provide an encryption certificate. You have […]