网络,是最脆弱的一环
多数移动场景的时间,都花在「信号好,直到它不好」的网络上——地铁车厢、球场、乡间公路、漫游边境。对查看持仓的券商、接单的骑手、检票的店员来说,信号掉线的那一刻,恰恰是屏幕最需要继续工作的时候。同一台手机上的两种模型,对这个时刻的应对截然不同。
H5 是「指望」自己能离线;小程序是「生来」就能离线。
H5 离线,是和浏览器谈判
H5 页面默认被网络拴着。要离线工作,它必须注册一个 service worker——而这正是坑所在。Service Worker 只在 HTTPS(或 localhost)下运行,有注册/安装/激活/请求的多步生命周期,还要求开发者亲手用 Cache API 编写缓存策略、用 IndexedDB 落持久数据。一旦注册失败、scope 写错、更新卡死或浏览器不支持,连接一断,页面直接死。很多 H5 页面根本没实现它,于是「离线即死」是默认结果。
即便 service worker 在场,它也是一条独立后台线程,有自己的状态与失败模式。激活卡住或缓存永不刷新,往往要等用户已经对着白屏时才会暴露。
小程序把离线当原语
小程序不是事后给离线打个补丁。程序包——框架、外壳、首屏——早已在上次启动时落在设备里,本地存储又给程序一处持久的、类同步的地方保存用户数据与高频内容。信号掉线时,应用外壳从缓存渲染、缓存数据即时呈现,只有实时请求在等待与重试。流程是优雅降级,而非崩塌。
这也是同一交易型流程表现天差地别的原因:H5 先伸手要网络、再退而求缓存(如果它费心搭了的话);小程序则先用设备上已有的东西绘制,把网络当作可选项。
韧性究竟从哪来
- 预缓存包:外壳与首屏在本地,UI 无需网络往返就能打开。
- 本地数据仓:用户状态、近期行情、表单草稿在掉线后仍在,重开即现。
- 内建的降级:runtime 先画缓存视图、把实时调用排队;H5 得在脆弱的后台线程上亲手实现这一切。
- 弱网暴露面小:重资源已在本地,只有少量数据请求暴露在那条不稳的链路上。
逐项对比
| 维度 | H5 / PWA | 小程序 |
|---|---|---|
| 离线机制 | Service Worker + Cache API + IndexedDB | 预缓存包 + 本地存储 |
| 激活方式 | 独立线程、多步生命周期、可静默失败 | 内建于 runtime,默认开启 |
| 无 HTTPS 能用? | 不能——SW 强制 HTTPS | 能——本地资源无需传输层 |
| 掉线表现 | SW 缺失/损坏则白屏;有缓存才可用 | 外壳+缓存数据照常渲染;实时调用重试 |
| 开发者负担 | 手写缓存策略 + 更新处理 | 声明式包 + 存储 API |
| 弱网暴露面 | 整页重新拉取 | 仅少量实时数据请求 |
对你的流程意味着什么
任何发生在真实世界而非 Wi-Fi 旁桌面的流程,离线韧性都是功能,不是赠品。从缓存打开的行情、留住草稿的表单、仍能检票的码,就是「完成一次操作」与「一块死屏」之间的距离。H5 也能到达同一境地,但前提是亲手构建并维护一个多数页面从不交付的有状态后台 worker。
Cross Mini App 的位置
Cross Mini App 是「离线优先」模型下的 runtime 与开放 catalog。按标准 API 面构建一次的小程序,在任意宿主内运行,其包已预缓存、本地存储完好,于是即便链路不在,屏幕照样打开、数据照样在。网络退居可选层,而非地基。H5 仍是门,小程序则是那间灯闪时不会熄的房间。