WeatherToRun

使用 Next.js Edge Functions、多层缓存与自定义天气评分算法,构建高性能 PWA,帮助跑者更好地安排训练。

Next.jsTypeScriptPWAEdge Functions性能
WeatherToRun

问题

如果你经常跑步,几乎每天都会遇到同一个问题:现在适不适合跑?该怎么穿?

大多数天气应用只给你温度、湿度、风速这些数字,但并不会告诉你“现在是否值得出门跑步”。我每天早上都要在脑子里做一次权衡,结果并不总是准确:有时穿太多,有时被冷风或突发降雨打个措手不及。

我如何构建这套方案

WeatherToRun 的核心思路很直接:把“人脑临时计算”变成“应用自动判断”。

应用会把多个天气因素合并成一个 1-100 分的跑步评分,并给出颜色化结论("差"、"一般"、"好"),让决策更快。

我重点实现了以下能力:

  • 基于研究的评分模型:温度(30%)、风(25%)、露点(20%)、降水(15%)、UV(10%)都来自对跑步表现和体感影响的实际资料,而不是拍脑袋。
  • Edge 优先的 API:天气接口跑在 Vercel Edge Runtime,冷启动从传统 serverless 的秒级降到几十毫秒级。
  • 多层缓存:边缘缓存 + 客户端缓存(TanStack Query)+ 坐标精度控制,显著提升命中率和响应速度。
  • 个性化穿衣建议:通过“多穿一点 / 少穿一点”偏好开关适配不同体感。
  • 离线可用 PWA:支持安装到手机主屏,在弱网/离线场景下保持可用。

从草图到界面

编码前我先画了草图,明确首页信息优先级:

  1. 当前评分
  2. 穿衣建议
  3. 其他辅助信息

这让产品在实现阶段始终围绕“快速决策”而不是“展示更多数据”。

WeatherToRun 草图 1 - 主界面探索WeatherToRun 草图 2 - 组件结构WeatherToRun 草图 3 - 用户流程

早期线框草图:主视图、组件结构与用户流程。

离线与可靠性设计

PWA 的关键不是“全部缓存”,而是“按资源类型使用正确策略”:

  • CacheFirst:静态资源(JS/CSS/图片),提升速度并节省带宽。
  • NetworkFirstmanifest,优先取新,失败回退缓存。
  • NetworkOnly:导航和 RSC payload,避免陈旧数据导致状态错乱。

我还加了友好的离线页面,避免用户看到浏览器默认错误页。

生产环境中的关键工程点

故障处理

  • 网络波动与 429 限流时使用 指数退避重试
  • 天气接口超时更宽松,AQI 更严格;AQI 失败不阻断主流程。

评分模型(简化)

因素权重说明
温度30%对体感与配速影响最大
25%逆风显著拖慢配速
露点20%比湿度更能反映闷热不适
降水15%雨雪与风暴风险
UV10%热负荷与曝晒风险

数据新鲜度

仅用 ISR 的时间重验证在低流量页面会失效。为此我加入了主动刷新机制:

  • 每 30 分钟触发一次安全的 /api/revalidate
  • 使用 revalidateTag('weather') 统一失效天气相关缓存
  • 结合 stale-while-revalidate,保证首屏快且数据持续更新

结果与收获

这个项目最关键的收获是:

  • 用户不需要更多原始数据,用户需要更快、更可信的决策。
  • 性能优化与容错处理虽然“不可见”,却决定产品是否好用。
  • Edge + 合理缓存策略能把“工具类应用”的体验从可用提升到丝滑。