我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

终于开始讲react的脱水和注水功能了,也就是“水合”。其中的“脱水”过程,实际上也可以理解为服务器端把事件绑定之类的功能都去掉,仅仅像传统页面一样,考虑数据的输出即可。目前脱水函数,有两个。本文讲述其中第一个:renderToString()

苏南大叔:React SSR,如何理解和使用脱水函数renderToString()? - rednder-to-string
React SSR,如何理解和使用脱水函数renderToString()?(图4-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程心得体会。本文测试环境:nodejs@20.18.0create-react-app@5.0.1react-router-dom@6.27.0react@18.3.1。值得一提的是,react官方,目前并不推荐使用renderToString()

renderToString()

苏南大叔的理解就是:使用renderToString()函数,把以往以jsx+js组合呈现的react代码,“脱水”成无限接近于纯html的字符串的过程。当然,这个最终得到的字符串,也丧失了react的各种活性。

官方对这个函数的解释是:

官方文档里面,定义的函数原型是:

renderToString(reactNode, options?) 

由于renderToString()的执行过程,需要耗时。而且,这个函数的使用场合多发生在服务器端。为了不拖慢服务器端的代码表现,(实际上就是第一个字节到达浏览器的时间,这个重要页面指标)。官方推荐使用其它支持pipe输出的函数,待议。

1、客户端其实也能运行renderToString()。但是角色分类上,renderToString()是使用在服务器端的代码。
2、options参数,基本上也没有啥大用途。暂时无视。

引入 renderToString

在目前最新的React中,是这样引入的。注意:/server字样。这是和老版本最大的不同之处。

import { renderToString } from "react-dom/server";

最简单demo

这里仅仅是个最简单的demo,和实际应用有较大差距。

import React from "react";
import { renderToString } from "react-dom/server";
const App = function () {
  return <div>苏南大叔</div>;
};
const html = renderToString(<App />);
console.log(html);

苏南大叔:React SSR,如何理解和使用脱水函数renderToString()? - 最简单的demo
React SSR,如何理解和使用脱水函数renderToString()?(图4-2)

搭配 http 服务输出

renderToString()的设计之初,就是在服务器端输出无限接近纯正html的目的的。所以,这里结合最简单的http服务,同时搭配react routerStaticRouter使用。

import http from "http";
import React from "react";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom/server";
import { Routes, Route, useParams } from "react-router-dom";
function Post() {
  var { id } = useParams();
  return <div>No.{id} article</div>;
}
function requestHandler(req, res) {
  let html = renderToString(
    <StaticRouter location={req.url}>
      <Routes>
        <Route path="/" element={<div>home</div>} />
        <Route path="/post/:id" element={<Post />} />
      </Routes>
    </StaticRouter>
  );
  res.write(html);
  res.end();
}
http.createServer(requestHandler).listen(3006);

这个例子,参考文章:

苏南大叔:React SSR,如何理解和使用脱水函数renderToString()? - http服务器代码
React SSR,如何理解和使用脱水函数renderToString()?(图4-3)

这里可以注意到:输出的就是无限接近于传统html的代码,并没有React程序底部标配的app.js(或其它名字)的引用。说明,两者并不是强绑定的。

搭配 express 输出

nodejs的世界里面,更多的情况,是搭配express使用的。同时搭配react routerStaticRouter的话,测试如下:

import express from "express";
import React from "react";
import { Routes, Route, useParams } from "react-router-dom";
import { StaticRouter } from "react-router-dom/server";
import { renderToString } from "react-dom/server";
function Post() {
  var { id } = useParams();
  return <div>No.{id} article</div>;
}
const app2 = express();
app2.use(express.static("dist"));
app2.get("/*", (req, res) => {
  let html = renderToString(
    <StaticRouter location={req.url}>
      <Routes>
        <Route path="/" element={<div>home</div>} />
        <Route path="/post/:id" element={<Post />} />
      </Routes>
    </StaticRouter>
  );
  let data = {
    www: "newsn.net",
    author: "苏南大叔",
  };
  function template() {
    return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>React Server Side Rendering</title>
</head>
<body>
    <div id="root">${html}</div>
    <script> window.__ROUTE_DATA__ = ${JSON.stringify(data)} </script>
    <script src="/app.js"></script>
</body>
</html>`;
  }
  res.send(template());
});
app2.listen(3006);

这个代码就相对完整了,很接近实际应用中的样子。这里还带出来了用于“补水”的app.js文件。这个文件是怎么来的,以及window.__ROUTE_DATA__这个全局变量是怎么回事,会在后续的“补水”相关文章里面进行说明。

苏南大叔:React SSR,如何理解和使用脱水函数renderToString()? - rednder-to-string-express
React SSR,如何理解和使用脱水函数renderToString()?(图4-4)

总结

这里可以看到,无论是普通的react代码,还是说带着react router的路由代码。都可以当作jsx组件,传递给renderToString()进行服务器端脱水。把脱水后的代码,发送给客户端浏览器。这就完成了SSR的第一步:脱水。

更多苏南大叔的react经验文章,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react