对react项目进行SSR 改造,求指导
发布于 5 天前 作者 1160007652 269 次浏览 来自 问答

项目采用:React V16.4 + mobx + react-router V4 + axios

项目已经开发完,现在要改造成SSR 服务端渲染, 做SEO, 怎么下手呢。

看了 next 对改造, staticRouter 改写, 初始数据获取, 路由跳转,不能使用 BrowserRouter 改staticRouter 的问题不是理解。查阅了React ssr 方案,对改造这块的资料,看着很模糊。

请大伙赐教

2 回复

做 react SSR 有一段时间了, 一些心得, 正好在这里分享一下.

什么是服务端渲染

用户第一次请求/刷新页面时, 由服务端响应. 服务器响应的是一个已经插入了组件文本的模板 ( template with pre-populated component ). 由于响应的页面已经有组件的 HTML 文本, 可以省去浏览器端首次渲染的工作, 加快首屏显示速度, SEO 友好.

服务端渲染时浏览器的工作流程

浏览器接收到服务器预渲染的模板后, 渲染 DOM, 然后开始下载 js 文件(bundle), 下载完成后 react 开始工作, 生成VDOM. 由于使用了 SSR hydrate() API, VDOM 上组件的 mount 行为 (也就是组件从 VDOM 到 真实 DOM 的第一次的 render) 将会被跳过. Mobx/Redux 和 React Router 开始工作.

余后的页面内的链接 ( <Link> ) 跳转皆由 react router 接管.

服务端渲染时的工程架构

服务端渲染时, 服务器和浏览器共用一套模板, 一套组件. 两个入口文件 (两个 bundle). 服务器需要一个 服务端 bundle, 对应的 webpack 编译配置需要适配服务端环境 (nodejs commonjs 模块系统). 开发环境下的服务端渲染工作可以和 webpack devServer 协作, 实现开发时服务端渲染的热加载.

流程

服务器响应

在客户端入口组件应用 ReactDOM.hydrate() 替换 ReactDOM.render() 在服务端使用 ReactDOMServer.renderToString() 将组件转化为字符串, 插入模板中, 响应给客户端.

实现首次加载时数据同步

  • Mobx 的服务端渲染配置: 参考官方文档.
  • 前后端数据传递: 通过脚本注入的方法向模板插入一个 js 对象, 以此传递数据给浏览器, 实现 VDOM 和 DOM 上组件/元素的数据同步.
  window.__INITIAL_STATE__ = <%%-initialState %>

服务端 React Router 设置

服务端需要使用 React Router <StaticRouter> 组件.

  • 通过 <StaticRouter> 上 location 自动实现对 <Route> 的匹配 (响应).
  • 通过 <StaticRouter> 上的 context 属性手动实现对 <Redirect> 的响应. 参考 React Router 官方文档.

前端路由的数据获取

定义接口: 可以在 routes 文件内定义用于获取数据的 API, 也可以在组件内部提供静态方法来获取数据的 API. 调用接口: 在组件的生命周期函数中调用这些 API.

针对 SEO 搜索引擎爬虫的配置.

动态渲染 <head>

以上, 代码细节还是比较多的. 使用了 Material-UI 的话也需要做相关的配置.

可以参考我最近写的这三个 repo, 有详细的逻辑流程, 第一个 demo 的逻辑比较清晰 (推荐)

  1. 这个 repo 是一个 React + React Router 4 SSR 的 React & React Router 4 Server Side Rendering Boilerplate

  2. 这个 repo 暂时未提交支持 Mobx 和 React Router 4 的代码. 在 SSR 的基础上实现了开发时服务器渲染的热更新, 流程可能会更为复杂些. A-SSR-React-Dev-Boilerplate

  3. 这个 repo 还未完成, 已经在第二个 repo 的基础上添加了对 Mobx, React Router4 以及 Material-UI 的支持. 不过由于在服务器开发环境下的流程有些过于复杂, 尚未优化, 可以略过开发服务器的部分. React-Express-Forum

@dudueasy 大佬就是大佬,能否加个QQ 1160007652,方便后续交流 谢谢

回到顶部