preface

When we use React/Vue to develop SPA, we always meet the need to improve the first screen rendering speed. At this time, we usually think of using SSR for optimization. What if we want to further improve the speed? Most are optimized in terms of interface response speed and amount of data rendered on the first screen. But let’s think about it a little differently. Can’t we optimize from the first renderToString step? Rax gives us a good idea.

What is Rax?

According to the official website: super lightweight, high performance, easy to use front-end solutions. Multi-terminal operation of one development liberates repetitive work, focuses on product logic and improves development efficiency.

React is a multiterminal framework based on React. This article is not about Rax, so we will not expand it. If you are interested, please visit the official website. Here’s a look at how Rax’s supposedly hybrid rendering mode of static templates and dynamic components is far ahead of its peers in terms of performance.

SSR server rendering

I won’t go into too much detail about what server-side rendering is, but if you don’t already know, there are plenty of detailed articles in the community that I recommend reading first. Rax’s SSR performance is much better than React’s. How did Rax do it? Let’s move on.

React(16.12.0)#renderToString x 6,047 ops/ SEC ±1.73% (85 runs sampled Inferno(7.3.3 runs)#renderToString x 3,335 ops/ SEC ±1.77% (82 runs sampled) Preact(10.2.1)#renderToString x 1005 ops/SEC plus or minus 1.10% (86 runs the javax.media.sound.sampled) Marko (4.18.33) # renderToString x 10291 ops/SEC plus or minus 1.64% (86 runs the javax.media.sound.sampled) Xtemplate (4.7.2)#render x 20,600 ops/ SEC ±2.89% (84 runs sampled) The benchmark was run on: Linux 5.0.0-1027-Azure CPU: Intel(R) Xeon(R) CPU E5-2673 V4 @ 2.30GHz SYSTEM MEMORY: 6.782737731933594GB NODE VERSION: v10.18.1Copy the code

Source code analysis

First, take a look at how the React – DOM renderToString method turns your component into an HTML string. If you read the source code, the rest of the logic is pretty simple: take the data and iterate through your component object, layer by layer, until you have a complete HTML string. As for Rax, after reading his source code, I found that the core of his Rax RenderToString method is not much different from React, which is a recursive lookup component. The key point lies in the compilation stage of Webpack. Add-on babel-plugin-transform-jsx-to-html is a plugin provided by Rax, which is used to precompile and process static content in the component during webpack construction.

Case analysis

export default class App extends React.Component {
  state = {};

  render() {
    const props = this.props || {};

    return (
      <div className="root" onClick={this.state.onClick}>
        <Banner cacheKey={"banner"} data={props.bannerData} />
        <List cacheKey={"list"} data={props.listData} />
      </div>); }};Copy the code

React

The react. createElement object is a standard React component object. The react-DOM renderToString provides a complete HTML string.

{
   '$$typeof': Symbol(react.element),
   type: 'div',
   key: null,
   ref: null,
   props: { 
     className: 'root',
     onClick: undefined,
     children: [ [Object], [Object] ]
   },
  _owner: null 
 }
Copy the code

Rax

Rax builds static template data in advance during the edit phase. This will save time during the actual SSR rendering and improve performance

[ 
  { __html: '<div class="root"' },
  { __attrs: { onClick: undefined } },
  { __html: '>' },
  { 
    type: [Function: r],
    key: null,
    ref: null,
    props: { data: [Array] },
    _owner: null
  },
  {
    type: [Function: r],
    key: null,
    ref: null,
    props: { data: [Array] },
    _owner: null
  },
  { __html: '</div>' } 
]
Copy the code

The following uses a map to summarize the differences between the two SSR programs, hoping to inspire you after reading them, and also hope to point out the bad places.