✨ EFLx ☁️

Back

前段时间,我写了 Safe & Consistent SWR 这篇文章,介绍了在纯客户端的 React 应用中,通过 SWR 或类似库进行数据获取的一种范式。 在实践了这种模式两个月后,这一范式的问题也逐渐浮现,并值得理性看待。

事实来源的混乱#

随着业务逻辑越来越复杂,数据的“scope”或“endpoint”会越来越多。你需要处理用户、项目、帖子等不同范围的数据和业务逻辑。这时,问题随之显现: SWR 模式通过 Key 来识别某种数据,并在此基础上构建缓存、去重、突变等功能。但是,十个 Endpoint 意味着十个 Key 定义,二十个 Endpoint 意味着二十个 Key 定义。 当规模开始增大时,你会开始思考减少模板代码。让我们看看:

  1. 在后端,我们通过 /api 或 Electron IPC 或别的什么方式,暴露了各种 CRUD 接口。
  2. 在前端 SWR 层,我们为每个 CRUD 接口定义了 Key、获取数据的 SWR 钩子和突变数据的 SWR 钩子和突变数据的钩子。
  3. 在前端组件中,我们使用了这些钩子。

貌似没有什么地方可以精简。显然,SWR 层需要手动建立 Key 与后端数据之间的关系,手写某个 CRUD 操作会改变哪些数据。这是令人不适的根源。

一个后端操作会改变什么,这件事归根结底只有后端知道。 因此,把“赋予数据 Endpoint、将变更操作与数据突变绑定”这样的任务交给前端,是不合逻辑的。后端才是这些对应关系的事实来源。

tRPC?Server Action?GraphQL?#

我首先想到了 electron-trpc。也许这有些倒反天罡,对于一般的 /api 服务器, tRPC 也是可用的方案。然而,这样会带来极大的重构成本,将后端切换到耦合度低的设计时(e.g.,运行 Go 或 Python 服务)更有风险。

那 Server Action 如何呢?我必须坦言,这样做的 DX 是非常好的。在一个“全栈”的 React 应用中,使用 RSC + Server Action 等原语并不是洪水猛兽, 事实上这些东西就像米其林餐厅里十万镑一勺的甜点,遇到一些问题时小用一下 RSC 给人的感觉非常舒适和优雅。 然而,我们不仅正在讨论具备复杂数据模型的应用——在这种情况下,Server Action 不见得好到哪去——而且,我们还在讨论纯客户端应用的解决方案。

既然后端要保持纯粹,又需要存在一个中间层,这让我们想到了 Codegen。正好,drizzle-orm 还允许我们生成 zod schema,一举两得!在这里,codegen 的意思是 根据 Schema 生成 SWR hooks。其实这个想法蛮好的,但是并没有解决突变关联的问题,也就是一个数据变更操作会引发哪些 Key 突变的问题。

最后我们貌似只有 GraphQL 之类的选项了。当我提到 GraphQL 时,它正处于一个很尴尬的境地:如果应用已经很复杂,这意味着和 tRPC 一样高的重构成本。 如果应用本身是 toy 级别的,为什么还要这么做呢?为了解决一点点过度设计的问题,我们引入了一个巨大的过度设计的设计……这不好。

略微迷茫#

因此,经过许久的思想实验之后,我其实没有对原有架构做出任何足够的改进。不过,在过去两个月里,我已经尝试了:

  • Service Locator 架构:将 SWR hooks 分类放进“service”对象中,所有 services 以 React Context 形式提供。
  • 一些减少模板代码的 utility,可以快速封装 IPC 函数或者 fetch /api/ 调用。
  • 在旧文章中,我采用基于 { endpoint: ..., /* other params */ } 的 Key 形状。但我发现 TanStack Query 鼓励的基于数组的 Key 甚至可能更好。我曾经假设我有耐心精心控制各个 key 的 mutate,最后发现,当你拥有“所有模型”、“用户添加的模型”、“用户固定的模型”、“真正的所有模型”、“模型列表的所有模型”这些乱七八糟的 Endpoint 之后,你只会在 mutate 里面一网打尽。我正在试验,并且感受到了 ['models', 'pinned'] 而非 { endpoint: 'pinnedModels' } 的正确性。

目前来看,虽然 SWR 层的代码在前端看起来非常庞大,但是它的运行仍然是稳定可靠的。加入一个新功能时,也只需要无脑复制一些模板即可。 未来,我可能会发布 Safe & Consistent SWR / Query 的第二版,包含所有更新的最佳实践。就目前为止,我依然认为这样做是最可靠、最有效的数据获取解决方案。

After Safe & Consistent SWR
https://eflx.top/blog/after-safe-consistent-swr/zh-hans
Author EFL
Published at April 18, 2026