ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SpacetimeDB Remix 快速上手:用 `spacetime dev --template remix-ts` 在 5 分钟内搭建全栈实时应用

SpacetimeDB Remix 快速上手:用 `spacetime dev --template remix-ts` 在 5 分钟内搭建全栈实时应用 SpacetimeDB Remix 快速上手用spacetime dev --template remix-ts在 5 分钟内搭建全栈实时应用【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB本文是 SpacetimeDB 官方 Remix 快速入门指南的完整实操讲解面向希望在 RemixVite应用中接入 SpacetimeDB 实时数据库的 TypeScript 开发者。通过spacetime dev一条命令即可自动完成本地服务器启动、模块发布、TypeScript 绑定生成与 Remix 开发服务器启动阅读完本文你将掌握 SpacetimeDB 模块表与 reducer的编写方式、Remix loader 的服务端数据获取SSR与 WebSocket 实时订阅的配合模式以及用 CLI 直接调用 reducer、查询数据和查看日志的调试方法。前置条件开始之前请确保本地环境满足以下要求Node.js 18Remix 2.x 与 Vite 5 需要较新的 Node 运行时模板依赖见 templates/remix-ts/package.json其中remix-run/node、react均为 18 系依赖SpacetimeDB CLI提供spacetime命令用于创建项目、管理本地服务器、发布模块、调用 reducer 与查询数据。安装完成后在终端验证spacetime --version可正常输出版本号即可继续。创建项目spacetime dev --template remix-ts在目标目录执行spacetime dev --template remix-tsspacetime dev是一个一体化开发命令它会依次完成以下工作启动本地 SpacetimeDB 服务器在当前环境拉起一个本地数据库实例供模块发布与连接使用发布你的模块把spacetimedb/src/index.ts中定义的 schema 与 reducer 编译并发布到本地服务器生成 TypeScript 绑定根据模块 schema 自动生成类型安全的客户端绑定代码位于src/module_bindings/包括表查询构建器、reducer 访问器等启动 Remix 开发服务器运行 Vite dev server默认监听http://localhost:5173。命令执行完成后浏览器访问 http://localhost:5173 即可看到运行中的应用。环境变量注入spacetime dev会自动为应用注入连接所需的配置。从模板源码 templates/remix-ts/app/lib/spacetimedb.server.ts 可以看到服务端代码读取SPACETIMEDB_HOST与SPACETIMEDB_DB_NAME默认回退到wss://maincloud.spacetimedb.com与remix-ts客户端根布局 templates/remix-ts/app/root.tsx 则读取以VITE_前缀暴露的VITE_SPACETIMEDB_HOST与VITE_SPACETIMEDB_DB_NAME。这意味着同一份代码既可以跑本地开发也可以在不改代码的情况下指向云端部署。探索项目结构spacetime dev --template remix-ts生成的项目同时包含服务端SpacetimeDB 模块与客户端Remix代码my-remix-app/ ├── spacetimedb/ # 你的 SpacetimeDB 模块 │ └── src/ │ └── index.ts # SpacetimeDB 模块逻辑 ├── app/ # Remix 应用 │ ├── root.tsx # 根布局包含 SpacetimeDBProvider │ ├── lib/ │ │ └── spacetimedb.server.ts # 服务端数据获取工具 │ └── routes/ │ └── _index.tsx # 首页含 loader 与实时组件 ├── src/ │ └── module_bindings/ # 自动生成的类型绑定 └── package.json各目录职责说明spacetimedb/src/index.ts模块的唯一代码入口定义表结构与 reducer 逻辑是你要经常编辑的文件app/root.tsxRemix 根布局负责用SpacetimeDBProvider包裹整个应用并管理 WebSocket 连接的构建、鉴权 token 的本地持久化app/lib/spacetimedb.server.ts仅在 Node 服务端运行的连接工具供 Remix loader 做首屏数据获取app/routes/_index.tsx首页路由同时演示loader 服务端取数 hooks 客户端实时更新的完整链路src/module_bindings/由spacetimeCLI 根据模块 schema 自动生成不要手改。该目录包含person_table.ts、add_reducer.ts、say_hello_reducer.ts、types.ts、index.ts等文件例如 templates/remix-ts/src/module_bindings/index.ts 中导出了类型安全的tables查询构建器、reducersreducer 访问器、DbConnection/DbConnectionBuilder/SubscriptionBuilder等类文件头部注释也明确标注由 SpacetimeDB 自动生成修改不会保留。从 templates/remix-ts/package.json 可以看到绑定再生成的备用方式# 方式一使用 spacetime CLI spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb # 方式二使用仓库内置的 gen-bindings 工具链 pnpm --dir spacetimedb install cargo run -p gen-bindings -- --out-dir src/module_bindings --module-path spacetimedb另有两个发布脚本spacetime publish --module-path spacetimedb --server local发布到本地与spacetime publish --module-path spacetimedb --server maincloud发布到 SpacetimeDB 云端。理解表Tables与 reducerReducers打开spacetimedb/src/index.ts这是整个应用的数据层核心。模板给出了一个最简可运行示例一张person表以及add、sayHello两个 reducer。import { schema, table, t } from spacetimedb/server; const spacetimedb schema({ person: table( { public: true }, { name: t.string(), } ), }); export default spacetimedb; export const add spacetimedb.reducer( { name: t.string() }, (ctx, { name }) { ctx.db.person.insert({ name }); } ); export const sayHello spacetimedb.reducer(ctx { for (const person of ctx.db.person.iter()) { console.info(Hello, ${person.name}!); } console.info(Hello, World!); });两个核心概念表Table存储数据table({ public: true }, { name: t.string() })定义了一张公开可读的person表仅含一个字符串字段name。t.string()来自spacetimedb/server的类型系统所有列类型都必须用它声明布尔值t.bool()、数字t.i32()、字符串t.string()等Reducer 修改数据reducer 是唯一可以写入数据库的函数即数据库写入必须经过 reducer客户端无法直接修改表内容。addreducer 接收{ name: t.string() }参数并通过ctx.db.person.insert({ name })插入一行sayHelloreducer 遍历ctx.db.person.iter()逐人打印问候语。模板 templates/remix-ts/spacetimedb/src/index.ts 中还内置了三个生命周期钩子init模块首次发布时调用、onConnect每个新客户端连接时调用、onDisconnect客户端断开时调用它们同样用spacetimedb.init/spacetimedb.clientConnected/spacetimedb.clientDisconnected声明适合在后续扩展中做种子数据初始化或在线人数统计。用 CLI 测试模块另开一个终端进入项目目录后即可用spacetimeCLI 直接与本地服务器交互。注意下例中 reducer 名在 CLI 侧使用蛇形命名say_hello与 TypeScript 侧的驼峰sayHello对应——这一点可以从自动生成的绑定文件 templates/remix-ts/src/module_bindings/index.ts 中看到 reducer 的 schema 名注册为say_hellocd my-remix-app # 调用 add reducer插入一个人 spacetime call add Alice # 查询 person 表 spacetime sql SELECT * FROM person name --------- Alice # 调用 sayHello向所有人打招呼 spacetime call say_hello # 查看模块日志 spacetime logs 2025-01-13T12:00:00.000000Z INFO: Hello, Alice! 2025-01-13T12:00:00.000000Z INFO: Hello, World!这套CLI 直连的验证方式在整个开发周期都很有用写 reducer 时无需打开浏览器即可快速确认表结构、调用参数与日志输出是否符合预期。理解服务端渲染SSR数据流SpacetimeDB 的 TypeScript SDK 同时支持服务端与客户端运行。Remix 模板采用了SSR 首屏 WebSocket 实时的双通道数据模式Loader服务端在服务端渲染期间从 SpacetimeDB 拉取初始数据客户端保持一条实时的 WebSocket 订阅连接持续接收表的增删改更新。app/lib/spacetimedb.server.ts提供了服务端取数工具函数fetchPeople。下面是与文档对应的模板实际源码templates/remix-ts/app/lib/spacetimedb.server.ts它比文档示例多了超时与错误处理更贴近生产// app/lib/spacetimedb.server.ts import { DbConnection, tables } from ../../src/module_bindings; import { Person } from ../../src/module_bindings/types; import type { Infer } from spacetimedb; const HOST process.env.SPACETIMEDB_HOST ?? wss://maincloud.spacetimedb.com; const DB_NAME process.env.SPACETIMEDB_DB_NAME ?? remix-ts; export type PersonData Infertypeof Person; export async function fetchPeople(): PromisePersonData[] { return new Promise((resolve, reject) { const timeoutId setTimeout(() { reject(new Error(SpacetimeDB connection timeout)); }, 10000); const connection DbConnection.builder() .withUri(HOST) .withDatabaseName(DB_NAME) .onConnect(conn { conn .subscriptionBuilder() .onApplied(() { clearTimeout(timeoutId); const people Array.from(conn.db.person.iter()); conn.disconnect(); resolve(people); }) .onError((_ctx, error) { clearTimeout(timeoutId); conn.disconnect(); reject(error); }) .subscribe(tables.person); }) .onConnectError((_ctx, error) { clearTimeout(timeoutId); reject(error); }) .build(); }); }这段代码演示了服务端短连接模式的标准写法DbConnection.builder()配置连接 →onConnect回调里用subscriptionBuilder().onApplied()等待订阅首次生效 → 从本地缓存conn.db.person.iter()取出全量数据 →立即disconnect()释放连接。它是一次性取数而不是长驻连接。与之相对客户端app/root.tsxtemplates/remix-ts/app/root.tsx维护的是长驻连接通过SpacetimeDBProvider注入全局连接并用localStorage按${HOST}/${DB_NAME}/auth_token缓存鉴权 token实现刷新后身份保持同时它在 SSR 阶段typeof window undefined跳过 Provider 渲染避免服务端启动 WebSocket。这种服务端短连接取数、客户端长连接订阅的分工是 Remix SpacetimeDB 的核心架构模式。用 Loader 与 Hooks 驱动 UI 数据app/routes/_index.tsx把上面两条数据通道接进了 UItemplates/remix-ts/app/routes/_index.tsx// app/routes/_index.tsx import { useLoaderData } from remix-run/react; import { tables, reducers } from ../../src/module_bindings; import { useTable, useReducer } from spacetimedb/react; import { fetchPeople } from ../lib/spacetimedb.server; export async function loader() { const people await fetchPeople(); return { initialPeople: people }; } export default function Index() { const { initialPeople } useLoaderDatatypeof loader(); // 来自 WebSocket 订阅的实时数据 const [people, isLoading] useTable(tables.person); const addPerson useReducer(reducers.add); // 客户端连接建立前先用服务端数据渲染 const displayPeople isLoading ? initialPeople : people; return ( ul {displayPeople.map((person, i) li key{i}{person.name}/li)} /ul ); }工作流程分为三个阶段服务端取数Remix 在渲染前调用loader()通过fetchPeople拿到初始people列表并注入页面 HTML因此首屏包括无 JS 场景就能看到数据客户端连接useTable(tables.person)建立或复用root.tsx中 Provider 提供的WebSocket 订阅isLoading为true表示本地缓存尚未就绪无缝切换isLoading ? initialPeople : people保证连接建立前的短暂窗口内继续展示 SSR 数据之后平滑过渡到实时数据用户不会感知到闪断。useTable与useReducer来自spacetimedb/react。从 SDK 源码 sdks/typescript/src/react/index.ts 可以看到该模块共导出SpacetimeDBProvider、useSpacetimeDB、useTable、useReducer、useProcedure五个入口其中useTable实现见 sdks/typescript/src/react/useTable.ts基于 React 的useSyncExternalStore实现除全表订阅外还支持查询过滤写法例如tables.user.where(r r.online.eq(true))并可通过onInsert/onDelete/onUpdate回调监听行级事件——在模板基础上扩展在线状态实时更新、未读消息计数等场景时可以直接复用。模板首页的实际实现还额外处理了表单提交addReducer({ name })调addreducer 写入数据库、连接状态展示Connecting.../Connected与客户端 hydration 判定isHydrated这些细节在 templates/remix-ts/app/routes/_index.tsx 中均有完整源码可参考。下一步阅读 Chat App 完整教程学习多表关联、消息订阅等更完整的实战示例查阅 TypeScript SDK 参考文档深入了解DbConnection、SubscriptionBuilder、类型系统与全部 hooks 的 API 细节在本仓库中浏览 templates/remix-ts 模板源码以及spacetimedb/react相关 hooks 的实现sdks/typescript/src/react进一步理解模板各文件与 SDK 的对应关系。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表