这个免费且仅需单个文件的 Firebase Go 替代方案

BBetter Stack
Computing/SoftwareSmall Business/StartupsInternet Technology

Transcript

00:00:00PocketBase 是 Supabase 或 Firebase 的开源替代方案,也可能是你运行过的最简单的
00:00:04后端。它只需要一个文件,就能为你提供实时数据库、身份验证和
00:00:11文件存储。这与现代 Web 开发变得极其复杂的现状形成了鲜明对比。
00:00:16所以在今天的视频中,我们将测试 PocketBase,看看它的简单架构
00:00:21在构建复杂应用时是否真的经得起考验。
00:00:29PocketBase 是一个内置了 SQLite 的单一 Go 二进制文件。但实际上用 Go 语言编写代码是
00:00:35可选的,因为后端可以使用 JavaScript 和 TypeScript 进行扩展。你还会获得
00:00:40一个基础的管理后台 UI,可以在其中配置所有集合,这与 Supabase 的工作方式完全相同。
00:00:46现在谈谈架构以及你实际如何使用它。一旦 PocketBase 运行起来,你就可以
00:00:51通过 JavaScript SDK 从前端连接到它。这与 Firebase 和
00:00:57Supabase 的设计非常相似,你可以直接从前端访问数据库,而不必
00:01:02担心安全性,因为 PocketBase 有 API 规则和身份验证来确保这些规则的安全性。但让我们直接进入
00:01:08演示环节,展示一个包含身份验证、数据库和文件存储的真实应用。如果你喜欢这个
00:01:13视频,请订阅 Better Stack,我们在频道中涵盖了大量的开发者内容。
00:01:18我们这里有一个应用,后端使用了 PocketBase,前端则是用
00:01:22React 编写的 Web 前端。Web 前端中最重要的文件是这里的 pb.ts 文件,因为
00:01:30我们在其中引入了 pocketbase,创建了一个新的 PocketBase 类实例,
00:01:36然后连接到我们的后端服务。现在我们可以在应用的其余部分使用 pb 对象了。
00:01:42应用本身是一个简单的 Bug 追踪器,我们可以在列之间拖动项目,可以
00:01:48创建新的问题。如果我们查看控制登录用户的 Hook,你可以看到
00:01:53我们最初使用 pb.authStore.record 来设置状态,这将获取当前已验证的用户
00:01:59来自 PocketBase。然后我们也设置了一个监听器,如果身份验证存储通过
00:02:05onChange 事件发生变化,我们就会将新用户设置到状态中。使用起来就是这么简单。
00:02:11我们可以访问状态,也可以订阅状态,对于我们的问题数据也是如此。
00:02:16所以,在我们的 useIssues Hook 内部,我们同样初始化了一些状态,这次让它为空。
00:02:21然后我们使用 useEffect,获取所有问题并获取完整列表,然后
00:02:27我们用该列表设置问题状态,这将预先填充数据。然后我们
00:02:32也可以订阅问题数据,这样如果你在列之间拖动问题,或者创建/删除问题,
00:02:38我们可以通过 pb.collection(“issues”).subscribe 来实现,这样每当有新记录进入时,我们就可以
00:02:44将其附加到我们的状态中。这意味着当我们直接与 PocketBase 数据库交互时,
00:02:49比如拖动卡片时,状态会自动更新。在创建
00:02:54一个新问题时,我们也可以附上一张截图。让我们给应用程序截个图,
00:02:59然后点击提交问题,新问题就会出现在前端。代码中这通过
00:03:05提交函数处理,我们将所有表单数据附加在一起,最后调用 pb
00:03:11collection(“issues”).create 来传入数据。我们在后端拥有集合 API
00:03:17规则来防止滥用这些 API。PocketBase 默认会提供这个管理界面,
00:03:24在这里你可以看到我们有 users 集合和 issues 集合,
00:03:27我们所有的问题都存在这里。如果我们查看 users 集合,然后点击上方的设置,
00:03:32就会看到 API 规则选项卡,这些规则限制了对特定
00:03:37集合的访问。例如,对于用户,请求的 auth ID 不能是空字符串,当
00:03:43更新或删除用户时,ID 必须匹配已验证用户的 ID,我们可以通过
00:03:50此处的特殊字符串 “@request.auth.id” 来访问它。如果你过去使用过 Supabase,
00:03:56你会发现这种模式非常熟悉。那么如果后端不能
00:04:02完成你需要的一切怎么办?幸运的是,你可以通过 Hook 来扩展它,使用 Go,也可以使用 JavaScript
00:04:08和 TypeScript。我们可以挂载到各种事件,例如应用启动时的 onBootstrap,或者
00:04:15数据库记录创建时的 onRecordCreate。在拍摄时有 82 个独特的 Hook,所以几乎
00:04:21你需要的一切都已覆盖。现在让我们扩展 PocketBase 服务,看看它是如何工作的。
00:04:27如果我们查看 pb 文件夹,可以看到我们的 PocketBase 二进制文件,这个文件实际上
00:04:32就是运行默认版本 PocketBase 所需的一切。但在我的情况下,我已经编写了所有的 Hook,
00:04:38使用 TypeScript 编写的,所以我有一些设置可以将这些 Hook 编译到 pb_hooks 文件夹中作为 JavaScript,因为
00:04:44PocketBase 原生只支持 JavaScript,所以如果你使用 TypeScript,你需要将其编译。
00:04:50如果查看主要 Hook 文件,我们可以看到有一个 Hook 是 onRecordCreate,
00:04:55这专门针对我们创建问题的情况。我们在这里所做的是,
00:05:00每当记录被创建时,我们都会给用户发送一封电子邮件,我们可以通过调用
00:05:05e.app.newMailClient().send() 并传入我们在这里构建的消息对象来实现。
00:05:10你当然可以挂载到 PocketBase 内部大量的不同功能中,因此任何自定义功能
00:05:15你可能需要的,都将得到 PocketBase 中 82 个以上的 Hook 的支持。
00:05:21因为这里运行的是 SQLite,这意味着我们需要持久化存储。所以像 Heroku、Render
00:05:28或 Railway 这样的平台实际上不太合适,因为它们的文件系统是短暂的,基本上你每次重新部署应用时都会丢失数据。
00:05:33为了避免这种情况,你可以挂载一个永久文件系统。但更好且更便宜的选择
00:05:39是直接托管在 VPS 上,数据就保存在 pb_data 文件夹中。所以如果
00:05:45查看这里,你可以看到我们有一个存储文件夹,它将包含所有
00:05:50我们上传到问题中的图片。它们恰好存储在存储文件夹中,所以
00:05:55在例如这个随机 ID 文件夹里,你可以看到我之前上传到问题中的图片。
00:05:59数据库文件本身也会保存在这个文件夹中。这里的 data.db
00:06:05包含了我们所有的 SQLite 代码,所以如果我删除了这个文件,我就会丢失应用中的所有数据。
00:06:11所以很明显,你需要一个好的备份策略,而不是仅仅把它作为一个单文件留在磁盘上。
00:06:16与 Supabase 等起步价 25 美元的工具相比,PocketBase
00:06:22基本上是免费的。你只需要支付 VPS 费用,低至 4 美元即可,并且允许
00:06:28你随心所欲运行多个项目,当然随着使用量增加,你也会希望扩展它。
00:06:33PocketBase 还为你提供了生产应用所需的一切,如迁移、作业调度和
00:06:38日志记录。你也可以通过将静态文件放入 pb_public 文件夹来直接使用 PocketBase 提供服务,
00:06:44这对 React 前端等很有用。另外你也可以托管
00:06:49带有模板渲染的动态路由,这对于电子邮件模板等场景非常完美。所以如果你
00:06:54确实想要一个单盒子设置,那么这就是实现方法。现在最大的问题是:它是否已为生产准备就绪?
00:06:59它确实包含了构建现代 SaaS 应用所需的所有功能,特别是
00:07:04迁移和日志记录等生产级功能。它也是完全可扩展的,所以你不会仅仅
00:07:09受限于默认配置。但最大的坑在于它还处于 v1 版本之前,所以他们明确表示,只有在
00:07:15你能接受阅读变更日志并时不时手动执行迁移的情况下才使用它。但如果是的话,
00:07:20那么放手去做吧,你完全可以构建出第一个单文件独角兽应用。你可以通过查看
00:07:25描述中的相关链接来了解更多关于 PocketBase 的信息。如果你喜欢开源替代方案,
00:07:29那么一定要看看我们关于 OpenCode 的视频,它是 Claude Code 的开源替代品。我是 Better Stack 的 Warren,
00:07:35感谢观看,我们下次见。

