支持动态路由的 React Server Side Rendering 实现

本文作者 Bermudarat

头图来自 Level up your React architecture with MVVM, 作者 Danijel Vincijanovic

1. 前言

在开始正文前,先介绍几个概念(已经了解的朋友可以跳过):

Server Side Rendering(SSR):服务端渲染,简而言之就是后台语言通过模版引擎生成 HTML 。实现方式依赖于后台语言,例如 Python Flask 的 Jinja、Django 框架、Java 的 VM、Node.js 的 Jade 等。

  • 优点:SEO 友好、更短的白屏时间;
  • 缺点:每次都需请求完整页面、前后端开发职责不清;

Client Side Rendering(CSR):客户端渲染,服务器只提供接口,路由以及渲染都丢给前端。

  • 优点:服务端计算压力小、可以实现页面的局部刷新:无需每次都请求完整页面、前后端分离;
  • 缺点:SEO 难度高、用户白屏时间长;

同构:前后端共用一套代码逻辑,所有渲染功能均由前端实现。在服务端输出含最基本的 HTML 文件;在客户端进一步渲染时,判断已有的 DOM 节点和即将渲染出的节点是否相同。如不同,重新渲染 DOM 节点,如相同,则只需绑定事件即可(这个过程,在 React 中称之为 注水)。同构是实现 SSR 的一种方式,侧重点在于代码复用。

静态路由:静态路由需要在页面渲染前声明好 URL 到页面的映射关系。如 Angular、Ember 中的路由,React Router v4 之前版本也采用此种路由。

动态路由:动态路由抛开了静态路由在渲染前定义映射关系的做法,在渲染过程中动态生成映射。React Router v4 版本提供了对动态路由的支持。

Code Splitting:也就是代码分割,是由诸如 Webpack,Rollup 和 Browserify(factor-bundle)这类打包器支持的一项技术,能够在打包文件时创建多个包并在运行时动态加载。

Next.jsNuxt.js 是目前成熟的同构框架,前者基于 React,后者基于 Vue。有了这些框架,开发者可以方便地搭建一个同构应用:只对首屏同构直出,满足 SEO 需求,减少白屏时间;使用前端路由进行页面跳转,实现局部渲染。这些同构框架,已经在工程中得到了广泛应用。然而知其然也要知其所以然,对于一个功能完善的同构应用,需要解决以下几个方面的问题:

  1. 服务端:如何匹配 URL;页面数据预获取;响应字符串的组装与返回。
  2. 客户端:应用如何进行数据管理;如何使用服务端获取的数据进行渲染;客户端和服务端的数据获取方式不同,如何保持一致。
  3. 工程化:如何结合 Code Splitting,区分服务端和客户端,输出分块合理的 JS/CSS 文件;对于无法 SSR 的深层组件,如何延迟到客户端再初始化。

上述问题的解决过程中,有很多坑会踩,本文主要讨论第一点。此外,提出一种解决方案,在服务端不使用中心化的路由配置,结合 Code Splitting ,通过一次预渲染,获取当前 URL 对应的模块名和数据获取方法。

2. 基于 React 的 SSR 实现

2.1 通用思路

React 提供了 四个方法 用来在服务端渲染 React 组件。其中,renderToStaticMarkuprenderToStaticNodeStream 不会在 React 内部创建额外的 DOM 属性,通常用于生成静态页面。同构中常用的是 renderToStringrenderToNodeStream 这两个方法:前者将应用渲染成字符串;后者将应用渲染为 Stream 流,可以显著降低首字节响应时间(TTFB)。

实现一个同构的 React 应用,需要以下几个步骤(下文均以字符串渲染为例):

  1. 获取匹配当前 URL 的路由,进而获取对应的数据获取方法;
  2. 调用第一步获得的方法请求数据;
  3. 结合上一步获取的数据(此处可以使用 Redux 等数据管理模块),调用 React
  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐琪皓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值