1、前言
作为前端开发,对于H5页面的SSR,我们一般只关心webview
启动之后的工作,如数据请求、水合、渲染等。实际上,H5页面的SSR,需要和客户端高度配合,才能实现所需效果。比如在笔者的上一篇文章【 手把手带你实现 Vite+React 的简易 SSR 改造【含部分原理讲解】】中,简要提到了流式SSR+FCC优化这一工作便主要是借助客户端的缓存 实现相应优化:
笔者除了前端开发外,对客户端开发也有一定了解(主要是iOS开发、flutter开发等),因此本文从iOS客户端 的角度讲解所需要关注的细节,让读者对整个SSR
流程更加了解。
2、客户端核心逻辑梳理

2-1 入口启动注册
在App启动时进行SSR模块的初始化(主要是注册自定义的 URL
协议类 SSRURLProtocol
):
Objective-C
[RequestSSRHandler setup];
2-2 URL拦截和处理
- SSRURLProtocol :
- 使用
NSURLProtocol
来拦截特定的网络请求。这些拦截基于请求 URL 的某些标志位或头字段。 canInitWithRequest:
方法用于判断是否对请求进行拦截,避免重复拦截,并进行必要的日志记录和异常处理。
- 使用
2-3 请求发送与响应处理
- RequestSSRHandler:
setup
方法设置与应用相关的请求参数,如appkey
、appver
、utdid
等,并进行统一管理。sendRequest:
方法将请求发送给后端,可选择缓存命中的内容直接响应,优化响应时间。ssrRequest:didReceiveResponse:
处理响应,检查缓存数据是否可用并适用的判断逻辑。- 对于特定错误进行降级处理(如网络错误),通过
requestOnline:receiver:
方法发起普通网络请求。
2-4 缓存管理
-
缓存数据 (
SSRCacheData
) :- 负责序列化缓存的 HTML 数据,并保存相关的版本、过期时间等,用于快速响应请求。
- 提供
getCacheHtml
和setCacheHtml
方法来管理缓存数据的存取,加速处理过程。
-
缓存存储 (
FCCStorage
) :- 管理缓存的持久化。
- 提供方法来保存、获取和移除缓存数据,以确保缓存的有效利用。
- 使用特定查询参数和用户标识决定缓存的唯一键值,使缓存管理更具灵活性。
2-5 响应版本和开关校验
- 在处理请求和响应时,对版本和开关的启用状态进行检查,确保缓存的正确性和适用性。
- 确保在版本不匹配或开关关闭的情况下替代渲染方法,以保障应用的稳定性。
2-6 请求上下文管理
- SSRRequestContext:
- 管理请求的状态和数据,包括是否启用首 chunk 缓存、是否命中缓存、是否复用完缓存等。
produceResponse:
和produceData:
负责处理接收到的响应和数据,根据缓存状态进行处理,包括使用缓存、替代渲染、保存缓存等。- 提供
matchFirstChunkCache
,saveFirstChunkCache
, 和matchFCC:cacheData:response:
等方法来管理首 chunk 缓存数据的匹配和存取。
2-7 错误处理与降级策略
- 在请求失败的情况下,如果满足特定条件,会自动降级请求为普通在线请求,以保证系统的稳定性和用户体验。
3、附上WebViewController应有的一些逻辑
-
WebView初始化与配置:
- 使用WKWebView,进行URL拦截。
- 支持下拉刷新、自定义导航栏、状态栏样式等。
-
请求处理与拦截:
- 登录拦截。
- URL安全校验,防止恶意链接。
- 路由拦截,处理本地协议跳转。
-
性能监控与埋点:
- 页面加载时间统计。
- 错误监控与上报。
- 应用启动阶段H5页面加载的性能追踪。
-
UI交互:
- 显示加载状态(自定义Loading动画)。
- 处理横竖屏切换。
- 导航栏返回按钮和关闭按钮的逻辑。
-
其他功能:
- Cookie同步、第三方验证、字体注入等。
了解客户端处理的这些逻辑之后,可以考虑h5页面首屏进一步的性能优化:webview预热和文档预请求
,具体的实现逻辑需要笔者和读者一起去学习探索: