SpacetimeDB TypeScript SDK 测试应用脚手架:React + Vite + TypeScript 工程化配置与 ESLint 类型感知规则实战
【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB
本指南以 SpacetimeDB 仓库中 crates/bindings-typescript/test-app 的工程说明为主体,系统讲解其基于 Vite + React + TypeScript 的前端脚手架结构、Fast Refresh 插件机制,以及从"基础语法检查"升级到"类型感知(type-aware)"的 ESLint 规则配置全流程。读完本文,你将掌握如何在 SpacetimeDB TypeScript SDK 客户端项目中搭建标准工程链路,并将 ESLint 从纯语法层提升到基于完整 TypeScript 类型信息做静态分析的生产级水准。
一、脚手架全景:test-app 在仓库中的定位与目录结构
crates/bindings-typescript/test-app是 SpacetimeDB TypeScript 绑定(@clockworklabs/spacetimedb-sdk)的 React 端测试应用。它的 README 采用 Vite 官方模板约定,描述了其工程骨架:React + TypeScript + Vite,并配置了 HMR(热模块替换)与 ESLint 规则。
从仓库实际文件看,该测试应用由两部分组成:
- 服务端模块:server/src/lib.rs 用 Rust 定义数据库表(
player、user、unindexed_player)、reducer(create_player、set_player_alias)与程序化视图(my_user_procedural); - 客户端脚手架:
src/下是 React 入口(main.tsx、App.tsx)、样式与自动生成的类型绑定src/module_bindings/。
关键工程文件一览:
| 文件 | 职责 |
|---|---|
| package.json | npm 脚本、依赖与 devDependencies 声明 |
| vite.config.ts | Vite 构建与插件配置 |
| tsconfig.json | 顶层项目引用(references)入口 |
| tsconfig.app.json | 应用代码(src/**/*)编译配置 |
| tsconfig.node.json | Vite 配置等 Node 侧文件编译配置 |
| index.html | Vite 的 HTML 入口,挂载#root |
其中 tsconfig.app.json 中有一个值得注意的细节:"include": ["src/**/*", "vite.config.ts", "../src/**/*"]将 SDK 源码../src/一并纳入编译范围——这使测试应用可以直接基于 SDK 源码(而非发布产物)进行联调与类型检查,这是仓库内联测试场景的典型做法。
二、Vite 插件体系与 React Fast Refresh
README 明确指出,目前官方提供两个 React 插件,二者都用于在 Vite 中启用 React 的Fast Refresh(快速刷新,即编辑组件后保留状态的即时热更新),区别仅在转译实现:
- @vitejs/plugin-react:基于Babel实现 Fast Refresh,并通过 Babel 完成 JSX 等语法转换;
- @vitejs/plugin-react-swc:基于SWC(用 Rust 编写的超快转译器)实现同样的 Fast Refresh,通常能获得更快的编译速度。
本测试应用采用的是前者。其 vite.config.ts 是全仓库最精简的配置形态:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], });对应的依赖声明见 package.json 的devDependencies:"@vitejs/plugin-react": "^4.3.1"、"typescript": "^5.2.2"、"vite": "^7.1.5",运行时依赖则只有react与react-dom(均为^18.3.x)。README 中"两个官方插件二选一"的说明意味着:将@vitejs/plugin-react替换为@vitejs/plugin-react-swc即可切换转译后端,其余配置(如tsconfig、ESLint)完全复用。
三、把 ESLint 从语法检查升级为类型感知分析
README 的核心段落针对"生产级应用"给出了官方推荐:开启type-aware lint rules(类型感知规则)。这类规则需要 TypeScript 的类型信息,因此能捕获仅靠语法层无法发现的错误,例如跨模块类型不匹配、隐式 any 引发的运行时风险等。配置分三步:
1. 配置顶层parserOptions.project
让@typescript-eslint/parser知道去哪里加载类型信息:
export default { // other rules... parserOptions: { ecmaVersion: 'latest', sourceType: 'module', project: ['./tsconfig.json', './tsconfig.node.json', './tsconfig.app.json'], tsconfigRootDir: __dirname, }, };要点解析:
project:指定参与类型检查的 tsconfig 列表。因为本工程采用project references(顶层 tsconfig.json 通过references指向tsconfig.app.json与tsconfig.node.json),需要把所有子配置都列全,与 Vite 模板的构建方式(tsc -b && vite build)保持一致;tsconfigRootDir:告诉解析器project里的相对路径以哪个目录为基准,避免相对路径解析错位。
2. 升级规则集为类型感知版本
将extends中的plugin:@typescript-eslint/recommended替换为带类型检查的版本:
plugin:@typescript-eslint/recommended-type-checked—— 在 recommended 基础上追加需要类型信息的规则;plugin:@typescript-eslint/strict-type-checked—— 更严格,包含更多可能"误报"但更严谨的规则;- 可选追加
plugin:@typescript-eslint/stylistic-type-checked—— 专注于代码风格但同样依赖类型信息的规则(如禁止不必要的可选链、推荐布尔表达式的规范写法等)。
3. 接入 React 专属插件
安装 eslint-plugin-react,并在extends中加入plugin:react/recommended与plugin:react/jsx-runtime。其中jsx-runtime规则与 React 17+ 的 JSX 转换方式(无需在文件中显式import React)配套,正好对应该仓库 tsconfig.app.json 中的"jsx": "react-jsx"设置。
仓库实际配置对照
SpacetimeDB 仓库根目录的 eslint.config.js 已采用 ESLint 9 的flat config语法实现了类型感知分析,可作为更现代的参考范本:
- 对
**/*.{ts,tsx}文件开启tseslint.configs.recommended,并在parserOptions.project中显式列出包括./crates/bindings-typescript/tsconfig.json、./crates/bindings-typescript/test-app/tsconfig.json在内的多个 tsconfig(见 eslint.config.js 第 60-66 行); - 启用
react-hooks与react-refresh插件,其中react-refresh/only-export-components警告组件文件只能导出组件——这正是 Fast Refresh 正常工作的重要前提; - 通过
no-restricted-syntax禁止在 SDK 中使用TSEnumDeclaration(枚举)与装饰器,强制使用 JS 兼容类型,保证 SDK 能运行在更广泛的运行时上; parserOptions.projectService: true配合tsconfigRootDir: __dirname完成类型服务连接。
这套配置说明:README 描述的"升级路径"在仓库中不是纸面建议,而是实际落地并被 lint 脚本(eslint . && prettier . --check)持续执行的工程规范。
四、脚手架在 SpacetimeDB 客户端中的实战串联
理解脚手架之后,回到它在 TypeScript SDK 测试应用中的真实用途。完整数据流如下:
1. 服务端模块定义(server/src/lib.rs):Rust 侧声明表结构与 reducer,例如create_player接收name: String与location: Point并写入user、player两张表。
2. 生成类型绑定(src/module_bindings/):由 CLI 生成、注释明确"不要手工编辑"。以 create_player_reducer.ts 为例,它把 reducer 的参数 schema 表达为name: __t.string()与location: Point;player_table.ts 则用__t.row({...})描述表结构与主键。类型定义在 types.ts 中通过__t.object('Player', {...})+__Infer推导。
3. React 端连接与订阅(main.tsx):用DbConnection.builder()链式配置.withUri('ws://localhost:3000')、.withDatabaseName('game')、.withLightMode(true),注册onConnect/onDisconnect/onConnectError回调,并用SpacetimeDBProvider包裹组件树。其中.withLightMode(true)对应 SDK 源码 db_connection_builder.ts 中"减少网络传输数据量"的连接模式。
4. 组件内响应式使用(App.tsx):useSpacetimeDB()从 Context 取连接状态;useTable(tables.player.where(r => r.name.eq('Hello')), { onInsert })返回实时行数组并注册插入回调;useReducer(reducers.createPlayer)拿到带完整参数类型的调用函数。三个 hooks 的实现位于 crates/bindings-typescript/src/react/,其中useTable基于useSyncExternalStore订阅onInsert/onDelete/onUpdate事件(见 useTable.ts),useReducer会在连接建立前把调用排队、建立后自动冲刷(见 useReducer.ts)。
而这一整套 client-server 协作流程,正是由 package.json 中的脚本串联的:
| npm 脚本 | 作用 |
|---|---|
dev | 启动 Vite 开发服务器(HMR 生效) |
build | tsc -b && vite build,先做全量类型检查再产物构建 |
generate/spacetime:generate | 由 Rust 模块重新生成src/module_bindings类型绑定 |
spacetime:start | 在本地启动 SpacetimeDB 独立服务器(默认监听端口3000) |
spacetime:publish:local | 把server模块以game数据库名发布到本地服务器 |
spacetime:publish | 发布到托管云(maincloud) |
lint/format | ESLint + Prettier 质量检查与自动格式化 |
一个典型的本地联调循环是:spacetime:start→spacetime:publish:local→dev,随后在浏览器中点击界面触发 reducer 写入,观察useTable驱动的实时行渲染与console.log输出。
五、实操排查要点
结合仓库源码与配置,几个容易踩坑的点:
- 类型感知规则与 project references:必须把顶层
tsconfig.json及其所有references(本工程为tsconfig.app.json、tsconfig.node.json)全部列入parserOptions.project,否则 ESLint 无法为"node 配置 + 应用配置"分域提供类型信息,会报project未覆盖文件的错误。 - Fast Refresh 前提:
react-refresh/only-export-components规则要求组件文件仅导出组件;若混入常量导出,热更新可能退化为整页刷新。 - 严格模式默认开启:tsconfig.app.json 设了
"strict": true,配合类型感知 ESLint 规则,对any的隐式渗透会非常敏感;仓库同时通过no-restricted-syntax禁止枚举与装饰器,写模块绑定相关代码时应沿用这一约束。 - 生成的绑定文件免检:
src/module_bindings/由 CLI 生成、文件头声明"EDITS TO THIS FILE WILL NOT BE SAVED",任何表结构或 reducer 变更都应回到 server/src/lib.rs 修改后重新执行generate脚本。
综上,这份"模板级 README"背后,是一条从 Rust 模块定义、CLI 类型生成、Vite/TS 编译链路到 ESLint 类型感知静态检查的完整工程流水线。掌握其脚手架配置与 lint 升级方法,即可在自有 SpacetimeDB 客户端项目中复现同等的开发体验与代码质量保障。
【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考