记录项目中使用服务端渲染 ssr的体会

Author Avatar
高翔 1月 01, 2019

什么?又回到大学里面写JSP的形式了?

最近在重构一个移动端原生的项目,采用的RN+H5的结构,对于某些偏展示和活动页之类的页面都用H5做,开发和迭代都方便很多。

在APP中从Native页面跳转H5页面时,如果白屏时间稍微长一点,就会导致用户有割裂的体验,怎么在native畅快体验和RN+H5的快速开发迭代中权衡是需要好好考虑的。

为了解决H5加载慢的问题,我们采用了一系列的优化措施,目前在首次打开H5页面(无缓存)的情况下,测试环境中页面能在60+ms内出现主结构+ui,并且采用了单页应用的形式(spa),所以从H5中的链接再跳转体验就完全没问题了。
image
这里主要记录一下为了优化首屏加载速度才有的服务端渲染(ssr)模式。

为什么要使用服务端渲染

前面也说到了,我们的H5采用了单页应用形式,单页应用无疑会带来更加沉浸式的H5体验,尤其是在我们这种UI主架构保持一致的应用内。但是单页应用也会带来两个问题:

  1. 页面搜索引擎优化(SEO)的困难:因为单页应用通常前端在开发时只是在html中放置一个容器div,后续根据不同路由来填充内容,这样对于爬虫来说一点都不香。
  2. 首页加载慢:单页应用体积肯定要大一些撒,如果等所有js都拉下来才渲染首页,那白屏时间就太长了,体验太差。

借用next的图看一下服务端渲染和客户端渲染(这里就是浏览器)的区别:
image
image
从图中可以看出,这两种渲染方式的区别主要在于出现首屏渲染的时机。对于SSR来说,服务器返回的是结构相对完整的HTML文件,浏览器只需要解析HTML文件,就能渲染出页面。而对CSR来说,浏览器拿到的只是包含JavaScript代码的HTML文件,在浏览器渲开始渲染出页面之前,需要动态创建HTML标签。

对于上面的第一点来说,爬虫请求这个url就能直接拿到相对完整的页面结构,所以单页应用SEO的问题就迎刃而解了。当然也有其他解决SEO的方法(某些框架可以单独针对爬虫渲染一套html文件),不过目前看来服务端渲染算是比较方便成熟的解决方案。

我们是开发的原生APP内嵌H5,所以没必要考虑SEO。接下来介绍一下采用服务端渲染对于首页加载速度的提升。

从输入一个网址到展示出页面经历了哪些呢?答案复杂到可以写一本书了吧,我们这里简单的把它分为网络请求和浏览器渲染两个部分,其中网络请求占大头。而传统的模式里面,需要下载下来html文档,再下载js,执行js,通过ajax请求数据,然后再渲染出完整首屏。

对于服务端渲染,服务端收到请求后,会先去拿需要的数据(相比浏览器ajax请求,要更稳定,性能更好),然后把数据和模板结合,生成html文档直接返回给浏览器。这时浏览器只需要把拿到的html渲染出来(渲染耗时极短)。这个过程相比于传统模式,将几次网络请求合并到了一次,并且提高了性能和稳定性,首屏出现的时间能提前不少。

对于进入了首屏,跳转其他页面,通常我们是做js分片的,在首屏加载完成后,异步而非按需加载剩余js,这样在非首屏的跳转就相当迅速了,虽然会多费点流量(我身边的同学今年都换了无限流量套餐了)。所以在非首屏是没有必要再去做服务端渲染来优化的。

具体使用nuxt框架中的缺点

我们的H5项目使用的vue框架,vue比较推荐的ssr框架是nuxt.js。官方文档还不错,参见nuxt.js

在实际使用中,发现框架还是有几个问题,记录一下:

  1. 服务端渲染会加重服务端的复核,框架的服务端是在node环境运行,毕竟请求数据和渲染html都放到了服务端,所以node端压力肯定比浏览器端渲染要大一些

  2. nuxt提供方法asyncData(这里明明是同步请求,居然取这个名字)来在服务端获取首屏需要的数据,但是是单页应用内跳转,这个方法会阻塞跳转,也就是点击了跳转链接,需要等这个方法执行结束才会跳转,而不是直接进入跳转动画,这样就会造成点击了链接延迟一下的问题。不知道是否是禁用了框架自带的页面跳转动画导致的,但是默认的动画是一个进度条,在最顶部,我们的单页应用顶部的导航栏是不变的。。。。

3.项目目录结构,nuxt项目目录如下:image
可以看到项目规定以page来存放每个页面,而项目的路由也是更具page的目录来生成的。但是不管是vue还是react应该都是组件化的思想,这样的结构目录在大型项目中可能会有问题。

感谢浏览,下一篇准备分享一下项目中使用React Native的体会。