Files
bun-app-template/DEVELOPMENT.md

33 KiB
Raw Blame History

my-app 开发文档

本文档面向 my-app 项目的开发者,介绍项目结构、前后端架构、构建流程、测试、代码规范等内容。

用户使用说明请参阅 README.md

目录


项目结构

src/
  server/
    bootstrap.ts    后端统一启动引导loadServerConfig → startServer
    config.ts       CLI 参数解析与配置文件加载(可选 YAML configPath支持 --help/-h
    dev.ts          开发模式启动入口mode: "development"
    main.ts         生产模式启动入口mode: "production",安全头启用)
    server.ts       HTTP server 启动工厂Bun.serve routes 声明式路由 + fetch fallback 静态资源服务)
    static.ts       生产模式静态资源服务SPA fallback、Content-Type 映射、immutable 缓存)
    helpers.ts      共享响应格式化工具(见下方函数清单)
    middleware.ts   API 参数校验中间件validateIdParam、validatePagination、validateTimeRange
     routes/         API 路由 handler按端点拆分
       meta.ts       GET /api/meta
     version.ts     运行时版本号读取(从 package.json 读取并验证)
   shared/
     api.ts          前后端共享 TypeScript 类型
     app.ts          应用全局常量name、title、subtitle、description
  web/              React 前端(通过 Vite 构建)
    index.html      HTML 入口
    app.tsx         根组件Admin 布局Header + Sidebar + Content
    main.tsx        入口BrowserRouter + QueryClient 挂载 + ErrorBoundary + ReactQueryDevtools + TDesign CSS 导入)
    routes.tsx      路由配置(定义所有页面路由)
    styles.css      全局样式与自定义 CSS 变量
    css.d.ts        CSS 模块类型声明
    pages/          页面组件
       dashboard/
         index.tsx   仪表盘页(欢迎语 + /api/meta 联调示例)
      users/
        index.tsx   用户管理页(占位)
      settings/
        index.tsx   系统设置页(占位)
      404/
        index.tsx   404 页面
    components/     UI 组件
      ErrorBoundary.tsx  React 错误边界,捕获渲染异常并展示降级 UI
      Sidebar/
        index.tsx   侧边栏菜单组件TDesign Menu + 折叠控制)
    hooks/          React hooks
      use-theme-preference.ts  主题偏好 hooksystem/light/darklocalStorage 记忆 + matchMedia 监听)
      use-sidebar-collapsed.ts 侧边栏折叠状态 hooklocalStorage 记忆)
    utils/          前端工具函数
      time.ts       时间处理formatCountdown、formatDurationUnit、formatRelativeTime、isOlderThan、subtractHours
    menu.tsx        菜单配置(路由与菜单项统一数据源)
    routes.tsx      路由配置(定义所有页面路由)
 scripts/
     dev.ts          双进程开发服务Bun API server + Vite dev server
     build.ts        Vite → codegen → Bun compile 三步构建流水线(含版本号注入)
     bump-version-logic.ts 纯版本管理逻辑parse、validate、bump、format
     bump-version.ts 版本升迁 CLI 脚本
     clean.ts        清理构建产物与临时文件
tests/              Bun test 测试(结构镜像 src 目录)
  setup.ts          全局测试配置jsdom、polyfill
  helpers.ts        测试辅助工具rmRetry
  server/           后端测试
    bootstrap.test.ts
    config.test.ts
    middleware.test.ts
    static.test.ts
  web/              前端测试
    App.test.tsx
    test-utils.tsx
openspec/           OpenSpec 变更、规格文档与 fast-drive workflow schema
config.example.yaml 配置文件示例

前后端边界

