The front-end page is now developed as a component. In the browser, the component renders the DOM by adding, deleting, and modifying the DOM through the DOM API. But there is no DOM API on the server side, we can render the component as AN HTML string, and then send it to the browser for rendering, because we already have THE HTML, we can render directly into the DOM, no need to execute JS, so very quickly.

The first browser rendering method is called CSR (Client Side Render), and the second server rendering method is called SSR (Server Side Render).

Obviously, SSR will render images faster because you don’t need to execute JS and parse HTML directly. Therefore, the pages embedded in the APP are basically SSR, so that the experience will be better. In addition, JS execution on low-end machines may be slow. If CSR is used, the page may be blank for a long time.

In addition, SSR is returned directly to HTML, so that search engine crawlers can capture specific content from it, which gives higher search weight, which is more conducive to SEO (Search Engine optimize).

In the pages embedded in the APP, search engine ranking optimization of these two scenarios, we have to do SSR.

Knowing what SSR is and why to do SSR, how to achieve SSR?

Realization principle of SSR

We know that vue uses template to describe the page structure and React uses JSX, but either template or JSX generates the Render function and then executes to generate the VDOM.

Vdom completes CSR by adding, deleting, and modifying DOM through DOM API in the browser, and COMPLETES SSR by concatenating strings on the server.

Vdom is a tree structure, so SSR is the process of traversing the tree and stitching strings.

If you recall that the generate phase of compilation also concatenates strings like this:

Yes, the logic for printing vDOM as a string in SSR is exactly the same as for printing AST as a string in compilation.

Mouth said without evidence, we look at the source code of both and then draw conclusions.

Vue SSR rendering process

Vue provides vue-server-renderer for SSR, which renders vUE components as strings.

It provides the createBundleRenderer API:

const bundle = fs.readFileSync(resolve('./dist/server-bundle.js'), 'utf-8');

createBundleRenderer(bundle)
Copy the code

This bundle is the object code generated by webPack compilation:

You might ask, why wait for WebPack to compile the bundle before rendering?

Esm module syntax, TS syntax, sass syntax, etc., are not supported by Node. You need to compile and bundle your code to run in Node.

This is why the API provided is called createBundleRenderer.

Once the Renderer is created, the renderToStream method is called and rendering begins.

Of course, renderToString can also be called. The difference between the two apis is that one returns the content while rendering, and the other returns the content after rendering.

The first step in rendering, of course, is to execute the incoming bundle:

RunInVm is the code that executes the bundle string, based on the VM package API provided by Node:

With vm.runInContext, you can execute a piece of code in a context.

After execution, an instance of Vue is returned:

Note that this is a Vue instance created in the Node environment, so there is no DOM API and you cannot manipulate the DOM, but you can print it as a string:

The implementation of render here is concatenated string:

After iterating through the VDOM like this, the final HTML is concatenated:

Just return the HTML to the browser. Thus we realize Vue SSR!

Summarize the process of Vue SSR:

The Vue-server-Renderer package provides the createBundleRenderer API to create a Renderer by passing in and compiling packaged bundle code. Renderer has apis for renderToString and renderToStream. Internally, the bundle’s code is executed via vm.runInContext, generating the Vue instance, and rendering the VDOM of the Vue instance into an HTML string. Returning this HTML string implements SSR.

Of course, when we actually do SSR, we don’t use vue-server-renderer directly, we use nuxt.js with a layer wrapped, because it handles routing and so on, and it also encapsulates the tool chain very well, right out of the box.

At this point, we can say that SSR is the process of iterating through vDOM concatenation strings.

Now look at the generate phase of the build:

The compilation process

Parse, Transform, and generate are the following three steps:

The Parse phase converts the source code to an AST (abstract syntax tree), the Transform phase adds, deletes, and modifies the AST, and the generate phase prints the modified AST recursively as a string.

The generate phase, like SSR’s render, is a process of concatenating strings:

For example, Babel’s implementation of Generate looks like this:

Print the while node:

Print the condition node:

Iterating through the AST recursively, printing each node, concatenating strings, generates object code.

Therefore, SSR vDOM render is the same logic as AST generate compiled at the front end, both are concatenated strings.

Of course, there are many different places, such as SSR VDOM is generated by the dynamic implementation of the Render function, while the AST is generated from the source code of the static compilation. It’s just the same logic for concatenating strings.

conclusion

SSR rendering the first screen is fast and conducive to the capture of search engines, so we will do SSR in the pages embedded in the APP and SEO.

SSR works by printing the VDOM as a string, much like the generate phase of the front-end build.

We looked at the source code of the vue-server-render package for Vue, which provides the createBundleRenderer API, passing in the packaged bundle code, and executing it through the VM. Then print the VDOM of the Vue instance as AN HTML string to realize SSR.

We also looked at the source code for Babel Generator, which provides printing logic for each node, recursively traversing the AST and concatenating strings to generate object code.

Although SSR and front-end compilation differ in flow and purpose, they are the same in generating code that prints the tree structure as a string.