这是我参与更文挑战的第18天,活动详情查看: 更文挑战。
前言
React 同构,需要实现以下功能:
- 在服务端根据 React 组件生成 html
- 数据脱水和注水
- 服务器端管理Redux Store
- 支持服务器和浏览器获取共同数据源
React服务器端渲染HTML
React在服务器端渲染使用函数和浏览器端不一样:
import ReactDOMServer from "react-dom/server';
const appHtml = ReactDOMServer.renderToString(<RootComponent />)
renderToString
函数的返回结果就是一个HTML字符串,至于这个字符串如何处理,要由开发者来决定。
当然,只是把 renderToString 返回的字符串在浏览器中渲染出来,用户看到的只是纯静态的 HTML 而已,并不具有任何动态的交互功能。要让渲染的HTML“活”起来,还需要浏览器端执行 JavaScript 代码。
服务器端渲染产生的React组件HTML被下载到浏览器网页之中,浏览器网页需要使用render函数重新渲染一遍React组件。
如果服务器端渲染和浏览器端渲染产生的内容不一样,用户会先看到服务器端渲染的内容,随后浏览器端渲染会重新渲染内容,用户就会看到一次闪烁,这样给用户的体验很不好。
为了让两端数据一致,就要涉及 脱水 和 注水 的概念。
脱水和注水
服务器端渲染产出了HTML,但是在交给浏览器的网页中不光要有HTML,还需要有 脱水数据,也就是在服务器渲染过程中给React组件的输入数据,这样,当浏览器端渲染时,可以直接根据“脱水数据”来渲染React组件,这个过程叫做 注水。
脱水数据的传递方式一般是在网页中内嵌一段 JavaScript,内容就是把传递给React组件的数据赋值给某个变量,这样浏览器就可以直接通过这个变量获取脱水数据。
需要注意的是,使用脱水数据要防止跨站脚本攻击(XSSAttack),因为脱水数据有可能包含用户输入的成分,而用户的输入谁也保不准包含什么。
服务器端Redux Store
在服务器端使用Redux,必须要对每个请求都创造一个新的Store,这是和浏览器渲染的最大区别。
支持服务器和浏览器获取共同数据源
很明显,最简单的方法,就是有一个API服务器提供接口让服务器和浏览器都能够访问,这样无论是什么样的场景,服务器和浏览器获得数据都是一致的。
服务器端路由
因为浏览器端使用了 React-Router
作为路由,没有理由不在服务器端使用一致的方法,不过在服务器端使用React-Router 的方式和浏览器端不一样,在浏览器端,整个 Router 作为一个 React 组件传递一个 ReactDOM的 render 函数,Router 可以自动和URL同步,但是对于服务器端的过程,URL对应到路由规则的过程需要用 match 函数:
import { match, RouterContext } from "react-router";
match({routes: routes, location: requestUrl }, function(err, redirect, renderProps){
if (err) {
return res.status(500).send(err.message);
}
if (redirect) {
return res.redirect(redirect.pathname + redirect.search);
}
if (!renderProps) {
return res.status(404).send("Not Found");
}
const appHtml = ReactDOMServer.renderToString(<RouterContext {...renderProps} />);
});
match 函数接受一个对象和一个回调函数作为参数,对象参数中的 routes 就是 Route 构成的路由规则树,这里根本用不上 Router 类,所以也用不上 Router 的 history 属性,这就是和浏览器端渲染的最大区别。match是通过对象参数中的 location 字段来确定路径的,不是靠和浏览器地址栏关联的 history。
当 match 函数根据 location 和 routes 匹配完成之后,就会调用第二个回调函数参数,根据回调函数第一个参数err和第二个参数 redirect 可以判断匹配是否错误或者是一个重定向。一切顺利的话,第一第二个参数都是空,有用的就是第三个参数 renderProps,这个 renderProps 包含路由的所有信息,把它用扩展操作符展开作为属性传递给 RouterContext 组件,渲染的结果就是服务器端渲染产生的HTML字符串。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!