preface

I have nothing to do but study SSR. The main reason is that last week, a back-end student said in a group technology sharing that he was particularly interested in the separation of the front and back ends and server side rendering. After he shared the back-end micro service, he invited me to share the server side rendering next week. The boss made me share it next week.

After reading this article, you will know that:

  • What is server-side rendering and what is the difference from client-side rendering?
  • Why is server-side rendering needed, and what are the pros and cons of server-side rendering?
  • How to isomorphize a VUE project?

Original address welcome star

Definition of server-side rendering

Before we talk about service rendering, let’s review the page rendering process:

  1. The browser requests an HTML text
  2. The renderer parses the HTML text and builds a DOM tree
  3. While parsing HTML, download and build stytle rules if you encounter inline styles or style scripts, or download execution scripts if you encounter JavaScript scripts.
  4. After the DOM tree and style rules are built, the render process merges them into a render tree.
  5. The render process starts to layout the render tree, generating a layout tree.
  6. The rendering process draws the layout tree and generates a drawing record
  7. The rendering process layers the layout tree, rasterizes each layer separately, and produces composite frames
  8. The renderer process sends the composited frame information to the GPU process for display on the page

As you can see, rendering a page is essentially the process by which the browser converts HTML text into page frames. Today, most WEB applications use JavaScript frameworks (Vue, React, Angular) for page rendering. That is, when JavaScript scripts are executed, the HTML page is already parsed and the DOM tree is built. JavaScript scripts simply change the structure of the DOM tree dynamically to make the page look like it wants to. This rendering method is called dynamic rendering, or client Side rende.

So what is server side render? As the name implies, server-side rendering is when the browser requests the page URL, the server will assemble the HTML text we need and return it to the browser. After the HTML text is parsed by the browser, it can directly build the desired DOM tree and display it in the page without the execution of JavaScript script. This server-side HTML assembly process is called server-side rendering.

The origin of server-side rendering

Back in the days before AJAX, in the era of web1.0, when almost all applications were server-side renderers (servers rendering instead of today’s server rendering), page rendering would look something like this: the browser would request the URL of the page, the server would receive the request, query the data in the database, Data is thrown into back-end component templates (PHP, ASP, JSP, etc.) and rendered into HTML fragments. The server then assembles these HTML fragments into a complete HTML, and finally returns them to the browser. At this point, the browser has received a complete HTML text that has been dynamically assembled by the server. The HTML is then rendered to the page without any JavaScript code involved.

Client-side rendering

In the era of WEB1.0, server-side rendering seemed to be the best way to render at that time, but with the increasing complexity of business and the subsequent emergence of AJAX, the shortcomings of WEB1.0 server rendering gradually began to be exposed.

  • Every time a small module of the page is updated, the page needs to be re-requested, the database needs to be re-queried, and the HTML needs to be re-assembled
  • The jumble of front-end JavaScript code and back-end (JSP, PHP, JSP) code makes increasingly complex WEB applications difficult to maintain

And at that time, there was no position of front-end engineer at all, the front-end JS work was generally handled by the back-end student jQuery. But as the front page after gradually complicated, the back-end to found js good trouble, although very simple, but too many holes, so the company has recruited some of the people write js, namely front-end, this time, before and after the despise the chain, for the back-end despise front end, because the backend feel js too simple, does not write a page of special effects (js), CSS, not a real programmer at all.

With the advent of NodeJS, the front end saw a turning point. In order to get rid of the back end’s finger-pointing, the front end started a movement to separate the front end from the back end, hoping to develop independently. The front and back end separation, which appears to be code separation, is actually for the front and back end people separation, that is, the front and back end separation, the front end is no longer owned by the back end team.

After the separation of the front and back ends, the web is treated as a Single Page Application (SPA), with the front end team taking over all the Page rendering and the back end team providing all the DATA query and processing apis. The general process is like this: First, the browser requests the URL, and the front-end server returns an empty static HTML file (without any database lookup or template assembly) loaded with JavaScript scripts and CSS stylesheets for rendering the page. The browser takes the HTML file and loads the scripts and stylesheets. At this time, the script requests the API provided by the back-end service to obtain the data. After obtaining the data, it dynamically renders the data to the page through JavaScript script to complete the page display.

This is a separate front and back rendering mode, also known as client rendering (CSR).

