搭建渲染服务器
基于 Express 的渲染服务器
renderToString
React 提供了两个方法 renderToString
和 renderToStaticMarkup
用来将组件(Virtual DOM)输出成 HTML 字符串,这是 React 服务器端渲染的基础,它移除了服务器端对于浏览器环境的依赖,所以让服务器端渲染变成了一件有吸引力的事情。这两个方法被包含在了 react-dom 仓库中,可以通过如下方式引入与使用:
import ReactDOMServer from "react-dom/server";
var ReactDOMServer = require("react-dom/server");
ReactDOMServer.renderToString(element);
我们可以在服务端即使用renderToString
将组件转化为 HTML 标签然后传递给客户端,这里 React 会自动为标签进行校验和计算;这样我们在客户端调用 ReactDOM.render()
渲染某个组件时,如果 React 发现已经存在了服务端渲染好的标签,则会直接使用这些标签来节约渲染时间。ReactDOMServer 中提供的另一个渲染函数是renderToStaticMarkup
,其很类似于renderToString
,不过其忽略了额外的譬如data-reactid
这样的 React 内部使用的非 HTML 标准属性;如果你只想把 React 作为简单的静态网页生成器,那么推荐使用这种方式,会帮你避免额外的带宽消耗。
服务器端渲染除了要解决对浏览器环境的依赖,还要解决两个问题:
-
前后端可以共享状态
-
前后端路由可以统一处理
状态传递
路由权限控制
import { renderToString } from "react-dom/server";
import { match, RouterContext } from "react-router";
import routes from "./routes";
serve((req, res) => {
// Note that req.url here should be the full URL path from
// the original request, including the query string.
match(
{ routes, location: req.url },
(error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
// You can also check renderProps.components or renderProps.routes for
// your "not found" component or route respectively, and send a 404 as
// below, if you're using a catch-all route.
res
.status(200)
.send(renderToString(<RouterContext {...renderProps} />));
} else {
res.status(404).send("Not found");
}
}
);
});