前端只通过 HTTP 调用后端API 路径为 /api/*。共享类型放在 src/shared,前端不得 import src/server 的运行时实现。


一、后端开发指引

1.1 架构概览

启动流程:
  dev.ts / main.ts → parseRuntimeArgs(cli args)
  → bootstrap({ configPath, mode })
  → loadServerConfig(configPath):可选 YAML 解析 → ServerConfig{ host, port }
  → startServer({ config, mode })Bun.serve routes 声明式路由 + fetch fallback
  → 注册 SIGINT/SIGTERM shutdown

HTTP 请求:
  Request → Bun.serve routes 声明式匹配 → routes/*.ts(handler)
  → helpers.ts(响应格式化) → Response
  前端: fetch fallback → serveStaticAsset (生产) / Vite proxy (开发)

1.2 库使用优先级

后端代码开发遵循严格的库选择顺序:

优先级 来源 典型用途
1 Bun 内置 API Bun.serveBun.fileBun.YAMLBun.spawnbun:sqlite(如需数据存储)
2 es-toolkit 类型判断(isPlainObject/isNil/isEmptyObject)、深度比较(isEqual)、并发控制(Semaphore
3 标准 Web API Object.fromEntriesHeadersfetchAbortControllerResponse
4 主流三方库 按需引入,优先社区活跃、类型完善的库
5 自行实现 仅在以上都无法满足时(如 parseDurationparseSize 等专项逻辑)

原则:新增依赖前先检查上述每一层级是否已有可用方案。禁止随意引入新依赖。

1.3 API 路由开发

路由文件位于 src/server/routes/,每个端点一个文件。路由通过 server.tsBun.serve({ routes }) 声明式注册,使用 per-method handler 对象:

// server.ts 中的路由注册
routes: {
  "/api/*": () => jsonResponse(createApiError("API route not found", 404), { mode, status: 404 }),
  "/api/meta": {
    GET: async () => handleMeta(mode, await resolveVersion()),
  },
}

Handler 函数签名:

// 带版本号参数的路由
export function handleMeta(mode: RuntimeMode, version: string): Response;

请求处理流程

  1. Bun.serveroutes 对象按路径 + HTTP 方法匹配请求
  2. 未匹配方法的请求落入 /api/* 通配符(返回 404
  3. 各 handler 内部通过 helpers.tsjsonResponsecreateApiError 等格式化输出
  4. 需要参数校验时使用 middleware.ts 提供的校验函数,返回 Response 实例表示校验失败(直接返回),返回数据对象表示通过

新增路由步骤

  1. src/server/routes/ 下创建 <name>.ts
  2. 实现 handler 函数并 export
  3. server.tsroutes 对象中注册路径和 method handler
  4. tests/server/ 中添加对应测试

1.4 共享工具

  • helpers.ts:跨路由共用的响应工具函数

    • createApiError(error, status) — 构造 API 错误体
    • createHeaders(mode, init) — 创建响应 Headers生产模式附加安全头X-Content-Type-OptionsReferrer-Policy
    • createMetaResponse(version) — 构造应用元信息响应 { ok: true, service, timestamp, version }
    • formatDuration(ms) — 毫秒转为可读时长字符串
    • jsonResponse(body, options) — JSON 响应构造
  • middleware.tsAPI 参数校验函数

    • validateIdParam(idStr, mode) — 校验 ID 参数格式(字母数字下划线连字符,字母开头),返回 { id }Response
    • validatePagination(pageParam, pageSizeParam, mode) — 校验分页参数(默认 page=1, pageSize=20pageSize 上限 200返回 { page, pageSize }Response
    • validateTimeRange(from, to, mode) — 校验时间范围参数ISO 格式、from < to返回 { from, to }Response
  • static.ts:生产模式静态资源服务

    • serveStaticAsset(pathname, assets) — 静态资源分发(文件扩展名路由 → immutable 缓存,无扩展名 → SPA fallback 返回 index.html
    • hasFileExtension(path) / contentTypeFor(path) / htmlResponse(html) — 辅助函数

1.5 类型定义规范

  • 共享类型src/shared/api.ts 为唯一源头,前后端共同引用
  • 应用常量src/shared/app.ts 为唯一源头,定义 APP 对象name、title、subtitle、description前后端及构建脚本共同引用
  • 版本号package.json.version 为唯一源头,通过 src/server/version.ts 运行时读取或构建时注入字面量
  • 前端不得 import src/server/ 下的任何文件
  • 严格联合类型优先于宽类型:如 RuntimeMode: "development" | "production" | "test" 而非 RuntimeMode: string
  • API 响应类型(ApiErrorResponseMetaResponse)定义在 shared 中

1.6 配置文件规范

配置加载流程:

CLI argv → parseRuntimeArgs → { configPath? }
  → loadServerConfig(configPath)
  → 可选 YAML 文件解析 → env 覆盖 → 默认值
  → ServerConfig{ host, port }

ServerConfig 包含以下字段:

字段 来源 默认值
host process.env["HOST"] → YAML server.host → 默认 127.0.0.1
port process.env["PORT"] → YAML server.port → 默认 3000

配置文件示例(config.example.yaml

server:
  host: "127.0.0.1"
  port: 3000

1.7 版本管理

项目使用 package.json.version 作为版本号唯一来源,严格 MAJOR.MINOR.PATCH 格式。

版本获取方式

  • 开发模式:src/server/version.ts 运行时从 package.json 读取版本号
  • 生产模式:scripts/build.ts 在构建时将版本号烘焙为 APP_VERSION 字面量注入 server-entry.ts

版本升迁命令

bun run version:patch          # 升迁 patch 版本0.1.0 → 0.1.1
bun run version:minor          # 升迁 minor 版本0.1.0 → 0.2.0
bun run version:major          # 升迁 major 版本0.1.0 → 1.0.0
bun run version:set 2.0.0      # 显式设置版本号

版本升迁仅更新 package.json.version,不自动创建 git commit、tag 或 changelog。

API 暴露GET /api/meta 返回 { ok, service, timestamp, version },前端通过此接口获取并展示版本号。

1.8 错误模式

  • API 错误{ error: "描述", status: <code> },状态码 400/404
  • 日志:非致命异常用 console.warn,启动失败用 console.error + process.exit(1)

二、前端开发指引

2.1 技术栈概览

层面 技术 用途
框架 React 19 UI 组件开发
构建 Vite开发+ Bun compile生产 开发服务 HMR 与生产构建
语言 TypeScript 类型安全
UI 库 TDesign React + tdesign-icons-react UI 组件与图标
数据层 TanStack Query (React Query) + React Query Devtools 服务端状态管理与自动刷新
路由 React Router v7 (Declarative mode) SPA 路由与页面导航

不引入的依赖状态管理库TanStack Query 即服务端状态层,组件内用 useState 足够)

2.2 组件树与数据流

main.tsx
└── StrictMode
    └── ErrorBoundaryReact 错误边界)
        └── QueryClientProviderTanStack Query 全局挂载)
            └── BrowserRouterReact Router 路由)
                ├── App根组件Admin 布局)
                │   ├── useThemePreference() ── Header 主题模式 RadioGroup系统/明亮/黑暗)
                │   ├── useSidebarCollapsed() ── 侧边栏折叠状态localStorage 记忆)
                │   ├── Layout
                │   │   ├── Header折叠按钮 + 品牌名 + 页标题 + 主题切换)
                │   │   └── Layout嵌套
                │   │       ├── Aside
                │   │       │   └── SidebarTDesign Menu菜单项点击导航
                │   │       └── Content
                │   │           └── AppRoutes路由配置
                │   │               ├── / → DashboardPage欢迎语 + /api/meta 联调)
                │   │               ├── /users → UsersPage占位
                │   │               ├── /settings → SettingsPage占位
                │   │               └── * → NotFoundPage404
                └── ReactQueryDevtools开发工具仅开发环境

Hook 架构

hooks/use-theme-preference.ts浏览器 UI 偏好)
├── ThemePreference: system / light / darkRadioGroup 受控值)
├── EffectiveTheme: light / dark写入 document.documentElement theme-mode
├── localStorage key: theme.preference同一浏览器记忆
└── matchMedia("(prefers-color-scheme: dark)")(系统模式下跟随系统明暗变化)

hooks/use-sidebar-collapsed.ts侧边栏折叠状态
├── collapsed: boolean折叠状态
├── localStorage key: sidebar.collapsed同一浏览器记忆
└── toggleCollapsed()(切换折叠状态)

菜单配置

utils/menu-config.ts路由与菜单统一数据源
├── MENU_ITEMS: MenuItemConfig[](菜单项配置数组)
│   ├── { value: "dashboard", label: "仪表盘", path: "/", icon: <DashboardIcon /> }
│   ├── { value: "users", label: "用户管理", path: "/users", icon: <UserIcon /> }
│   └── { value: "settings", label: "系统设置", path: "/settings", icon: <SettingIcon /> }
└── Sidebar 和 Routes 共同引用,保证菜单项与路由同步

2.3 TanStack Query 数据层

Query Key 规范

// 使用 structured array非字符串以便精确匹配和按 prefix 失效
const queryKeys = {
  meta: () => ["meta"] as const,
};
  • Key 使用 structured array(非字符串),以便精确匹配和按 prefix 失效
  • 使用 as const 保持字面量类型

查询配置规范

// 全局级查询(需要持续刷新)
useQuery({
  queryKey: queryKeys.meta(),
  queryFn: () => fetchJson<MetaResponse>("/api/meta"),
  refetchInterval: 30000, // 30s 轮询
  refetchIntervalInBackground: false, // 切后台不轮询
  staleTime: 5000, // 5s 内视为 fresh
});

fetch 封装

async function fetchJson<T>(url: string): Promise<T> {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return response.json() as Promise<T>;
}
  • 统一使用 fetch(不引入 axios与后端共享 Web API 生态
  • 错误抛异常,由 TanStack Query 的 error 状态承接

QueryClient 全局配置

new QueryClient({
  defaultOptions: {
    queries: {
      retry: 1, // 失败重试 1 次
      refetchOnWindowFocus: true, // 窗口聚焦时刷新
      staleTime: 5000, // 5s 内视为 fresh避免重复请求
    },
  },
});

2.4 组件开发规范

文件命名与导入

  • 每个 React 组件一个 .tsx 文件,文件名使用 PascalCaseErrorBoundary.tsx
  • 组件 props 定义为 interface XxxProps,紧邻组件函数声明
  • 类型从 ../shared/api 导入,使用 type 导入(import type { ... }
import type { MetaResponse } from "../shared/api";

interface AppProps {
  title?: string;
}

export function App({ title }: AppProps) {
  // ...
}

组件拆分原则

  • 展示组件components/):纯渲染逻辑,通过 props 接收数据,通过回调返回事件
  • 容器逻辑放在 hooks 中,组件只做数据消费
  • 工具函数(时间处理等)放在 utils/,保持纯函数无副作用

2.5 样式开发规范

前端基于 TDesign React 构建 UI样式开发遵循以下优先级从高到低

  1. 使用 TDesign 组件:布局、间距、排版优先使用 TDesign 组件(如 Space、Divider、Typography
  2. 使用 TDesign 组件 props:通过组件的 props 参数控制外观(如 themevariantsize
  3. 使用 TDesign CSS tokens:颜色、间距、字体等使用 --td-* CSS 变量(如 --td-success-color--td-comp-margin-xxl
  4. 在 styles.css 中定义 CSS 类:无法通过上述方式满足的样式需求,集中定义在 styles.css
  5. 自行开发组件:仅在 TDesign 无法满足需求时自行开发

红线

  • 严禁在组件中使用 style 属性内联调整样式
  • 严禁通过 CSS 覆盖 TDesign 组件内部类名(如 .t-tab-panel),如需定制使用组件的 className prop
  • 严禁使用 !important
  • 颜色统一使用 TDesign CSS tokens--td-success-color--td-error-color--td-warning-color 等),不使用硬编码色值

styles.css 组织

  • 自定义 CSS 变量定义在 :root
  • 布局类(.dashboard.dashboard-header-controls)定义全局页面结构
  • 组件修饰类为自定义视觉组件提供样式变体
  • 通用工具类(.full-width.text-disabled.tabular-nums)提供公用排版能力

2.6 前端测试规范

  • 测试目录:tests/web/,结构对应 src/web/
  • 重点测试 纯函数(时间处理、格式化等)和组件渲染
  • 使用 bun:test 框架
  • 组件测试使用 @testing-library/react 的语义化查询getByText、getByRole而非 CSS 选择器
  • 测试用户行为而非实现细节:模拟用户点击、输入等操作,而非直接调用组件方法
  • 只 mock 系统边界mock fetch 返回预设响应,使用真实的 QueryClientProvider 包裹组件

三、项目运行、集成与打包

3.1 开发期运行

bun run dev [config.yaml]

scripts/dev.ts 同时启动两个进程:

  • Bun API server(端口 3000后端 API 服务,--watch 监听后端文件变更自动重启
  • Vite dev server(端口 5173前端 SPA + HMR 热更新

开发时访问 http://127.0.0.1:5173Vite 自动将 /api 请求代理到后端。

也可以单独启动:

bun run dev:server [config.yaml]  # 仅启动后端 API server--watch 模式)
bun run dev:web                   # 仅启动 Vite dev server

3.2 前后端集成方式

双进程开发架构

开发模式下前后端分别由 Vite 和 Bun 服务:

  • Vite dev server 负责前端 SPA、HMR、模块热替换
  • Bun API server 负责后端 API 路由
  • Vite 通过 proxy 配置将 /api/* 转发到 Bun

生产模式架构

生产模式下前端通过 Vite 构建为静态资源,通过 import with { type: "file" } 嵌入 Bun 可执行文件:

// server.ts
const server = Bun.serve({
  fetch(req) {
    // staticAssets 存在时服务嵌入的前端资源
    if (staticAssets) {
      return serveStaticAsset(new URL(req.url).pathname, staticAssets);
    }
    return new Response("Frontend is served by Vite dev server on :5173", { status: 404 });
  },
  routes: {
    "/api/*": () => ...,
    "/api/meta": { GET: async () => handleMeta(mode, await resolveVersion()) },
  },
});

路由优先级

Bun routes 的匹配规则:具体路径 > 通配符。/api/meta 优先于 /api/*

未匹配 method 的请求(如 POST /api/meta会落入 /api/* 通配符返回 404若无该通配符会落入 fetch fallback。

非 API 路径由 fetch fallback 处理:有文件扩展名的返回对应静态资源或 404无扩展名的返回 SPA index.html。

3.3 构建打包

构建命令

bun run build

构建流程

scripts/build.ts 执行三步流水线:

1. Vite build        → dist/web/ (前端静态资源,含 code splitting)
2. Code generation   → .build/static-assets.ts + .build/server-entry.ts含版本号字面量注入
3. Bun compile       → dist/my-app (单可执行文件)
  • Vite 构建前端资源到 dist/web/,自动 code splittingvendor-react、vendor-tdesign、vendor-chart
  • Code generation 扫描 dist/web/ 生成 import with { type: "file" } 声明,将资源嵌入 binary
  • Bun compile 以 .build/server-entry.ts 为入口编译最终可执行文件
  • .build/ 临时目录在构建完成后自动清理

产物

产物 用途
dist/my-app 生产可执行文件(含前端资源,单文件部署)
dist/web/ Vite 构建的前端资源(构建中间产物)

构建参数

环境变量 说明
BUN_TARGET/BUILD_TARGET 交叉编译目标平台(如 bun-linux-x64

运行可执行文件

./dist/my-app [config.yaml]

启动后:

  • 访问 http://127.0.0.1:3000/ → 返回前端 SPA
  • 访问 http://127.0.0.1:3000/api/meta → 返回应用元信息 JSON含版本号

清理

bun run clean
# 清理 dist/ 构建产物和 .build/ 临时文件

3.4 开发工作流

日常开发循环

bun run dev [config.yaml]  # 启动双进程开发环境Vite :5173 + API :3000
# 访问 http://127.0.0.1:5173
# 修改前端代码 → Vite HMR 热更新 / 修改后端代码 → --watch 自动重启
bun run check              # 提交前运行完整质量检查

完整验证流程

bun run verify
# = bun run check + bun run build

verify 适合 CI 或正式提交前会完整验证类型检查、lint、格式、单元测试和生产构建。

3.5 脚本说明

脚本 文件 说明
bun run dev scripts/dev.ts 双进程开发服务Vite :5173 + API :3000
bun run dev:server src/server/dev.ts 仅启动后端 API server--watch 模式)
bun run dev:web Vite CLI 仅启动 Vite dev server
bun run build scripts/build.ts Vite → codegen → Bun compile 三步构建
bun run clean scripts/clean.ts 清理构建缓存与临时文件
bun run version:patch scripts/bump-version.ts 升迁 patch 版本x.y.Z
bun run version:minor scripts/bump-version.ts 升迁 minor 版本x.Y.0
bun run version:major scripts/bump-version.ts 升迁 major 版本X.0.0
bun run version:set scripts/bump-version.ts 显式设置版本号

3.6 环境变量

变量 用途 默认值
BUN_TARGET/BUILD_TARGET 交叉编译目标平台(仅在 bun run build 时有效) 当前平台
HOST 服务监听地址 127.0.0.1
PORT 服务监听端口 3000

3.7 项目配置文件

文件 用途
package.json 项目信息、脚本、依赖声明
tsconfig.json TypeScript 配置ESNext 模块、严格模式)
eslint.config.js ESLint 规则(含前端不得 import server 的检查)
commitlint.config.js commitlint 提交信息格式校验
.prettierrc.json Prettier 格式化规则(printWidth: 120
.prettierignore Prettier 排除路径
.lintstagedrc.json lint-staged 配置TS/TSX → ESLintMD/JSON/YAML → Prettier
config.example.yaml 配置文件示例
vite.config.ts Vite 构建配置React 插件、代码分割、API proxy
bunfig.toml Bun 配置(测试 preload、排除规则
opencode.json OpenCode 工具配置

3.8 依赖管理

  • 包管理器:仅使用 bun,禁止使用 npm、pnpm、yarn
  • 安装依赖bun install
  • 运行工具:使用 bunx,禁止使用 npxpnpx
  • 锁文件bun.lock

3.9 目录约定

目录 约定
src/server/ 后端代码,不能 import src/web/HTML import 除外)
src/web/ 前端代码,不能 import src/server/
src/shared/ 前后端共享类型,双向可引用
scripts/ 独立运行脚本,可 import 项目源码
tests/ 测试目录,结构镜像 src 目录
dist/ 构建产物gitignore
openspec/ OpenSpec 变更管理与规格文档

代码质量

项目使用多层代码质量保障体系ESLint 类型感知规则 + Perfectionist 导入排序 + Prettier 格式化(通过 eslint-plugin-prettier 集成至 ESLint+ TypeScript 严格模式 + Git hooks 自动化。

bun run lint          # ESLint 检查含类型感知规则、导入排序、导入验证、Prettier 格式)
bun run format        # Prettier 自动格式化
bun run typecheck     # TypeScript 类型检查
bun test              # 运行所有测试
bun run check         # 一键运行 typecheck + lint + test
bun run verify        # 完整验证check + build

check 是日常开发推荐的质量检查命令。

ESLint 规则

配置文件:eslint.config.js

配置来源 用途
@eslint/js recommended JavaScript 基础规则
typescript-eslint recommended-type-checked TypeScript 类型感知规则no-floating-promises 等)
typescript-eslint stylistic-type-checked TypeScript 风格规则(命名规范、语法选择等)
eslint-plugin-perfectionist recommended-natural 导入语句和命名导出自动排序
eslint-plugin-import 导入路径验证、循环依赖检测、重复导入合并
eslint-plugin-react-hooks recommended React Hooks 规则(依赖数组完整性检查等)
eslint-plugin-react-refresh React Fast Refresh 兼容性检查
eslint-plugin-prettier recommended + eslint-config-prettier 将 Prettier 格式集成为 ESLint 规则,禁用冲突规则

前端导入限制src/web/ 下的文件禁止 import src/server/ 下的运行时实现,通过 no-restricted-imports 规则强制执行。

Prettier 配置

配置文件:.prettierrc.json,通过 eslint-plugin-prettier 集成为 ESLint 规则(lint 命令同时检查格式),也可通过 format 命令独立运行。

显式声明所有格式化参数(printWidth: 120semi: truesingleQuote: falsetrailingComma: "all"endOfLine: "lf" 等),确保不同开发环境产出完全一致的格式化结果。

TypeScript 严格标志

标志 说明
strict true 全局严格模式
noUnusedLocals true 未使用局部变量视为错误
noUnusedParameters false 保留关闭(路由 handler 统一签名需要)
noPropertyAccessFromIndexSignature true 禁止通过点号访问索引签名属性,强制使用括号语法
noUncheckedIndexedAccess true 数组/Map 访问必须运行时真值检查
noImplicitOverride true 子类覆盖父类方法时必须显式使用 override 关键字
verbatimModuleSyntax true 强制 import type 纯类型导入,与 Bun 构建兼容

Git Hooks

通过 husky 在 commit 阶段自动执行检查:

Hook 行为
pre-commit lint-staged 对变更文件运行 eslint --fixTS/TSX含 Prettier 格式修复)或 prettier --writeMD/JSON/YAML
commit-msg commitlint 校验提交信息格式 类型: 简短描述

提交类型限定:featfixrefactordocsstyletestchore

bun install 时自动初始化 husky hooks无需手动配置。

质量检查完整清单

提交代码前建议运行:

bun run verify

CI 或正式提交前执行完整验证(类型检查 + lint + 格式 + 测试 + 构建),确保代码可编译并通过所有检查。


测试

项目采用两层测试体系:单元测试 + 组件测试。所有测试使用 bun:test 运行。

测试分层

层级 覆盖范围 位置 命令
单元测试 后端函数、纯函数、常量 tests/server/**/*.test.tstests/scripts/**/*.test.tstests/web/{utils,hooks}/**/*.test.ts bun test tests/serverbun test tests/web
组件测试 React 组件渲染和交互 tests/web/components/**/*.test.tsx bun test tests/web