Server side rendering

With the growth of single-page apps (SPA), programmers are finding SEO (Search Engine Optimazition) problematic, and JavaScript is getting bloated as applications get more complex. The first screen rendering is also slower than the server rendering of Web1.0.

Their choice of road, kneel also want to go down. So the front-end team chose to use NodeJS to render the page on the server, which led to server-side rendering again. The general process is similar to that of client rendering. First, the browser requests the URL. After receiving the URL request, the front-end server requests the data from the back-end server according to different URLS. At the same time, the browser loads and executes JavaScript scripts to bind events to elements on the page, making the page interactive. When the user interacts with the browser page, such as jumping to the next page, the browser will execute JavaScript scripts. The back-end server requests the data, retrieves the data, and then executes the JavaScript code again to render the page dynamically.

Pros and cons of server-side rendering

What are the advantages of server-side rendering over client-side rendering?

Conducive to SEO

Good for SEO is basically good for crawlers to crawl your page, and then when other people use search engines to search for relevant content, your page will rank higher and your traffic will be higher. So why is server rendering better for crawling your page? In fact, crawlers are also divided into low-level crawlers and high-level crawlers.

  • Low-level crawlers: they only request urls and crawl whatever HTML the URL returns.
  • Advanced crawler: Request URL, load and execute JavaScript script rendering page, crawl JavaScript rendered content.

In other words, a low-level crawler can do nothing about a client-rendered page because the HTML returned is an empty shell that requires JavaScript script execution before rendering the actual page. At present, some old crawlers of baidu, Google, Microsoft and other companies still belong to low-level crawlers. They use server-side rendering and are more friendly to these low-level crawlers.

The white screen time is shorter

In contrast to client-side rendering, server-side rendering already gets an HTML text with data after the browser requests the URL. The browser simply parses the HTML and builds the DOM tree directly. The client rendering needs to get an empty HTML page first, at which time the page has entered a white screen. After that, it needs to load and execute JavaScript, request the back-end server to obtain data, and render the page with JavaScript before the final page can be seen. Especially in complex applications, JavaScript scripts need to be loaded. The more complex the application is, the more and larger the JavaScript scripts need to be loaded. As a result, the first screen of the application takes a long time to load, which reduces the experience.

Server side rendering shortcomings

Not all WEB applications must use SSR, and this is a trade-off for the developer, as server-side rendering brings the following issues:

  • Code complexity increases. In order to achieve server-side rendering, the application code needs to be compatible with both server-side and client-side running conditions, while some of the external extension libraries that rely on can only run on the client side and need special processing to run in the server rendering application.
  • More SERVER load balancers are required. As the server has increased the demand for rendering HTML, nodeJS service, which originally only needed to output static resource files, has increased the IO for data acquisition and CPU for rendering HTML. If the traffic suddenly increases, the server may go down. Therefore, it is necessary to use the cache strategy of response and prepare the corresponding server load.
  • More requirements related to build setup and deployment. Unlike a fully static single-page application (SPA) that can be deployed on any static file server, a server rendering application needs to be in a Node.js Server environment.

Therefore, before using the server to render SSR, developers need to consider the input and output ratio, for example, most application systems do not need SEO, and the first screen time is not very slow, if using SSR, but a storm in a molebowl.

homogeneous

Given the pros and cons of server rendering, what do we need to do if we need to use server-side rendering in a project? That’s the isomorphism of our project.

Definition of isomorphism

In server-side rendering, there are two ways to render a page:

  • The front-end server requests the back-end server to fetch the data and assemble the HTML back to the browser, which directly parses the HTML and renders the page
  • During the interaction, the browser requests new data and dynamically updates the rendered page

One of the differences between these two rendering methods is that the HTML is assembled on the server side and the HTML is assembled on the client side. The runtime environment is different. Isomorphism means that a piece of code can be executed on both the server side and the client side, and the effect of execution is the same, which is to complete the assembly of the HTML and display the page correctly. That is, a piece of code can be rendered by both the client and the server.

Isomorphism conditions

What conditions do we need to satisfy in order to achieve isomorphism? First of all, let’s think about the composition of a page in an application. If we use vue.js, when we open a page, we first open the URL of the page. This URL can be matched by the route of the application to find the specific page. From the perspective of application, view = template + data, so in Vue.js, template can be understood as component, data can be understood as data model, that is, responsive data. Therefore, for homogeneous applications, we must realize the sharing of client and server routes, model components, and data models.

practice

After knowing the principle of server rendering and isomorphism, start from scratch, step by step to complete an isomorphism, through practice to understand SSR.

Implement basic NODEJS server rendering

First, simulate a simple server rendering that simply returns the HTML files we need to the page.

const express = require('express');
const app = express();

app.get('/'.function(req, res) {
    res.send(`   SSR   

hello world

`
); }); app.listen(3001.function() { console.log('listen:3001'); }); Copy the code

After starting localhost:3001, you can see hello World displayed on the page. And open the page source code:

In other words, when the browser gets the HTML source code returned from the server, it can simply display Hello World without loading any JavaScript.

Implement basic VUE client rendering

Let’s create a new vue project with vue-CLI and modify an app. vue component:

<template>
  	<div>
    		<p>hello world</p>
    		<button @click="sayHello">say hello</button>
  	</div>
</template>

<script>
export default {
    methods: {
        sayHello() {
	          alert('hello ssr'); }}}</script>
Copy the code

Then run NPM Run serve to start the project, open the browser, you can also see the page shows Hello World, but open our open page source code:

In addition to the simple compatibility handling of the noscript tag, there is only a simple div tag with the id of app, without any words about Hello world, so it can be said that this is an empty page (white screen), and after loading the JavaScript script with the following script tag, These scripts start the page, and when they finish, hello World is displayed as normal. In other words, the actual rendering of Hello World is a JavaScript script.

Isomorphic VUE project

Build configuration

Template component sharing, in fact, is the use of the same set of component code, in order to achieve Vue components can run in the server, first we need to solve the code compilation problem. In general, vue projects use WebPack for code construction. Similarly, server-side code construction can also use Webpack, borrow the official one.

Step 1: Build the server-side code

As you can see from the previous figure, the build results need to be run on the NodeJS server after the server-side code is built. However, there are a few things to note when building server-side code:

  • There is no need to compile CSS, style sheets are only needed when the browser (client) is running.
  • The target runtime environment of the build is CommonJS, and the modular mode of NodeJS is CommonJS
  • Instead of cutting code, NodeJS is more efficient by loading all code into memory at once

As a result, we get a server-side Webpack build configuration file called vue.server.config.js

const nodeExternals = require("webpack-node-externals");
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = {
    css: {
        extract: false // Do not extract CSS
    },
    configureWebpack: () = > ({
        entry: `./src/server-entry.js`.// Server entry file
        devtool: 'source-map'.target: 'node'.// Build for nodeJS environment
        output: {
            libraryTarget: 'commonjs2' // Build the target load pattern commonjs
        },
        // Skip node_mdoules, which is loaded automatically at runtime without compiling
        externals: nodeExternals({
            allowlist: [/\.css$/] // Allow CSS files for CSS Module convenience
        }),
        optimization: {
            splitChunks: false // Turn off code cutting
        },
      	plugins: [
            new VueSSRServerPlugin()
        ]
    })
};
Copy the code

Use the server-plugin provided by vue-server-renderer. This plugin is mainly used in conjunction with the client-plugin described below. It is mainly used to realize hot loading, source-map and HTML file generation of NodeJS during development.

Step 2: Build the client code

When we build the client code, we use the client execution entry file, and when we’re done, we run the build in the browser, but in the server rendering, the HTML is rendered by the server, which means that the server decides which JavaScript scripts we want to load, Since the script tags in HTML are concatenated by the server, when the client code is built, we need to use the plug-in to generate a build result list that tells the server which JS scripts and CSS stylesheets need to be loaded on the current page.

So we get the client build configuration, vue.client.config.js

const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

module.exports = {
    configureWebpack: () = > ({
        entry: `./src/client-entry.js`.devtool: 'source-map'.target: 'web'.plugins: [
            new VueSSRClientPlugin()
        ]
    }),
    chainWebpack: config= > {
      	// Remove all HTML configuration for client-side generation, since it has been handed over to back-end generation
        config.plugins.delete('html');
        config.plugins.delete('preload');
        config.plugins.delete('prefetch'); }};Copy the code

Vue – SSR -client-manifest.json is used to generate and construct the added manifest. When the server renders the page, Use this listing to render script tags (JavaScript) and link tags (CSS) in HTML.

Next, we need to hand both vue.client.config.js and vue.server.config.js to vue.config.js, the build configuration file built into VUe-CLI, using different configurations depending on the environment variables

// vue.config.js
const TARGET_NODE = process.env.WEBPACK_TARGET === 'node';
const serverConfig = require('./vue.server.config');
const clientConfig = require('./vue.client.config');

if (TARGET_NODE) {
    module.exports = serverConfig;
} else {
    module.exports = clientConfig;
}
Copy the code

Use cross-env to differentiate the environment

{
  "scripts": {
    "server": "babel-node src/server.js"."serve": "vue-cli-service serve"."build": "vue-cli-service build"."build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build --mode server"}}Copy the code

Template Component Sharing

Step 1: Create a VUE instance

To implement template component sharing, we need to get the Vue rendering instance in common code, as shown in createApp:

import Vue from 'vue';
import App from './App';

export default function createApp (context) {
    const app = new Vue({
        render: h= > h(App)
    });
  	return {
      	app
    };
};
Copy the code
Step 2: The client instantiates VUE

Create the client project entry file, client-entry.js

import Vue from 'vue'
import createApp from './createApp';

const {app} = createApp();

app.$mount('#app');
Copy the code

Client-entry. js is the entry file for browser rendering. After the browser loads the code compiled by the client, the component will be rendered to the element node whose ID is APP.

Step 3: Server instantiate VUE

Create the server side code entry file, server-entry.js

import createApp from './createApp'

export default context => {
    const { app } = createApp(context);
    return app;
}
Copy the code

Server-entry. js is the entry file for the server to render vue components. After the browser accesses the server through the URL, the server needs to use the functions provided by server-entry.js to render components into HTML.

Step 4: HTTP service

With everything ready, we need to modify the nodejs HTTP server startup file. First, load the webpack build results of the server-side code server-entry.js

const path = require('path');
const serverBundle = path.resolve(process.cwd(), 'serverDist'.'vue-ssr-server-bundle.json');
const {createBundleRenderer} = require('vue-server-renderer');
const serverBundle = path.resolve(process.cwd(), 'serverDist'.'vue-ssr-server-bundle.json');
Copy the code

Load the webpack build result of the client code client-entry.js

const clientManifestPath = path.resolve(process.cwd(), 'dist'.'vue-ssr-client-manifest.json');
const clientManifest = require(clientManifestPath);
Copy the code

Create an HTML renderer using createBundleRenderer with vue-server-renderer:

const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
const renderer = createBundleRenderer(serverBundle, {
    template,  // Use HTML templates
    clientManifest // Pass in a list of client build results
});
Copy the code

Create the HTML template, index.html

<html>
  <head>
    <title>SSR</title>
  </head>
  <body>
    <! --vue-ssr-outlet-->
  </body>
</html>
Copy the code

In the HTML template, all link stylesheet tags will be automatically injected through the incoming client render result clientManifest, and placeholders will be replaced with specific HTML fragments and script script tags after the template component is rendered.

After the HTML is ready, we suspend all routing requests in the server

const express = require('express');
const app = express();

/* Code todo instantiate renderer */

app.get(The '*'.function(req, res) {
    renderer.renderToString({}, (err, html) = > {
        if (err) {
            res.send('500 server error');
            return; } res.send(html); })});Copy the code

Next, we build the client and server projects, execute Node Server.js, open the page source code,

< span style = “color: # 0000ff; color: # 0000FF; line-height: 22px;

app.use(express.static(path.resolve(process.cwd(), 'dist')));
Copy the code

Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = Rendered = rendered = rendered = rendered

Since the server has rendered the HTML, we obviously don’t have to throw it away and recreate all the DOM elements. Instead, we need to “activate” the static HTML and then make it dynamic (able to respond to subsequent data changes).

If you examine the output rendered by the server, a special attribute is added to the root element of the application:

<div id="app" data-server-rendered="true">
Copy the code

Data-server-rendered is a special attribute that lets the client Vue know that the HTML portion was rendered by the Vue on the server and should be mounted in active mode.

Route sharing and synchronization

