跳到主要内容

为什么我重新认真看待 Local-first

· 阅读需 6 分钟
Jimmy
前端

Local-first 最近又被频繁提起,但这次的讨论已经和十年前不是同一个语境。

我第一次接触 PouchDBCouchDB 时,就意识到这条路线真正想改的不是缓存策略,而是 Web 应用默认把可用性和响应速度都押在网络上的前提。

PouchDB 当年其实已经把方向指对了

PouchDB 让前端开发者第一次比较系统地拥有了在用户设备上存储结构化数据、离线读写、再与远端同步的能力。那时它最打动人的地方,不是某个 API 设计得多漂亮,而是它让人意识到:原来 Web 应用也可以在断网时继续工作,而不是只能原地报错。

CouchDB 的设计也很有启发性。它把同步、版本和文档模型变成数据库内建能力,而不是全部交给业务系统自己拼。前端和数据库之间的距离被明显拉近了,很多过去必须经过中间层才能完成的事情,第一次有了更直接的实现路径。

但这条路线并没有在当年真正进入主流。PouchDB 生态后来逐渐降温,社区也慢慢沉寂下来。问题不在方向错了,而在当时的浏览器、工具链和团队认知都还没准备好。

问题不是理念不对,而是当时条件不够

我现在回头看,至少有三类阻力很现实:

  1. 工程门槛高:你不仅要会写前端,还得理解建模、同步、索引、冲突这些原本更像数据库工程的问题。
  2. 默认架构惯性太强:大多数团队早就习惯了“前端调接口,服务端管数据”,要切到“本地先可用”并不只是换个库。
  3. 浏览器能力当时不够成熟:早期存储能力、执行性能和相关 API 远没有今天稳定,复杂数据应用很容易撞墙。

现在回头看,时机确实不一样了

过去几年真正改变局面的,不是一句“离线优先”口号,而是浏览器底层能力终于补上来了。尤其是 WebAssembly 和配套存储能力成熟之后,前端第一次有条件认真讨论“在浏览器里跑数据库”这件事。

几个变化尤其关键:

  • wa-sqlite 把 SQLite 带进浏览器,让本地关系型查询、索引和事务不再只是原生应用的专利。
  • PGlite 进一步把 PostgreSQL 风格的能力推进到前端运行时,复杂查询不必一开始就退回服务端。
  • 浏览器侧持久化、Worker、WASM 配套工具链也比过去成熟得多,本地数据层终于有了可持续工程化的基础。

这意味着 Local-first 不再只能停留在“缓存列表页数据”这种轻量级用法,而开始有机会支撑真正复杂的业务数据场景。

前端已经不只是“调接口然后渲染”了

Figma 这类产品已经证明,浏览器不是只能负责展示的壳。它完全可以承载复杂状态、实时协作和大量客户端计算。这个变化对前端开发的影响很直接:

  • 前端不再只是消费 API 的一层界面。
  • 复杂业务规则和部分数据处理可以直接在客户端落地。
  • 用户体验不必处处受制于网络往返和服务端响应时间。

所以我现在更愿意把 Local-first 理解成一种架构选择:把“先可用、先响应、先落地到用户设备”作为默认前提,再去设计同步、协作和远端一致性,而不是反过来。

这也是我们为什么要做 @aiao/rxdb

基于这些思考,我们团队正在打造 @aiao/rxdb。它想解决的不是“再包装一个 Local-first 概念”,而是把浏览器内数据层真正做成可复用、可维护、能落在业务里的工程基础设施。

目前我们更关注下面几件事:

1. 先把模型立住

  • 用声明式模型定义实体、字段、关系和约束。
  • 让类型、查询能力和生成代码围绕模型展开,而不是散落在页面和服务层里。
  • 降低“业务越复杂,数据代码越碎”的问题。

2. 再把数据库能力接进熟悉的前端栈

  • 在 Angular、React、Vue 中复用同一套模型、查询和实体语义。
  • 差异只保留在各框架自己的绑定层,而不是把数据层 API 做成三套完全不同的东西。
  • 让团队可以先讨论数据结构和查询语义,再讨论具体 UI 框架怎么接。

3. 把数据层和界面层拆开

  • 让本地持久化、响应式查询、实体操作和 UI 层之间有清晰边界。
  • 少写围绕缓存、同步状态和接口转换的胶水代码。
  • 为后续的同步、协作和版本能力留出稳定扩展点。

4. 让前端的数据结构真正变成资产

  • 当数据真正落在前端,本地数据结构就不再只是临时状态,而会逐渐变成可复用资产。
  • 复杂查询、树结构、关系遍历、派生视图这些能力,应该像组件一样被复用,而不是每个项目从头再写一遍。

什么情况下,你应该认真试一次 Local-first

如果你的应用已经出现这些信号,现在就值得认真看一遍这条路线:

  • 页面越来越像一个本地工作台,而不是简单的数据展示层。
  • 用户对离线可用、秒开、低延迟操作反馈开始有明确要求。
  • 前端里已经堆了大量缓存逻辑、状态补丁和接口二次封装。
  • 你希望同一套数据抽象能在不同框架里复用,而不是反复重写。

Local-first 对我来说,已经不是一句“未来趋势”的判断,而是前端工程边界变化后的自然结果。浏览器现在终于有能力承接更重的数据职责,接下来真正有价值的问题,不是要不要继续喊口号,而是怎样把这层能力做得更稳、更清晰、更适合真实业务。

如果这些问题也是你现在正在面对的,欢迎看看我们的 GitHub 仓库,也欢迎直接拿实际业务场景来讨论。比起再讲一遍愿景,我更关心它能不能在真实项目里成立。