Thinkjs项目中React同构实践

Thinkjs项目中React同构实践 什么是React同构 什么是同构呢? 我们为什么要使用同构? 如何进行react同构? React同构遇到的问题 结合Thinkjs遇到的问题 性能优化与监控

Thinkjs项目中React同构实践

在奇舞团最优秀的服务端框架Thinkjs中想进行React同构我们该怎么弄呢?本篇文章就讲讲360视频云项目在Thinkjs中进行React同构实战。

什么是React同构

什么是同构呢?

答:简单说,同构就是前后端都使用同一套代码进行渲染。

我们为什么要使用同构?

答:因为现在SPA的流行,React或者Vue的项目越来越多的应用在了外网的项目中。但是SPA的页面都是通过js来动态生成的,这样就造成了一些需要SEO的页面无法被搜索引擎更好的抓取。同时,因为React库体积等问题,js很容易就达到2M左右,网络请求 + eval javascript的消耗,大型项目首屏速度基本都在1秒或者1.5秒开外。这对于首屏速度要求高,或者移动站在弱网条件下同构就显得非常重要了,同构可以使你的首屏在300ms左右就渲染完成。

如何进行react同构?

从 React官网 我们就可以轻易的找到,React内置为我们提供了4个方法,分别是

renderToString renderToStaticMark renderToNodeStream renderToStaticNodeStream

从方法的命名我们就知道前两个是直接把代码渲染成字符串,后两个是输出一个可读流 readableStream。首先介绍一下直播云同构环境,我们的环境基于 Node 8.9 React16.3 react-router3 think3 来进行。我们知道了服务端渲染的api之后,我们就摩拳擦掌跃跃欲试了。既然我们使用了react-router,我们找到了react-router文档,二话不说先上一段代码

import { renderToString } from 'react-dom/server'
import { match, RoutingContext } from 'react-router'
import routes from './routes'

serve((req, res) => {
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.send(500, error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
      res.send(200, renderToString(<RoutingContext {...renderProps} />))
    } else {
      res.send(404, 'Not found')
    }
  })
})

React同构遇到的问题

问题一:既然是同构,如何处理原本在客户端的请求呢?

答:既然是同构,那肯定需要在服务端先请求数据接口,然后拿到对应的数据在去rander我们的前端代码。在前端大部分是用XMLHttpRequest 对象进行请求,但是在node端没有这个对象,这个时候我们可以使用XHR2的第三方库来帮我们包装。但是在这里我更推荐使用axios网络库。

问题二:我们该何时发送请求呢?

答:在React中,我们可以在componentDidUpdate声明周期里发起一个数据请求,但是在服务端渲染的时候我们没有componentDidUpdate这个声明周期,只有componentWillMount这个声明周期,那我们可以把请求放在这里面吗?还有我们的请求是异步的,那我们的能在声明周期里用async/await吗?显而易见,都是否定的。因为React在调用声明周期是同步式的调用,很多新人在这里会掉进坑里。那使用不了async/await,那我们就不能再生命周期里去处理请求,因为请求是异步的,渲染是同步的。那我们该把请求放在哪里呢?

结合Thinkjs遇到的问题

性能优化与监控

文章来源:

Author:光宇
link:http://www.gyblog.cn/post/thinkjs&react.html