Key Takeaway

PocketBase 提供了一个基于 SQLite 的轻量化、单一二进制文件后端解决方案,通过配套的 SDK 和高度扩展的 Hook 机制,能以极低成本支撑 SaaS 应用的实时数据与身份验证需求。

Highlights

  • PocketBase 将实时数据库、身份验证和文件存储封装在一个单一的 Go 二进制文件中。

  • 开发人员可以通过 JavaScript SDK 从前端直接连接并访问数据库,安全规则由后端 API 规则管理。

  • 后端支持使用 JavaScript 和 TypeScript 进行功能扩展,提供超过 82 个 Hook 挂载点。

  • PocketBase 使用 SQLite 作为数据存储引擎,所有数据保存在本地的 pb_data 文件夹中。

  • 部署成本极低,仅需配置一个支持持久化存储的 VPS,起步费用可低至 4 美元。

  • PocketBase 尚未发布 v1 版本,使用时需具备阅读变更日志并执行手动迁移的能力。

Timeline

架构特点与前端交互

  • 单一 Go 二进制文件内置了 SQLite 数据库。
  • 前端通过 SDK 直接访问数据,配合 API 规则保证安全性。
  • 支持通过身份验证存储获取用户状态并实时订阅数据变化。

PocketBase 旨在简化现代 Web 开发的复杂性。其架构允许开发者无需构建传统复杂的后端 API,即可在前端使用 JavaScript SDK 连接数据库。安全性通过集合 API 规则与身份验证机制实现,与 Supabase 的设计逻辑相似,确保直接从前端操作数据时依然受控。

