背景
「让每一个用户在最短的时间内看到页面上重要的内容」一直以来都是前端工程师们精益求精的方向。对于一个H5的源码页面,我们已经有了很多缩短首屏渲染时间的方法,比如数据预取,离线缓存。但在目前看来,由于数据预取和离线缓存都依赖客户端的能力,很多时候会给我们带来一些限制。比如用于增长业务的外投拉新页面,我们并不能知晓第三方APP是否具备这样的能力。再比如使用离线缓存能力,我们受制于命中率高低,以及缓存对APP性能带来的负面影响这样的问题。
服务端渲染,让最重要的内容和用户之前,只需要请求HTML DOC的时间,并且不依赖于客户端的能力,可以大大缩短用户看到页面首屏内容的时间。
方案要点
目前主流前端框架比如React,都已经提供了支持SSR的API,我们可以只用几行代码便将一段原本执行在客户端的绘制UI的逻辑转化为可以在Node层直出HTML的功能。在此基础之上,一个SSR技术方案应该同时做到以下几点要求:
页面首屏有效绘制(FMP)时间变短:从webview发出页面url请求,到用户看到首屏有效内容的时间真实变短。
应用稳定性高,运维成本低:保证由Node应用提供前端页面,尽可能跟已经非常成熟的「CDN缓存前端静态资源 Java服务提供首屏数据」有相近的稳定性。并且Node服务一旦出现不可用的情况,页面能够自动降级到稳定的CSR(当下H5页面都在用的客户端渲染)模式,而不需要工程师手动执行降级。
低研发成本:采用SSR以后,前端工程师仍然只需要关心业务功能的实现,而无需为满足稳定性要求增加额外开发成本。
本文将重点介绍闲鱼的SSR方案围绕这三个要点进行了怎样的设计。
技术架构
先来看下闲鱼目前SSR架构整体的设计,再来单独聚焦每一个功能点的实现。
如图,架构设计分别考虑了用户正常访问的SSR链路(红色结点),以及SSR应用不可用时自动降级到的CSR链路(蓝色结点)。用CSR链路作为SSR失败时的降级兜底方案,是保证SSR方案稳定性的关键点。
SSR链路基于serverless的node应用
随着阿里Serverless生态建设的不断完善,前端同学开发Node应用,已经不需要像面对传统Node应用一样,花费太多时间来运维Node应用。我们可以凭借「函数即服务」的FaaS能力,聚焦于Node应用本身功能的实现。
为了实现SSR功能我们需要在Node层实现两个服务:
数据聚合。一个前端页面首屏需要的数据,可能来自于多个服务端(Java)的接口。我们在Node层实现一个Service,该Service调用首屏依赖的所有服务端接口,将其汇聚为一个接口,输出全部首屏数据。这种由Node层实现数据胶水的设计,同时可以降低前端与服务端开发协作的成本。前端只需要得到服务端原子功能级别的数据,便可以根据UI的需要按照自己方便的方式定义最终输出的数据结构。
直出HTML页面(HTTP服务)。当用户访问某个URL时,Node应用获取页面构建产物,同时调用上条提到的首屏数据接口,将返回的数据用于生成页面的DOM树。
SSR应用网关
当需要发布某一个前端应用,或者当某一个应用不可用时,我们肯定不希望影响到其他的应用。所以我们在业务维度,将跟某个特定业务相关联的前端功能作为独立的Node应用单独维护。那么,为什么我们还需要一个公共的网关为应用提供服务,而不是每一个应用单独向用户提供服务呢?
原因是每一个对用户开放的HTTP服务,都必须接入集团的「统一接入」机制。统一接入承载了转发、负载均衡、安全认证等多种必不可少的功能。接入的整个流程,包括应用架构的评审、域名的配置、其他安全机制的确认等等需要1~2个工作日。而由于我们不断会有新的业务、新的项目,为每一个新应用都走一遍统一接入是要消耗大量人力成本且没有必要的。因而我们在所有Node应用之上,架设网关应用,利用Nginx根据访问path的不同,将用户的请求分发到不同的应用上。网关本身作为CDN回源的源站。ssr怎么设置(ssr加速器节点)节点是什么意思(手机怎么换节点)