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:
- 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;
- Need to develop a web framework specifically for SPA (various frameworks with SSR capabilities, including
Next.js
, etc.) - search engine crawler
- Problems with browser history (various
router
based onpushState
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
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 versioncra
command to create a new project, the startup will report a problem similar toMini.... is not a function
. This is becausemini-css-extract-plugin
the plugin version is updated, only need to passpackage.json
resolutions
restrictionmini-css-extract-plugin
in ---4a0c93dd7d9cc2c86b9f8d90d25fcf44--- with version2.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:
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
命令后, start
, nginx
的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
orchunk.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 ofJSX
HTML
and insert it into the templateHTML
- 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.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。