91 lines
5.8 KiB
Markdown
91 lines
5.8 KiB
Markdown
## Context
|
||
|
||
当前项目是 Bun + TypeScript 的前后端一体化 demo:开发期由 Vite React 提供前端 HMR,Bun 提供 `/api/*` 和 `/health`;生产期先构建 Vite 静态资源,再通过 Bun file import 将资源和后端编译为单 executable。
|
||
|
||
现有能力已经通过 `typecheck`、单元测试和 executable smoke test 验证,但真实业务开发尚未开始。此变更聚焦平台基础设施硬化,目标是在业务 API、数据模型和前端业务页面扩展之前,先把开发联调、代码质量、格式一致性、HTTP 契约和生产验证闭环固化下来。
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
|
||
- 引入 ESLint 审查代码质量、React Hooks 规则和前后端边界。
|
||
- 引入 Prettier 统一代码风格,但不格式化 `openspec/`,避免影响 OpenSpec 文档和 tasks 一行一个任务的规则。
|
||
- 提供快速 `check` 和完整 `verify` 两层验证命令。
|
||
- 让开发期 Vite proxy 目标端口和 Bun server 监听端口保持一致。
|
||
- 补齐 HTTP method、JSON 404/405、静态资源缓存和低风险安全头的运行时契约。
|
||
- 增强生产 executable smoke test,确保验证的是当前源码构建出的生产产物。
|
||
- 同步 README,使文档描述与脚本、构建中间产物和验证流程一致。
|
||
|
||
**Non-Goals:**
|
||
|
||
- 不开发 gateway checker 真实业务能力。
|
||
- 不引入数据库、持久化、认证、React Router 或 UI 组件库。
|
||
- 不新增 CI 配置;本次仅提供本地 `check` 和 `verify` 命令,CI 接入留给后续仓库托管策略。
|
||
- 不引入 CSP;本次只加入低风险安全响应头,避免提前约束未来前端资源策略。
|
||
- 不做大规模目录重构或业务框架抽象。
|
||
|
||
## Decisions
|
||
|
||
### ESLint 和 Prettier 分工
|
||
|
||
ESLint 只承担质量审查和边界约束,不承担缩进、换行、引号等格式职责。Prettier 专门负责代码风格,避免 ESLint stylistic 规则和格式化器重复工作。
|
||
|
||
备选方案是只引入 ESLint 并启用 stylistic 规则,但后续维护成本更高,且容易和编辑器格式化行为冲突。另一个备选方案是只引入 Prettier,但它无法检查 React Hooks、未处理 Promise 或前端误导入后端实现等质量问题。
|
||
|
||
本次采用的最小依赖集合为 `eslint`、`@eslint/js`、`typescript-eslint`、`eslint-plugin-react-hooks`、`eslint-plugin-react-refresh` 和 `prettier`。暂不引入 `eslint-config-prettier`,除非实现阶段引入会与 Prettier 冲突的 ESLint preset 或 stylistic 规则。
|
||
|
||
### 验证命令分层
|
||
|
||
新增 `check` 和 `verify` 两层命令:
|
||
|
||
```text
|
||
check
|
||
├─ typecheck
|
||
├─ lint
|
||
├─ format:check
|
||
└─ test
|
||
|
||
verify
|
||
├─ check
|
||
├─ build
|
||
└─ test:smoke
|
||
```
|
||
|
||
`check` 面向日常开发,反馈快;`verify` 面向提交前或发布前验证,包含生产构建和 executable smoke test。备选方案是只提供 `verify`,但每次都构建 executable 会降低日常迭代速度。
|
||
|
||
### Prettier 忽略范围
|
||
|
||
Prettier SHALL 忽略 `openspec/`、`dist/`、`.build/`、`node_modules/`、`bun.lock` 和临时构建产物。`openspec/` 排除是显式决策,因为 OpenSpec tasks 要求一行一个任务,Markdown 自动折行可能破坏审阅体验和规则遵循。
|
||
|
||
### 开发期端口配置
|
||
|
||
文档化的全栈开发命令以 `PORT` 作为后端端口的唯一对外配置。Vite proxy 使用的 `BACKEND_PORT` 应由开发脚本从 `PORT` 派生,或者明确作为内部变量,避免用户只改 `BACKEND_PORT` 导致 proxy 与 server 分叉。直接运行 Bun server 或生产 executable 时仍可继续使用现有 CLI 参数覆盖 host 和 port。
|
||
|
||
### 运行配置校验
|
||
|
||
运行配置继续保持 CLI 参数优先于环境变量,缺省时使用 README 文档化默认值。端口配置必须拒绝非整数、小于 0 或大于 65535 的值,并通过单元测试覆盖默认值、优先级、非法输入和边界值,避免开发期和生产期配置行为分叉。
|
||
|
||
### HTTP method 和错误契约
|
||
|
||
现有 demo 端点按路径匹配,后续业务扩展前需要先固化 method 语义。`/health` 和 `/api/demo` 以 `GET` 为主,并支持 `HEAD` 返回相同状态和 headers 但无响应体;不支持的 method 返回 JSON 405,并带 `Allow` header。未知 `/api/*` 继续返回 JSON 404,不能落入前端 HTML fallback。
|
||
|
||
### 生产响应头策略
|
||
|
||
生产 HTML 使用 `Cache-Control: no-cache`,Vite hash 静态资源使用长缓存 `public, max-age=31536000, immutable`。所有生产 HTTP 响应增加低风险安全头,例如 `X-Content-Type-Options: nosniff` 和 `Referrer-Policy`。CSP 暂不纳入本次变更,避免后续业务页面接入外部资源时产生过早约束。
|
||
|
||
### 构建确定性
|
||
|
||
生成 `.build/static-assets.ts` 时,嵌入资源列表应按稳定顺序输出。这样可以减少重复构建时的无意义差异,也方便 smoke test 和后续审查定位问题。
|
||
|
||
### Smoke test 增强
|
||
|
||
`test:smoke` SHALL 针对当前构建出的 executable 验证生产行为,包括 `/health`、`/api/demo`、未知 API、根 HTML、SPA fallback、静态资源、未知静态资源、生产 runtime mode、缓存头和低风险安全头。`verify` 必须先执行 build 再 smoke,避免验证旧产物。
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- 新增 ESLint 和 Prettier 会增加开发依赖与初次配置成本 → 采用最小依赖集合,只启用与当前项目直接相关的规则。
|
||
- 现有代码可能被 Prettier 产生格式化改动 → 本次作为平台硬化变更集中处理,后续业务变更减少格式噪音。
|
||
- 405 和 HEAD 行为会让 HTTP handler 稍复杂 → 在业务 API 扩展前处理,避免未来每个端点重复补语义。
|
||
- 安全头不包含 CSP,安全强度有限 → 先采用低风险头,CSP 在前端资源来源稳定后单独设计。
|
||
- `verify` 包含构建和 smoke,运行更慢 → 保留快速 `check` 作为日常反馈通道。
|