1
0
Files
DiAL/openspec/specs/fullstack-app-runtime/spec.md
lanyuanxiaoyao d6a77b2c6e feat: 迁移前端构建从 Bun fullstack 到 Vite
前端性能问题根因在于 Bun bundler 无法有效 code split、CSS
tree-shake 和产出优化的前端资源。经多轮 Bun 原生优化尝试
均无明显效果后,决定将前端构建迁回 Vite。

主要变更:

- 前端构建:从 Bun HTML import bundling 切换为 Vite build
  (Rolldown code splitting、vendor chunk、CSS 优化)
- 开发模式:从 Bun fullstack 单进程 HMR 切换为 Vite dev
  server + Bun API server 双进程(:5173 + :3000)
- 生产构建:三步流水线(Vite build → code generation →
  Bun compile),通过 `import with { type: "file" }` 嵌入前端资源
- 静态资源服务:从 Bun HTML import manifest 切换为自定义
  serveStaticAsset 函数,支持 SPA fallback 和正确的 Cache-Control
- Server 接口:BootstrapOptions 和 StartServerOptions 增加
  staticAssets? 可选参数
- 文档更新:DEVELOPMENT.md 和 README.md 反映新的开发模式,
  主 specs 同步 delta 变更

新增能力:
- static-asset-embedding: 构建时资源扫描与 code generation、
  运行时静态资源服务
- vite-frontend-bundling: Vite 构建配置、code splitting 策略、
  CSS 处理
2026-05-15 11:26:46 +08:00

