前端全链路 NodeJS¶
同构渲染架构 SSR¶
同构渲染架构:实现一个SSR应用
SSR 应用实践¶
同构应用中的重要细节¶
-
环境区分
-
路由代码差别
- 服务端:根据请求路径,匹配页面组件;StaticRouter
- 客户端:通过浏览器地址,匹配页面组件;BrowserRouter
-
打包差别(服务端)
- 如果需要依赖Node核心模块或者第三方模块就不再需要把这些模块代码打包到最终代码中因为环境已经安装这些依赖,可以直接引用
- 在Nebpack中配置target:node,并借助webpack-node-externals插件,解决第三方依赖打包的问题
-
-
注水和脱水
- 脱水:服务端返回 HTML 字符串时,将数据 JSON.stringify 一并返回
- 注水:不需要进行数据请求,直接使用服务端下发的数据
- 如何保证服务端请求所有APIs,保障所有数据请求?react-router 的解决方案:配置路由route-config,结合matchRoutes,找到页面上相关组件所需的请求接口的方法并执行请求
- 另外一种思路类似 Next.js,我们需要在React组件上定义静态方法,如 loadData
-
安全问题
- 严格清洗JSON字符串中的HTML标签和其他危险的字符
- React dangerouslySetInnerHTML API 怎么处理风险?
-
请求认证处理
- 服务端请求时需要保留客户端页面请求的请求认证处理信息(一般是cookie),并在API请求时携带并透传这个信息(cookie)
-
样式问题处理
- isomorphic-style-loader利用context API,在渲染页面组件时获取所有React组件的样式信息,最终插入HTML字符串中
性能守卫系统¶
设计性能守卫系统:完善CI/CD流程
性能守卫理论基础¶
-
LCP (Largest Contentful Paint)
- 衡量页面的加载体验,表示视口内可见的最大内容元素的渲染时间
- LCP vs FCP
-
FID (First Input Delay)
- 衡量可交互性,表示用户和页面进行首次交互操作所花费的时间
- FID 比 TTI 更加提前
-
CLS (Cumulative Layout Shift)
- 衡量视觉稳定性,表示页面的整个生命周期中发生的每个意外的样式移动的所有单独布局更改得分的总和
-
业界公认的监控素材
-
真实用户监控(Real User Monitoring,RUM)
- 基于用户真实访问应用情况,在应用生命周期内计算产出性能指标,并进行上报。
- 一般搭配稳定的SDK,会在一定程度上影响用户的访问性能,也给用户带来了额外的流量消耗
-
合成监控(Synthetic Monitoring,SYN)
- 一种实验室数据,它指的是在某一个模拟场景中,通过工具,搭配规则和性能审计条目,得到一个合成的监控报告
- 优点:实现比较简单,有现成成熟的解决方案;如果搭配丰富的场景和规则,得到的数据类型也会较
- 缺点:数据量相对较小,且模拟条件配置相对复杂,无法完全反映真实场景
-
Lighthouse 原理¶
- Lighthouse 架构图
- 1)首先,Lighthouse驱动Driver,底层通过Chrome DevTool Protocol调用浏览器进行应用的加载和渲染
- 2)然后通过Gatherers模块集合,获取到收集到的Artifacts信息
- 3)Artifacts 信息在 Auditing 阶段,通过对自定义指标的审计,得到Audits结果,并生成相关文件
- lighthouse实践
Perf-patronus 系统¶
- 整体流程
-
监控指标
- FCP
- Total Blocking Time
- First CPU Idle
- TTI
- Speed Index
- LCP
-
如何真实反映用户情况
-
常见不确定和波动因素
- 页面不确定性
- 用户侧网络情况不确定性
- 终端设备不确定性
- 页面服务器不稳定性
- 性能体检服务的稳定性
-
如何解决有“用户态”页面的鉴权问题
BFF 网关¶
实践打造网关:改造企业BFF方案
BFF 网关介绍和优缺点¶
- API Gateway + BFF
- 优点:降低沟通成本;提供更好的用户体验
- 痛点:需要解决分工问题;链路复杂;资源浪费
BFF 网关的考量¶
-
数据处理
- 数据聚合和裁剪
-
序列化格式转换
- 不同端可能也会需要不同的数据序列化格式:JSON、XML等
-
协议转换
- 客户端需要通过HTTP REST进行所有的通信;而某个微服务内部使用了gRPC或GraphQL
-
Node.js调用RPC
- Node.js是一个Proxy,调用RPC发挥BFF层能力
-
流量处理
- 代理能力:比如 http-proxy 实现
-
请求分发能力
- 方案一:hard coding 写在代码里,实现网关层的服务发现
- 可方案二:URL规范化,网关层进行请求匹配时根据URL内容对应不同的namespace,进而对应到不同的微服务
- 也要考虑条件路由,即对具有 特定内容(或者一定流量比例)的请求进行筛选,并分发到特定实例组上
-
可用性保障
- 网关层:良好的限速、隔离、熔断降级、负载均衡和缓存能力
-
安全问题(BFF 层的原则)
- BFF层不需要完成全部的校验逻辑,部分业务校验应该留在微服务中完成
- BFF需要完成必要的检查,比如请求头检查和必要的数据消毒
- 合理使用Content-Security-Policy
- 使用HTTPS/HSTS
- 设置监控报警以及调用链追踪能力
-
权限与校验设计
- 身份验证(基于 cookie 或 token)
-
权限校验(ACL 或 RBAC)
- ACL:访问控制列表,用户直接与权限挂钩
- RBAC:用户只和角色关联
实现一个 gateway¶
-
基本反代理
- fast-proxy:支持 HTTP/ HTTPS / HTTP2 三种协议
@polka/send-type
:处理请求的工具函数- restana:restful 风格的极简的nodejs框架
-
中间件
-
缓存策略
- http-cache-middleware
- 内存缓存 / Redis 缓存
-
Hooks 设计
Puppeteer 海报系统¶
实现高可用:使用 puppeteer 生成性能最优的海报系统
puppeteer 介绍¶
- Headless 浏览器
- Puppeteer是一个Node库,它提供了一整套高级API,通过DevTools协议控制Chromium或Chrome;
- 正如其翻译为“操纵木偶的人”一样你可以通过Puppeteer提供的API直接控制Chrome,模拟大部分用户操作进行UI测试或者作为爬虫访问页面来收集数据。
- puppeteer:默认下载 chromium
- puppeteer-core:不下载 chromium,同时忽略 puppeteer_* 环境变量
puppeteer 原理¶
- 为网页生成页面PDF或者截取图片
- 抓取SPA(单页应用)并生成预消染内容
- 自动提交表单,进行U川测试、键盘输入等
- 创建一个随时更新的自动化测试环境,使用最新的Javascript和浏览器功能直接在最新版本的Chrome中执行测试
- 捕获网站的timeline trace,用来帮助分析性能问题
- 测试浏览器扩展
puppeteer 应用场景¶
- 为网页生成页面PDF或者截取图片
- 抓取SPA(单页应用)并生成预渲染内容
- 自动提交表单,进行U测试、键盘输入等
- 创建一个随时更新的自动化测试环境,使用最新的JavaScript
- 浏览器功能直接在最新版本的Chrome中执行测试
- 捕获网站的timeline trace,用来帮助分析性能问题
- 测试浏览器扩展
Puppeteer 与 SSR¶
- 使用Puppeteer实现服务端预渲染不需要对项目进行任何调整
Puppeteer 与 UI 测试¶
- 结合 jest,通过断言能力实现一个完备的端到端测试系统
Puppeteer 与 Lighthouse¶
- 实现简单的性能守卫系统
Puppeteer 海报系统¶
-
业务流程:分享 -> 模板选择 -> 发送至服务端 -> Puppeteer-poster(启动Headless浏览器并截图) -> Database
- 使用
generic-pool
优化 puppeteer 并发问题