After completing the template component sharing, the next step is to complete the route sharing. The route used by our previous server is *, which accepts any URL. This allows all URL requests to be processed by Vue routing, thus completing the reuse of client and server routes.

Step 1: Create a ROUTER instance

For reuse, as with createApp, we create a createrouter.js

import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home';
import About from './views/About';
Vue.use(Router)
const routes = [{
    path: '/'.name: 'Home'.component: Home
}, {
    path: '/about'.name: 'About'.component: About
}];
export default function createRouter() {
    return new Router({
        mode: 'history',
        routes
    })
}
Copy the code

Create the router in createapp.js

import Vue from 'vue';
import App from './App';
import createRouter from './createRouter';

export default function createApp(context) {
    const router = createRouter(); // Create a Router instance
    const app = new Vue({
        router, // Inject router into the root Vue instance
        render: h= > h(App)
    });
    return { router, app };
};
Copy the code
Step 2: Route matching

After the router is ready, modify server-entry.js and pass the requested URL to the router so that when creating the app, it can match the route according to the URL and know which components need to be rendered

import createApp from './createApp';

export default context => {
    // Since it might be an asynchronous routing hook function or component, we'll return a Promise,
    // So that the server can wait for everything to be ready before rendering.
    return new Promise((resolve, reject) = > {
        const { app, router } = createApp();
        // Set the router location on the server
        router.push(context.url)
        // onReady waits until the router has resolved possible asynchronous components and hook functions
        router.onReady(() = > {
            const matchedComponents = router.getMatchedComponents();
            Reject if the route cannot be matched, reject, and return 404
            if(! matchedComponents.length) {return reject({
                    code: 404
                });
            }
            // Promise should resolve the application instance so that it can be rendered
            resolve(app)
        }, reject)
    })
}
Copy the code

Change the route to server.js to pass the URL to the renderer

app.get(The '*'.function(req, res) {
    const context = {
        url: req.url
    };
    renderer.renderToString(context, (err, html) = > {
        if (err) {
            console.log(err);
            res.send('500 server error');
            return; } res.send(html); })});Copy the code

For testing, we changed app. vue to router-view

<template>
    <div id="app">
        <router-link to="/">Home</router-link>
        <router-link to="/about">About</router-link>
        <router-view />
    </div>
</template>
Copy the code

Home.vue

<template>
    <div>Home Page</div>
</template>
Copy the code

About.vue

<template>
    <div>About Page</div>
</template>
Copy the code

Compile, run, look at the source code

Clicking route does not refresh the page, but redirects the client route, as expected.

Data model sharing and state synchronization

Previously we simply implemented server-side rendering, but in reality we need to fetch and render the data we need to render into HTML when we visit the page. In other words, before rendering the HTML, we need to get all the data ready and pass it to the renderer.

Normally, in Vue, we hand over state data to Vuex for management. Of course, the state can also be stored inside the component, but the component needs to synchronize the data itself during instantiation.

Step 1: Create a STORE instance

The first step, similar to createApp, is to create createstore.js, which instantiates the Store and provides it to both clients and servers

import Vue from 'vue';
import Vuex from 'vuex';
import {fetchItem} from './api';

Vue.use(Vuex);

export default function createStore() {
    return new Vuex.Store({
        state: {
            item: {}},actions: {
            fetchItem({ commit }, id) {
                return fetchItem(id).then(item= > {
                    commit('setItem', item); })}},mutations: {
            setItem(state, item){ Vue.set(state.item, item); }}})}Copy the code

Actions encapsulates the function that requests the data, and mutations sets the state.

Add createStore to createApp and inject store into the VUE instance to make the Store instance available to all VUE components

export default function createApp(context) {
    const router = createRouter();
    const store = createStore();
    const app = new Vue({
        router,
        store, // Inject store into the root Vue instance
        render: h= > h(App)
    });
    return { router, store, app };
};
Copy the code

For testing purposes, we mock out a remote service function called fetchItem that queries the corresponding item

export function fetchItem(id) {
    const items = [
        { name: 'item1'.id: 1 },
        { name: 'item2'.id: 2 },
        { name: 'item3'.id: 3}];const item = items.find(i= > i.id == id);
    return Promise.resolve(item);
}
Copy the code
Step 2: STORE connects components

