HTML5离线增量同步需用IndexedDB存操作日志而非快照,每条含id、docId、操作类型、Delta内容、timestamp、clientId及pending状态;Service Worker按序提交pending记录,服务端基于clientVersion幂等合并变更,冲突时返回明确响应。

HTML5 离线数据同步要实现增量同步而非全量覆盖,核心不是“把整个文件或记录重传一遍”,而是识别变化、只传差异、在客户端与服务端协同重建最新状态。这需要分层配合:本地存储负责暂存变更、网络层精准识别差异、服务端支持原子化合并。全量覆盖浪费带宽、延长同步时间、增加冲突概率;增量同步则让离线编辑、小范围更新、弱网环境下的同步真正可行。
用 IndexedDB 存操作日志,不是存快照
别把整个文档或表单数据定期 dump 成一份新副本存 localStorage —— 那本质还是全量。正确做法是把每次用户操作(如输入一段文字、删除一行、修改字段值)封装成一条结构化日志,写入 IndexedDB:
- 每条记录含唯一 id、文档标识 docId、操作类型(insert/update/delete)、变更内容(建议用 JSON Patch 或 Delta 格式)、毫秒级 timestamp、设备 clientId
- status 字段标记为 pending,表示待同步;成功后改为 synced,失败则保留并设为 failed,便于后续重试
- IndexedDB 支持按 docId + timestamp 建索引,网络恢复后可直接 cursor 扫描出所有 pending 记录,按序提交,避免乱序导致的数据错乱
服务端接收差异,不做覆盖,做合并
前端上传的不该是“新版完整数据”,而应是“从哪个版本起发生了哪些变更”。服务端需具备幂等处理与版本合并能力:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 请求体携带 clientVersion(即该操作基于的上一个已知服务端版本号),服务端比对当前 latestVersion
- 若 clientVersion === latestVersion,直接应用变更,version 自增
- 若 clientVersion
- 前端收到冲突后,可用 OT(Operational Transformation)或轻量 CRDT 策略本地计算合并结果,再带新 clientVersion 重发
资源类文件(如 HTML/CSS/JS)用分块哈希做差异上传
针对静态资源包或 H5 离线包更新,避免整包重新下载。采用基于内容的分块策略识别变化:
立即学习“前端免费学习笔记(深入)”;
- 客户端将新 HTML5 包按固定大小(如 4KB)切块,计算每块 SHA-256 哈希,生成哈希列表
- 向服务端请求目标版本的哈希列表;服务端返回缺失块索引(或使用 Rabin 滚动哈希动态分块,抗插入偏移)
- 客户端仅上传不匹配的块 + 元信息(位置、长度),服务端按索引拼接重组完整文件
- 配合 ETag 和 If-None-Match 请求头,无变更时直接 304 响应,跳过全部哈希比对流程
用 Service Worker + Background Sync 驱动可靠上传
不能依赖用户手动点击“同步”按钮,也不能只靠 online 事件——它不可靠。必须由 Service Worker 主动兜底:
- 页面加载时注册 background sync:navigator.serviceWorker.ready.then(sw => sw.sync.register('sync-' + docId))
- 在 Service Worker 的 sync 事件中,查询 IndexedDB 获取该 docId 的所有 pending 记录,按 timestamp 排序逐条 POST
- 失败请求不丢弃,标记 status: 'failed' 并保留在 DB 中;下次 sync 触发时继续尝试
- 服务端响应需明确返回 success、conflict 或 retry-after,前端据此决定是否暂停、合并或延迟重试


















