3

I still want to talk, but I want to talk, but it's cool and it's a good autumn----"Ugly Slave · Shubo Mountain Road Middle Wall" Xin Qiji

What is SSR

ShadowsocksR? Onmyoji? FGO?

Server-side rendering (SSR) is the ability of an application to render a web page by displaying it on the server instead of in the browser. The server sends the client a fully rendered page (just an HTML page to be exact). At the same time, combined with the client's JavaScript bundle makes the page run. As opposed to SSR, there is also a Client-side rendering (CSR). The biggest difference between CSR and SSR is whether the rendering is provided by the client or the server, and there is another kind of essence. Therefore, if the difference between CSR and SSR is not highlighted below, the default is the same.

Why SSR

Thanks to the development of front-end frameworks such as React webpack the separation of front and back ends, the popularity of compilation tools such as ---e868585671e9f959336af6eec8c28dc4---, and ajax to achieve partial page refresh, we now The application no longer needs to obtain the page from the server like the previous application, and can dynamically modify the local page data to avoid frequent page jumps that affect the user experience and other problems. That is, SPAs are increasingly becoming the mainstream application model.
But the use of SPA, in addition to the advantages mentioned above, will inevitably bring disadvantages. for example:

  1. Since all the JavaScript libraries required by the page need to be loaded before the page loads, it takes a long time to open the page for the first time;
  2. Need to develop a web framework specifically for SPA (various frameworks with SSR capabilities, including Next.js , etc.)
  3. search engine crawler
  4. Problems with browser history (various router based on pushState 197b302e17ae79e0e6835cdca5b053f7---)

In order to solve the problems of 1. and 3. mentioned above, SSR began to enter the stage of history.

How to do SSR

file

Based on the above theory, we can design a SSR React .

First, we initialize a React project through the create-react-app command, which can be understood as a project with the simplest functions. We will implement a SSR function based on this project.

 # Yarn
$ yarn create react-app ssr-demo
⚠️ Students need to pay attention when practicing, when the current version cra command to create a new project, the startup will report a problem similar to Mini.... is not a function . This is because mini-css-extract-plugin the plugin version is updated, only need to pass package.json resolutions restriction mini-css-extract-plugin in ---4a0c93dd7d9cc2c86b9f8d90d25fcf44--- with version 2.4.5 can

The directory where the project is generated is as follows:

 ./
├── README.md
├── build
├── node_modules
├── package.json
├── public
├── src
└── yarn.lock

The dependencies have been automatically installed, and we can see the simplest page in the " local environment " when starting the project.

Next, let's implement an SSR function. First, we need to install express (if it is CSR then this step is not required)

 yarn add express

After the installation is complete, we need to write the following code in the server/index.js file

 import express from "express";
import serverRenderer from "./serverRenderer.js";

const PORT = 3000;
const path = require("path");

const app = express();
const router = express.Router();

// 当爬虫的请求进来的时候,把所有请求导向 serverRenderer 路由
router.use("*", serverRenderer);

app.use(router);
app.listen(PORT, () => console.log(`listening on: ${PORT}`));

Among them serverRenderer The content of the file is as follows:

 import React from "react";
import ReactDOMServer from "react-dom/server";

import App from "../src/App";

const path = require("path");
const fs = require("fs");

export default (req, res, next) => {
  // 获取当前项目的 HTML 模板文件路径
  const filePath = path.resolve(__dirname, "..", "build", "index.html");

  // 读取该文件
  fs.readFile(filePath, "utf8", (err, htmlData) => {
    if (err) {
      console.error("err", err);
      return res.status(404).end();
    }

    // 借助 react-dom 依赖下的方法将 JSX 渲染成 HTML string
    const html = ReactDOMServer.renderToString(<App />);

    // 将 HTML string 替换到 root 中
    return res.send(
      htmlData.replace('<div id="root"></div>', `<div id="root">${html}</div>`)
    );
  });
};

As above, we have completed a very simple server with SSR function.
But this is not enough, we also need to create a new parser.js in the root directory and convert ESM to CommonJS to run, the code is as follows:

 require("ignore-styles");
require("@babel/register")({
  ignore: [/(node_modules)/],
  presets: ["@babel/preset-env", "@babel/preset-react"],
});

require("./server");

Explain the role of the package introduced above:

  • @babel/register :该依赖会将node 后续运行时所需要require .es6.es.jsx.mjs and .js will be automatically converted by Babel.
  • ignore-styles : This dependency is also a Babel hook, which is mainly used to ignore the import of style files during Babel compilation.

After the above operations, we first yarn build out our product, and then start the SSR service through node parser.js .


After the above operations, we have designed a very simple but reasonable SSR server. As a comparison, we simply compare with Next.js .

In the Next.js project's root directory package.json , we can see that express is also selected as the server.

 ...
"eslint-plugin-react-hooks": "4.2.0",
"execa": "2.0.3",
"express": "4.17.0",
"faker": "5.5.3",
...

~/packages/next/server/next.ts文件夹中, Next.js createServer方法,启动一个---b778d7c38c2e017695f6980526d13a21---对象, NextServer Render the template template.
The command call is as follows:

file

On the official website of [Next.js](https://nextjs.org/docs/basic-features/pages#server-side-rendering) , we can see that it supports dynamic acquisition of interface data through the getServerSideProps function on the page. In fact, in most framework libraries that support SSR, there are similar designs. Because of the application of SPA, it is inevitable to obtain dynamic data through the server and render the page, and the design ideas of SSR for rendering dynamic data are relatively consistent. That is, export a fixed method in the same file of the component of the page, and return a fixed format. The framework will use this data as initial data for SSR rendering of the page.


We take Next.js as an example to understand the general design idea of SSR, then let's understand the general idea of CSR.

CSR can be understood as a castrated version of SSR, which only implements the pre-rendering function of SSR. It is generally used for static websites and does not have the function of dynamically obtaining data.

The rendering idea of CSR is the same as that of SSR. The difference is that SSR needs to be installed express and CSR does not need to be installed express . This also leads to the difference in the deployment process of CSR and SSR. SSR 项目如Next.js应用在执行完build命令后, startnginx的reverse proxy. And CSR projects such as Umi still need a proxy for nginx .

The biggest difference between CSR is the difference in the compiled product. Usually the compiled products of a front-end project include the following:

  • bundle.js or chunk.js
  • index.html
  • index.css
  • public/*
  • Other related files, such as rss.xml etc.

After the project with CSR is compiled, there will be more HTML files, and the structure of these files will be generated according to the route. For example: our current route is as follows:

  • /a
  • /b

Corresponding to ComponentA and ComponentB respectively, then a.html and b.html cab699700a96886aaad6--- will be generated in our compiled product. After we deploy the product to the nginx service, the pre-rendering function can be implemented.

To achieve the above functions, the most important steps are as follows:

  • Get the route to the current item
  • Get the component corresponding to the route. If the component has not been compiled, it needs to be compiled
  • Render ---0d8843f24fec9685983f4fb018dc7acd--- as --- react-dom with the ability of JSX HTML and insert it into the template HTML
  • Create a folder according to the route in the compiled product, and generate the resulting HTML into the corresponding path

Here, we understand the entire SSR process, I believe everyone has a certain degree of understanding of SSR. Most of the frameworks in the current community do not require us to do SSR by ourselves. Our understanding of the rendering process helps us stay the same when dealing with a wide variety of frameworks.


袋鼠云数栈UED
277 声望33 粉丝

我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。