116 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Purpose
定义基于 Vite + Bun 的全栈应用运行时,包括 HTTP server、API 命名空间、健康检查、生产静态资源服务和 SPA fallback 行为。
## Requirements
### Requirement: Bun HTTP 运行时
系统 SHALL 运行一个 Bun HTTP server使用 `routes` 对象声明式注册 HTML 页面路由和 API 端点,由单个进程提供后端 API、健康检查和前端服务。
#### Scenario: 启动运行时服务器
- **WHEN** server 进程成功启动
- **THEN** 它 SHALL 监听配置文件中指定的 host 和 port通过 routes 对象注册所有路由,并记录实际 server URL
#### Scenario: 通过 YAML 配置提供运行时参数
- **WHEN** 通过 YAML 配置文件提供 host、port、数据目录等参数
- **THEN** server SHALL 使用该值,且不需要重新构建
#### Scenario: CLI 只接受配置文件路径
- **WHEN** 用户通过命令行启动程序
- **THEN** 系统 SHALL 只接受一个命令行参数作为 YAML 配置文件路径
#### Scenario: 提供拨测相关 API
- **WHEN** server 启动完成
- **THEN** 系统 SHALL 通过 routes 对象提供 `/api/summary``/api/targets``/api/targets/:id/history``/api/targets/:id/trend` 端点
### Requirement: HTTP method 语义
系统 SHALL 只为运行时端点声明实际支持的 GET handler不支持的 API method SHALL 按未匹配 API 路由处理,不再保留自定义 405 和 Allow header 语义。
#### Scenario: GET 请求访问运行时端点
- **WHEN** 客户端使用 `GET` 请求 `/health``/api/*` 端点
- **THEN** Bun server SHALL 返回对应端点的成功响应
#### Scenario: 不支持的 API method 请求
- **WHEN** 客户端使用不支持的 method 请求已存在的 `/api/*` 端点
- **THEN** `/api/*` 通配符 SHALL 返回包含 `error``status` 字段的 JSON 404 响应
### Requirement: API 路由命名空间
系统 MUST 将 `/api/*` 保留给后端 API 路由。
#### Scenario: API 路由匹配
- **WHEN** 请求匹配已注册的 `/api/*` 路由
- **THEN** Bun server SHALL 返回 API handler 的响应
#### Scenario: API 路由未命中
- **WHEN** 请求访问未注册的 `/api/*` 路由
- **THEN** Bun server MUST 返回 JSON 404 响应,而不是前端 HTML 文档
### Requirement: API 错误响应一致性
系统 SHALL 为 API 命名空间内的未匹配路由和未匹配 method 返回机器可读 JSON 404 响应。
#### Scenario: 未知 API 路由
- **WHEN** 客户端请求未知的 `/api/*` 路由
- **THEN** Bun server MUST 返回包含 `error``status` 字段的 JSON 404 响应,而不是前端 HTML 文档
#### Scenario: API method 不匹配
- **WHEN** 客户端使用不支持的 method 请求已存在的 API 路由
- **THEN** Bun server MUST 返回包含 `error``status` 字段的 JSON 404 响应
### Requirement: 健康检查端点
系统 SHALL 在前端 SPA fallback 之外暴露健康检查端点。
#### Scenario: 健康检查成功
- **WHEN** 客户端请求 `/health`
- **THEN** Bun server SHALL 返回成功的、机器可读的健康检查响应
### Requirement: 生产静态资源服务
系统 SHALL 在生产模式下通过自定义 `serveStaticAsset` 函数服务嵌入的 Vite 前端产出。
#### Scenario: 请求构建后的资源
- **WHEN** 客户端请求 `/assets/*` 路径下的前端资源
- **THEN** 系统 SHALL 从 StaticAssets 的 files map 中查找并返回对应资源Content-Type 根据扩展名推断
#### Scenario: 请求前端根路径
- **WHEN** 客户端请求 `/`
- **THEN** 系统 SHALL 返回 StaticAssets 中的 indexHtmlContent-Type 为 `text/html; charset=utf-8`
### Requirement: 生产缓存策略
系统 SHALL 为生产静态资源提供基于文件名 content hash 的缓存策略。
#### Scenario: 请求前端入口 HTML
- **WHEN** 生产 server 返回前端入口 HTML 文档
- **THEN** 响应 SHALL 包含 `Cache-Control: no-cache` header
#### Scenario: 请求构建后的静态资源
- **WHEN** 生产 server 返回 `/assets/*` 路径下的静态资源
- **THEN** 响应 SHALL 包含 `Cache-Control: public, max-age=31536000, immutable` header
### Requirement: 低风险安全响应头
系统 SHALL 在生产运行时的 JSON API 响应中附加低风险安全响应头HTML 和静态资源响应由 Bun HTML import manifest 返回其内置 headers。
#### Scenario: 生产 JSON 响应包含安全头
- **WHEN** 生产 Bun server 返回 `/health``/api/*` JSON 响应
- **THEN** 响应 SHALL 包含 `X-Content-Type-Options: nosniff``Referrer-Policy` headers
#### Scenario: 生产静态资源响应
- **WHEN** 生产 server 返回前端 HTML 文档或构建后的静态资源
- **THEN** 响应 SHALL 不要求附加自定义安全 headers仅需 Content-Type 和 Cache-Control
### Requirement: SPA fallback 行为
系统 SHALL 通过 fetch fallback 为非 API、非静态资源路径返回前端入口 HTML 文档。
#### Scenario: 刷新前端路由
- **WHEN** 客户端请求不包含文件扩展名的非 API 路径(如 `/dashboard`
- **THEN** fetch fallback SHALL 返回前端入口 HTML 文档
#### Scenario: 保留 API 错误语义
- **WHEN** 客户端请求未知的 `/api/*` 路由
- **THEN** routes 中的 `/api/*` 通配符 MUST 返回 JSON 404 响应,而不是前端入口 HTML 文档
### Requirement: 优雅关机
系统 SHALL 在收到终止信号时正确清理资源。
#### Scenario: SIGINT/SIGTERM 处理
- **WHEN** 开发模式进程收到 SIGINT 或 SIGTERM 信号
- **THEN** 系统 SHALL 调用 engine.stop() 停止调度、调用 store.close() 关闭数据库连接后退出进程