预订页同时展示相对稳定的商品介绍、随日期变化的价格库存,以及只属于当前用户的购物车和结账状态。把这些数据当成同一种页面请求处理,容易出现首屏慢、价格过期或服务端与客户端内容不一致。
| 数据 | 适合的处理方式 | 原因 |
|---|---|---|
| 标题、图片、介绍 | 服务端生成页面,按业务频率缓存或重新验证 | 便于首屏展示和搜索引擎读取 |
| 日期对应的价格与库存 | 按当前选择请求,并明确新鲜度 | 旧报价不应直接用于下单 |
| 购物车、旅客表单 | 客户端交互,必要时持久化草稿 | 用户频繁修改,且包含私有数据 |
| 最终订单金额 | 提交时由服务端重新计算 | 浏览器中的金额不能作为结算依据 |
这里的“服务端”指执行 Next.js 页面代码的环境;它与最终负责库存和订单规则的业务 API 可以是两个服务。服务端渲染不会自动保证数据正确,缓存策略和下单前复核仍然必要。
商品详情页先确定能否展示该商品,再请求首屏真正需要的信息。彼此独立的请求可同时开始;评价、推荐内容和非当前日期的价格不应拖住主要内容。对会快速变化的报价,显式使用不缓存的请求或业务允许的短时缓存,并标明报价失效后的处理方式。
在 App Router 中,交互组件才需要 use client。把整个页面都放进客户端组件,会增加发送到浏览器的 JavaScript,也让原本能在服务端完成的数据准备变成浏览器请求。向客户端传递的数据应尽量是展示所需的字段,避免把内部接口响应或敏感信息原样序列化出去。
用户先选周一、马上改选周二时,周一的请求可能更晚返回。如果直接把“最后返回的响应”显示在页面上,界面会把周一价格放到周二下面。
一个可用的状态模型应包含:当前选择、请求中的报价、有效报价、空结果和错误。发起新请求时取消旧请求,或记录请求标识,只接受与当前选择匹配的响应。按钮应在报价尚未确认时不可提交;取消请求是减少无用工作,校验响应归属才是防止旧数据覆盖新数据的关键。
提交订单时,后端再次检查库存、优惠码和金额。若报价变化,返回明确的冲突结果,让用户看到新的价格并重新确认,而不是静默改价或把下单失败统称为“网络错误”。
SSR 页面还要注意水合一致性。不要在初始渲染中直接读取 window、本地存储或浏览器时区来决定会改变页面结构的内容;等客户端挂载后再读取,并为变化提供稳定的占位或默认状态。
技术检查不应停在“页面能打开”。更能发现问题的一组路径是:从搜索进入详情、切换日期、填写不同旅客信息、应用优惠码、提交订单,再分别模拟库存冲突、报价变化和支付失败。每个异常都应能回到可继续操作的状态,用户输入不应无故丢失。
性能检查也应沿着这条路径看请求时序:首屏是否等待了无关数据,日期切换是否发出重复请求,客户端包是否包含只在服务端需要的代码。优化前记录实际瓶颈,再决定是否使用并行请求、分段加载或动态导入。
若日历支持拖拽排期,可继续阅读 React 日历拖拽的性能排查。