运行命令

bun test                   # 运行所有单元测试和组件测试
bun test tests/server      # 只运行后端单元测试
bun test tests/web         # 只运行前端测试(单元 + 组件)
bun run check              # 日常开发(类型检查 + lint + 测试)
bun run verify             # 完整验证check + 构建)

组件测试环境

组件测试使用 jsdom 模拟浏览器环境,配置位于 tests/setup.ts(通过 bunfig.toml preload 加载):

  • jsdom 提供完整的 DOM 环境
  • TDesign 组件所需的 polyfillResizeObserver、IntersectionObserver、MutationObserver、matchMedia、attachEvent
  • 全局 afterEach 清理 document.body 内容,确保测试隔离

编写规范

  • 优先使用 @testing-library/react 的语义化查询getByText、getByRole而非 CSS 选择器
  • 测试用户行为而非实现细节:模拟用户点击、输入等操作,而非直接调用组件方法
  • 只 mock 系统边界mock fetch 返回预设响应,使用真实的 QueryClientProvider 包裹组件
  • 组件测试文件命名tests/web/ComponentName.test.tsx
  • 测试目录镜像源码目录tests/server/config.test.ts 对应 src/server/config.ts

已知限制

  • 当前仅为单页面应用,不涉及用户认证和权限控制
  • 不支持集群部署,单进程运行
  • 配置文件仅支持 YAML 格式,不支持热加载
  • 无国际化和多语言支持