In general, we need to access the route to determine which parts of the data to fetch, which also determines which components to render. In fact, the data required for a given route is also the data required to render components on that route. Therefore, we need to place the data prefetch logic function in the component of the route.

Define a static function asyncData in the Home component. Note that since this function is called before the component is instantiated, it cannot access this. Store and route information need to be passed in as parameters

<template>
<div>
    <div>id: {{item.id}}</div>
    <div>name: {{item.name}}</div>
</div>
</template>

<script>
export default {
    asyncData({ store, route }) {
        // When the action is triggered, a Promise is returned
        return store.dispatch('fetchItems', route.params.id)
    },
    computed: {
        // Get the item from the store state object.
        item() {
            return this.$store.state.item; }}}</script>
Copy the code
Step 3: The server gets the data

At the entrances to the server file server – entry. Js, we match the router through the URL route. GetMatchedComponents got going to render () components, this time we can call the component internal asyncData method, will be needed after all data access, Pass to the renderer context.

Modify createApp to call asyncData after the routing component matches, fetch the data and pass it to the Renderer

import createApp from './createApp';

export default context => {
    // Since it might be an asynchronous routing hook function or component, we'll return a Promise,
    // So that the server can wait for everything to be ready before rendering.
    return new Promise((resolve, reject) = > {
        const { app, router, store } = createApp();
        // Set the router location on the server
        router.push(context.url)
        // onReady waits until the router has resolved possible asynchronous components and hook functions
        router.onReady(() = > {
            const matchedComponents = router.getMatchedComponents();
            Reject if the route cannot be matched, reject, and return 404
            if(! matchedComponents.length) {return reject({ code: 404})}// Call asyncData() on all matching routing components
            Promise.all(matchedComponents.map(Component= > {
                if (Component.asyncData) {
                    return Component.asyncData({
                        store,
                        route: router.currentRoute
                    });
                }
            })).then(() = > {
                // The state is passed to the renderer's context so that later clients can activate the datacontext.state = store.state resolve(app) }).catch(reject); }, reject); })}Copy the code

After storing state into context, when the server renders HTML, that is, when the template is rendered, context.state is serialized to window.__initial_state__ so that the client can activate the data.

Step 4: Client activates status data

After the server pre-requests the data, it injects the data into the component, renders the component, converts it into HTML, and then vomits it to the client. In order to activate the DOM node returned by the back-end after the HTML is parsed, the client needs to synchronize the store state used by the back-end rendering component to the store of the browser. Rendered pages will be rendered in accordance with server rendered data to complete DOM activation, and data-server-rendered markers will be rendered accordingly.

In server-side rendering, state has been serialized to window.__initial_state__, for example, if we visit http://localhost:3001? Id =1, then look at the page source code

As you can see, the state has been serialized to window.__initial_state__. All we need to do is to synchronize this window.__initial_state__ to the store of the client before rendering it to the client

const { app, router, store } = createApp();

if (window.__INITIAL_STATE__) {
  	// Activate status data
    store.replaceState(window.__INITIAL_STATE__);
}

router.onReady(() = > {
    app.$mount('#app'.true);
});
Copy the code

The state synchronization of the data model is accomplished by synchronizing window.__initial_state__ inside the store using the store’s replaceState function.

To this a simple VUE isomorphism project has been completed, project complete source code please see VUE-SSR -demo

conclusion

When the browser visits the server rendering project, the server passes the URL to the pre-selected and constructed VUE application renderer. After the renderer matches the component of the corresponding route, it executes the asyncData method defined in the component to get the data and passes the obtained data to the context of the renderer. Template is used to assemble HTML, and both HTML and state are presented to the front-end browser. After loading the constructed client VUE application, the browser synchronizes the state data to the front-end store, and activates the HTML text returned by the back-end which is parsed into DOM elements by the browser according to the data. Complete the synchronization of data state, routing and components, while making the page straight out, less white screen time, a better loading experience, and more conducive to SEO.

Personally, I think understanding server-side rendering is helpful to improve the comprehensive ability of front-end engineers, because it covers not only front-end framework, but also front-end construction and back-end content. It is a cost-effective knowledge, so it is useless to learn, come on!

reference

  • Why is server-side rendering HTML all the rage now?
  • Vue. Js server rendering guide
  • Understand server rendering from the ground up