1
0

refactor: 迁移 Bun fullstack 架构

This commit is contained in:
2026-05-14 00:23:37 +08:00
parent bcfac52112
commit 6e485cc991
36 changed files with 403 additions and 1081 deletions

View File

@@ -1,61 +1,42 @@
## Purpose
定义将 Vite 前端资源与 Bun 后端打包为单个 standalone executable 的生产构建、运行配置和验证要求。
定义将 Bun HTML import 前端资源与 Bun 后端打包为单个 standalone executable 的生产构建、运行配置和验证要求。
## Requirements
### Requirement: 生产构建顺序
生产构建 MUST 在编译 Bun 后端 executable 之前先构建 Vite 前端
生产构建 MUST 通过 Bun.build 的 HTML import 识别机制一步完成前端资源打包和后端编译
#### Scenario: 运行生产构建
- **WHEN** 开发者运行生产构建命令
- **THEN** 系统 MUST 调用 Bun standalone executable 编译之前生成前端静态资源
- **THEN** 系统 MUST 调用 Bun.build自动识别 server 入口中的 HTML import 并完成前端 bundling 和后端编译
#### Scenario: 前端构建失败
- **WHEN** 前端生产构建失败
#### Scenario: 前端 bundling 失败
- **WHEN** Bun.build 在处理 HTML import 中的前端资源时失败
- **THEN** 系统 MUST 停止生产构建,且不能输出 stale executable
### Requirement: 构建生成确定性
生产构建 SHALL 以稳定顺序生成嵌入静态资源清单,减少重复构建产生无意义差异。
#### Scenario: 生成静态资源清单
- **WHEN** 生产构建扫描 Vite 输出目录并生成嵌入资源模块
- **THEN** 资源条目 SHALL 按稳定顺序输出
#### Scenario: 重复构建相同前端产物
- **WHEN** Vite 输出内容未变化且生产构建重复运行
- **THEN** 生成的嵌入资源模块 SHALL 保持语义一致且不依赖文件系统遍历顺序
### Requirement: 单 executable 输出
生产构建 SHALL 输出一个 standalone executable其中包含 Bun 后端、必要 server 依赖和构建后的前端资源。构建成功后 SHALL 自动清理中间产物目录(`.build/`,构建失败时 SHALL 保留中间产物以便排查。生成的入口代码 SHALL 通过 import config-loader 模块隐式触发 checker 注册,而非显式调用注册函数。生成的入口 SHALL 注册 SIGINT 和 SIGTERM 信号处理器,在收到信号时依次调用 engine.stop() 和 store.close() 后退出进程
生产构建 SHALL 输出一个 standalone executable其中包含 Bun 后端和通过 HTML import manifest 嵌入的前端资源。构建流程 SHALL 不再生成项目自定义中间产物目录,构建失败时 SHALL 保留 stale executable
#### Scenario: 在目标机器运行 executable
- **WHEN** 生成的 executable 在兼容目标平台上运行
- **THEN** 它 SHALL 启动全栈应用,且不要求目标机器安装 Node.js、Bun、Vite`node_modules`
- **THEN** 它 SHALL 启动全栈应用,且不要求目标机器安装 Node.js、Bun 或 `node_modules`
#### Scenario: 服务嵌入的前端
- **WHEN** executable 收到前端根路径请求
- **THEN** 它 SHALL 从 executable 内包含的资源服务前端,且不需要外部 `dist/` 目录
- **THEN** 它 SHALL 通过 Bun 内置的 HTML import manifest 机制服务前端资源,且不需要外部 `dist/` 目录
#### Scenario: 服务嵌入 API 和页面
- **WHEN** 生成的 executable 启动,且浏览器打开前端根路径
- **THEN** 页面 SHALL 展示同一个 executable 进程中 `/api/summary``/api/targets` 返回的数据
#### Scenario: 构建成功后清理中间产物
#### Scenario: 构建成功不生成自定义中间产物
- **WHEN** 生产构建成功完成并输出 executable
- **THEN** 系统 SHALL 自动删除 `.build/` 目录及其所有内容
- **THEN** 系统 SHALL 不生成 `.build/` 静态资源清单或 server entry 中间产物
#### Scenario: 构建失败时保留中间产物
- **WHEN** 生产构建在任意步骤失败前端构建、中间产物生成、Bun 编译)
- **THEN** `.build/` 目录 SHALL 保留在磁盘上以供排查
#### Scenario: checker 注册通过 import 链触发
- **WHEN** 生成的入口代码 import config-loader 模块
- **THEN** checkerRegistry 单例 SHALL 通过模块依赖链自动完成注册,入口代码 SHALL NOT 显式调用任何注册函数
#### Scenario: 生产入口优雅关闭
- **WHEN** executable 进程收到 SIGINT 或 SIGTERM 信号
- **THEN** 系统 SHALL 调用 engine.stop() 停止所有定时器,调用 store.close() 关闭数据库连接,然后以退出码 0 退出进程
#### Scenario: 构建失败时保留 stale executable
- **WHEN** 生产构建在任意步骤失败
- **THEN** 系统 SHALL 不输出上一次构建遗留的 stale executable
### Requirement: 外部运行时配置
executable MUST 将环境相关运行时配置保留在嵌入的前端和 server bundle 之外。
@@ -69,20 +50,12 @@ executable MUST 将环境相关运行时配置保留在嵌入的前端和 server
- **THEN** executable SHALL 使用文档化的默认值
### Requirement: 构建验证
项目 SHALL 提供验证,证明生产 executable 可以服务 API、健康检查、静态资源和 SPA fallback 路由,并且完整验证 MUST 针对当前源码重新构建后的 executable 运行
#### Scenario: 验证 executable 路由
- **WHEN** 构建验证针对生成的 executable 运行
- **THEN** 它 SHALL 检查 `/api/summary``/api/targets``/health`、前端根路径、静态资源、未知 API、未知静态资源和前端 fallback 请求
#### Scenario: 验证生产模式和响应头
- **WHEN** 构建验证针对生成的 executable 运行
- **THEN** 它 SHALL 检查 API 响应处于 production runtime mode并验证代表性 HTML、JSON 和静态资源响应的缓存或低风险安全 headers
项目 SHALL 提供 `verify` 命令执行质量检查和生产构建;原 smoke test 暂时移除executable 路由验证由后续变更重新设计
#### Scenario: 完整验证重新构建 executable
- **WHEN** 开发者运行完整验证命令
- **THEN** 系统 MUST 先基于当前源码执行生产构建,再对新生成的 executable 运行 smoke test
- **THEN** 系统 MUST 先执行质量检查,再基于当前源码执行生产构建
#### Scenario: 验证失败
- **WHEN** 任一代表性生产路由、响应头、生产模式或构建阶段检查失败
- **THEN** 验证 SHALL 使构建或测试命令失败
- **WHEN** 质量检查或构建阶段失败
- **THEN** 验证 SHALL 使命令失败