数据库交互与 API 规则

  • 支持数据的实时订阅与自动状态更新。
  • 通过管理界面配置集合与访问规则。
  • API 规则利用特殊字符串如 @request.auth.id 限制特定记录的操作权限。

在 Bug 追踪器等应用场景中,前端利用钩子函数初始化状态并监听数据库变更。通过 pb.collection 订阅功能,当记录被创建、更新或删除时,前端状态能实现自动同步。后端管理界面直观地控制数据集合及复杂的权限规则,确保只有符合要求的已验证用户才能访问特定数据。

后端扩展与存储策略

  • 通过超过 82 个 Hook 实现自定义功能扩展。
  • 使用 TypeScript 开发的 Hook 需编译为 JavaScript 存入 pb_hooks 文件夹。
  • 数据需存储在持久化文件系统中,避免因临时文件系统导致的丢失。

虽然 PocketBase 原生提供核心功能,但开发者可通过 Hook 挂载到应用生命周期,如记录创建触发器。由于其 SQLite 本质,数据存储在本地文件夹,因此不建议使用文件系统短暂的托管平台,直接托管在 VPS 上并配合良好的备份策略是保障数据安全的关键。

生产环境就绪度与成本

  • 相较于每月 25 美元起的同类工具,PocketBase 仅需支付低廉的 VPS 费用。
  • 支持静态文件服务、动态路由托管、迁移及任务调度等生产功能。
  • 由于处于 v1 之前版本,使用者需预留手动执行迁移的维护工作。

PocketBase 具备迁移、日志记录和作业调度等 SaaS 开发所需的完备功能,且支持直接托管静态前端。尽管目前尚未进入稳定生产版本,但其极简架构和高扩展性使其成为构建小型独角兽项目的有力候选。开发者应权衡其手动维护成本与极低的运营成本。

Community Posts

View all posts