chore: check off all plan tasks

This commit is contained in:
2026-07-02 15:53:08 +08:00
parent e22fedcd00
commit 34726cc46d

View File

@@ -0,0 +1,728 @@
---
change: migrate-to-turborepo
design-doc: docs/superpowers/specs/2026-07-02-migrate-to-turborepo-design.md
base-ref: 72db78daed6d840f2ddc7c0103f69325253b9098
---
# Turborepo 单体仓库迁移实施计划
> **面向自动化执行器:** 必需子技能:使用 superpowers:subagent-driven-development推荐或 superpowers:executing-plans 按任务逐步实施此计划。任务步骤使用 checkbox (`- [x]`) 语法进行追踪。
**目标:** 将 gongxue-base 从松散的多项目结构迁移为 npm workspaces + Turborepo 单体仓库,统一构建编排、工具链和 TypeScript 配置。
**架构:** 采用 npm workspaces`apps/*` + `packages/*`组织源码Turborepo 编排构建流水线oxfmt 统一格式化oxlintadmin 前端)+ ESLintserver 后端)混合 Lint 策略,`@gongxue/typescript-config` 共享包统一 TypeScript 配置。
**技术栈:** Turborepo, npm workspaces, oxfmt, oxlint, ESLint 9, TypeScript ~6.0.2, NestJS, React + Vite, Docker Compose
## 全局约束
- 使用 `git mv` 移动文件,保留完整 Git 历史
- npm workspaces 模式,不更换包管理器
- TypeScript 统一版本 `~6.0.2`
- Docker 容器名 `dorm_billing_backend` / `dorm_billing_frontend` 保持不变
- 所有 workspace 统一使用 `lint` / `format` / `build` / `dev` / `test` 脚本名
- 每个任务完成后立即 `git commit`,便于独立审查和回滚
---
### Task 1: 目录重组
**文件:**
- 创建: `apps/`(目录)
- 创建: `packages/`(目录)
- 移动: `backend/``apps/server/`
- 移动: `frontend/``apps/admin/`
- 创建: `packages/typescript-config/package.json`
- 创建: `packages/typescript-config/base.json`
- 创建: `packages/typescript-config/nestjs.json`
- 创建: `packages/typescript-config/react-vite.json`
**接口:**
- 产出: `apps/server/`(完整 NestJS 项目,路径已更新)
- 产出: `apps/admin/`(完整 Vite + React 项目,路径已更新)
- 产出: `packages/typescript-config/`(三个 TS 预设文件Task 4 使用)
- [x] Step 1: 创建顶层目录结构
```bash
mkdir -p apps packages
```
- [x] Step 2: 使用 git mv 将 backend 移动至 apps/server
```bash
git mv backend apps/server
```
预期结果:无错误,`git status` 显示 `renamed: backend/... -> apps/server/...`
- [x] Step 3: 使用 git mv 将 frontend 移动至 apps/admin
```bash
git mv frontend apps/admin
```
预期结果:无错误,`git status` 显示 `renamed: frontend/... -> apps/admin/...`
- [x] Step 4: 创建 packages/typescript-config/package.json
```json
{
"name": "@gongxue/typescript-config",
"version": "0.0.0",
"private": true,
"license": "UNLICENSED",
"files": ["base.json", "nestjs.json", "react-vite.json"]
}
```
- [x] Step 5: 创建 packages/typescript-config/base.json
```json
{
"compilerOptions": {
"target": "ES2023",
"skipLibCheck": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true
}
}
```
- [x] Step 6: 创建 packages/typescript-config/nestjs.json
```json
{
"extends": "./base.json",
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"resolvePackageJsonExports": true,
"esModuleInterop": true,
"isolatedModules": true,
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"incremental": true,
"noImplicitAny": false,
"strictBindCallApply": false,
"noFallthroughCasesInSwitch": false
}
}
```
- [x] Step 7: 创建 packages/typescript-config/react-vite.json
```json
{
"extends": "./base.json",
"compilerOptions": {
"lib": ["ES2023", "DOM"],
"module": "esnext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true
}
}
```
- [x] Step 8: 验证目录结构
```bash
ls -d apps/server apps/admin packages/typescript-config
```
预期输出:三个目录路径均存在。
- [x] Step 9: 提交 Task 1
```bash
git add apps/ packages/
git commit -m "feat(task1): restructure directories for turborepo monorepo
- Move backend/ to apps/server/ via git mv
- Move frontend/ to apps/admin/ via git mv
- Create packages/typescript-config/ with base, nestjs, and react-vite presets"
```
---
### Task 2: 根配置
**文件:**
- 修改: `package.json`(根目录)— 添加 workspaces 和 turbo 脚本
- 创建: `turbo.json`
- 修改: `.gitignore` — 适配新路径
- 删除: `node_modules/``package-lock.json`(根目录),重新安装
**接口:**
- 消费: `apps/server/``apps/admin/``packages/typescript-config/`Task 1 产出)
- 产出: 功能正常的 npm workspaces 环境,`turbo run` 可用Task 3-6 使用)
- [x] Step 1: 更新根 package.json
将根 `package.json` 内容替换为:
```json
{
"name": "gongxue-base",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
],
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"lint": "turbo run lint",
"test": "turbo run test",
"format": "turbo run format",
"typecheck": "turbo run typecheck"
},
"devDependencies": {
"turbo": "^2.0.0"
},
"dependencies": {
"@fission-ai/openspec": "^1.5.0"
}
}
```
说明:保留 `@fission-ai/openspec` 依赖(根目录 cli 工具使用),新增 `turbo` devDependency所有根脚本委托 `turbo run`
- [x] Step 2: 创建 turbo.json
```json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {},
"test": {},
"format": {
"cache": false
},
"typecheck": {
"dependsOn": ["^build"]
}
}
}
```
- [x] Step 3: 更新 .gitignore
在现有 `.gitignore` 末尾追加以下条目(现有内容保持不变):
```gitignore
# Turborepo
.turbo/
# Monorepo pattern matches
apps/server/node_modules/
apps/server/dist/
apps/admin/node_modules/
apps/admin/dist/
```
- [x] Step 4: 删除旧的 node_modules 和 lock 文件,重新安装
```bash
rm -rf node_modules package-lock.json apps/server/node_modules apps/server/package-lock.json apps/admin/node_modules apps/admin/package-lock.json
npm install
```
预期结果:安装成功,根目录 `node_modules/` 重新创建Turbo 被安装。
- [x] Step 5: 验证 turbo 可用
```bash
npx turbo --version
```
预期输出Turbo 版本号(如 `2.x.x`)。
- [x] Step 6: 提交 Task 2
```bash
git add package.json turbo.json .gitignore package-lock.json
git commit -m "feat(task2): add root turborepo and npm workspaces configuration
- Add workspaces field (apps/*, packages/*)
- Delegate all root scripts to turbo run
- Configure turbo.json with build/dev/lint/test/format/typecheck pipelines
- Update .gitignore for turborepo artifacts"
```
---
### Task 3: 工具链迁移oxlint + oxfmt
**文件:**
- 创建: `.oxfmtrc.json`(根目录)
- 创建: `oxlint.config.ts`(根目录)
- 修改: `apps/admin/package.json` — 替换 lint 脚本,移除 ESLint 依赖
- 删除: `apps/admin/eslint.config.js`
- 修改: `apps/server/package.json` — 移除 Prettier 相关依赖,保留 ESLint
- 修改: `apps/server/eslint.config.mjs` — 移除 Prettier 集成
- 删除: `apps/server/.prettierrc`
**接口:**
- 消费: 根 `package.json``turbo.json`Task 2 产出)
- 产出: oxfmt 统一格式化 + admin oxlint / server ESLint 混合 Lint 策略Task 6 验证使用)
- [x] Step 1: 安装 oxfmt
```bash
npm install --save-dev oxfmt
```
- [x] Step 2: 创建根目录 .oxfmtrc.json
```json
{
"singleQuote": true,
"trailingComma": "all"
}
```
此配置与原来的 `apps/server/.prettierrc` 完全一致。
- [x] Step 3: 为 apps/server 添加 format 脚本
修改 `apps/server/package.json``scripts` 字段,添加:
```json
"format": "oxfmt"
```
保持其他脚本不变。
- [x] Step 4: 为 apps/admin 添加 format 脚本
修改 `apps/admin/package.json``scripts` 字段,添加:
```json
"format": "oxfmt"
```
- [x] Step 5: 验证 oxfmt 格式化
```bash
npx oxfmt --check apps/server/src apps/admin/src
```
预期结果:`No formatting issues found`(或报告格式化差异,使用 `npx oxfmt --write` 自动修复)。
- [x] Step 6: 安装 oxlint
```bash
npm install --save-dev oxlint
```
- [x] Step 7: 创建根目录 oxlint.config.ts
```typescript
import type { OxlintConfig } from 'oxlint';
const config: OxlintConfig = {
plugins: ['typescript', 'react', 'import'],
rules: {
'typescript/no-explicit-any': 'off',
'typescript/no-non-null-assertion': 'warn',
},
settings: {
react: {
version: 'detect',
},
},
};
export default config;
```
- [x] Step 8: 将 apps/admin 的 lint 脚本迁移为 oxlint
修改 `apps/admin/package.json``scripts` 字段,将 `lint` 脚本替换为:
```json
"lint": "oxlint --config ../../oxlint.config.ts"
```
并从 `devDependencies` 中移除以下 ESLint 相关依赖:
- `@eslint/js`
- `eslint`
- `eslint-plugin-react-hooks`
- `eslint-plugin-react-refresh`
- `globals`
- `typescript-eslint`
- [x] Step 9: 删除 apps/admin 的 ESLint 配置文件
```bash
rm apps/admin/eslint.config.js
```
- [x] Step 10: 从 apps/server 移除 Prettier 集成
修改 `apps/server/eslint.config.mjs`,删除 Prettier 相关行。新内容:
```javascript
// @ts-check
import eslint from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{
ignores: ['eslint.config.mjs'],
},
eslint.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
globals: {
...globals.node,
...globals.jest,
},
sourceType: 'commonjs',
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-floating-promises': 'warn',
'@typescript-eslint/no-unsafe-argument': 'warn',
},
},
);
```
关键变更:
- 删除 `import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';`
- 删除 `eslintPluginPrettierRecommended` 配置项
- 删除 `"prettier/prettier": ["error", { endOfLine: "auto" }]` 规则
- [x] Step 11: 从 apps/server 移除 Prettier 依赖
修改 `apps/server/package.json`,从 `devDependencies` 中移除:
- `eslint-config-prettier`
- `eslint-plugin-prettier`
- `prettier`
`format` 脚本更新为:
```json
"format": "oxfmt"
```
- [x] Step 12: 删除 apps/server 的 .prettierrc
```bash
rm apps/server/.prettierrc
```
格式化配置已统一由根目录 `.oxfmtrc.json` 管理。
- [x] Step 13: 验证 lint 工具链
```bash
cd apps/server && npx eslint "{src,test}/**/*.ts" && cd ../..
cd apps/admin && npx oxlint --config ../../oxlint.config.ts && cd ../..
```
预期结果:两个 Lint 检查均通过(或报告现有代码问题,此时应手动修复或将规则降级为 warn
- [x] Step 14: 提交 Task 3
```bash
git add .oxfmtrc.json oxlint.config.ts \
apps/server/package.json apps/server/eslint.config.mjs \
apps/admin/package.json
git rm apps/admin/eslint.config.js apps/server/.prettierrc
git commit -m "feat(task3): migrate toolchain to oxfmt + oxlint
- Install oxfmt with .oxfmtrc.json (maps Prettier config)
- Install oxlint with oxlint.config.ts (TypeScript + React rules)
- Replace admin ESLint with oxlint
- Remove Prettier integration from server ESLint (keep ESLint for type checking)
- Delete server .prettierrc and admin eslint.config.js"
```
---
### Task 4: TypeScript 配置更新
**文件:**
- 修改: `apps/server/tsconfig.json` — 继承 `@gongxue/typescript-config/nestjs.json`
- 修改: `apps/admin/tsconfig.app.json` — 继承 `@gongxue/typescript-config/react-vite.json`
- 修改: `apps/admin/tsconfig.node.json` — 继承 `@gongxue/typescript-config/base.json`
- 修改: `apps/server/package.json` — 更新 name、TypeScript 版本、添加依赖
- 修改: `apps/admin/package.json` — 更新 name、添加依赖
**接口:**
- 消费: `packages/typescript-config/`Task 1 产出npm workspacesTask 2 产出)
- 产出: server 和 admin 均通过 typecheckTask 6 验证使用)
- [x] Step 1: 更新 apps/server/package.json — name 和 TypeScript 版本
修改 `apps/server/package.json`
-`"name"``"backend"` 改为 `"@gongxue/server"`
-`"typescript"``"^5.7.3"` 改为 `"~6.0.2"`
-`devDependencies` 中添加:
```json
"@gongxue/typescript-config": "*"
```
- [x] Step 2: 更新 apps/server/tsconfig.json
```json
{
"extends": "@gongxue/typescript-config/nestjs.json",
"compilerOptions": {
"outDir": "./dist",
"baseUrl": "./"
}
}
```
- [x] Step 3: 更新 apps/admin/package.json — name 和依赖
修改 `apps/admin/package.json`
- 将 `"name"` 从 `"frontend"` 改为 `"@gongxue/admin"`
- 在 `devDependencies` 中添加:
```json
"@gongxue/typescript-config": "*"
```
- [x] Step 4: 更新 apps/admin/tsconfig.app.json
```json
{
"extends": "@gongxue/typescript-config/react-vite.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"types": ["vite/client"]
},
"include": ["src"]
}
```
- [x] Step 5: 更新 apps/admin/tsconfig.node.json
```json
{
"extends": "@gongxue/typescript-config/base.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"lib": ["ES2023"],
"module": "esnext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"types": ["node"]
},
"include": ["vite.config.ts"]
}
```
- [x] Step 6: 重新安装依赖
```bash
npm install
```
预期结果npm workspaces 解析 `@gongxue/typescript-config: "*"` 工作区内部引用,安装成功。
- [x] Step 7: 验证 TypeScript 类型检查
```bash
cd apps/server && npx tsc --noEmit && cd ../..
cd apps/admin && npx tsc -b --noEmit && cd ../..
```
预期结果:两个项目的类型检查均通过。
- [x] Step 8: 提交 Task 4
```bash
git add apps/server/package.json apps/server/tsconfig.json \
apps/admin/package.json apps/admin/tsconfig.app.json apps/admin/tsconfig.node.json
git commit -m "feat(task4): update TypeScript configs to use shared presets
- Server tsconfig extends @gongxue/typescript-config/nestjs.json
- Admin tsconfig.app extends @gongxue/typescript-config/react-vite.json
- Admin tsconfig.node extends @gongxue/typescript-config/base.json
- Update package names: backend -> @gongxue/server, frontend -> @gongxue/admin
- Align server TypeScript to ~6.0.2"
```
---
### Task 5: Docker 适配
**文件:**
- 修改: `docker-compose.yml` — 更新 build.context 路径
**接口:**
- 消费: `apps/server/`、`apps/admin/`Task 1 产出)
- 产出: Docker compose build 和 up 成功运行Task 6 验证使用)
- [x] Step 1: 更新 docker-compose.yml 的 build.context
将 `backend` 服务的 `build:` 从 `./backend` 改为 `./apps/server`
```yaml
backend:
build: ./apps/server
```
将 `frontend` 服务的 `build:` 从 `./frontend` 改为 `./apps/admin`
```yaml
frontend:
build: ./apps/admin
```
容器名 `dorm_billing_backend` 和 `dorm_billing_frontend` 保持不变。
- [x] Step 2: 验证 Docker Build
```bash
docker compose build
```
预期结果:两个镜像均构建成功,无错误。
- [x] Step 3: 提交 Task 5
```bash
git add docker-compose.yml
git commit -m "feat(task5): update docker-compose build.context paths
- backend build.context: ./backend -> ./apps/server
- frontend build.context: ./frontend -> ./apps/admin
- Container names unchanged: dorm_billing_backend, dorm_billing_frontend"
```
---
### Task 6: 验证
**文件:**
- 修改: `apps/server/package.json` — 添加 typecheck 脚本(如需要)
- 修改: `apps/admin/package.json` — 添加 typecheck 脚本(如需要)
**接口:**
- 消费: Task 1-5 的所有产出
- 产出: 完整验证报告,确认迁移成功
- [x] Step 1: 添加 typecheck 脚本
在 `apps/server/package.json` 的 `scripts` 中添加:
```json
"typecheck": "tsc --noEmit"
```
在 `apps/admin/package.json` 的 `scripts` 中添加:
```json
"typecheck": "tsc -b --noEmit"
```
- [x] Step 2: 验证 npm install
```bash
npm install
```
验证 `@gongxue/typescript-config` 符号链接:
```bash
ls -la apps/server/node_modules/@gongxue/typescript-config
ls -la apps/admin/node_modules/@gongxue/typescript-config
```
- [x] Step 3: 验证 npm run build
```bash
npm run build
```
验证构建产物:
```bash
ls apps/server/dist/main.js
ls apps/admin/dist/index.html
```
- [x] Step 4: 验证 npm run lint
```bash
npm run lint
```
- [x] Step 5: 验证 npm run format
```bash
npm run format
```
- [x] Step 6: 验证 npm run test
```bash
npm run test --workspace=apps/server
```
- [x] Step 7: 验证 npm run dev
```bash
npm run dev
```
预期server :3003 + admin :3002 并行启动API 代理正常。
- [x] Step 8: 验证 npm run typecheck
```bash
npm run typecheck
```
- [x] Step 9: 提交 Task 6
```bash
git add -A
git commit -m "chore(task6): complete turborepo migration verification
Verification results:
- [PASS] npm install (all workspaces)
- [PASS] npm run build (server + admin)
- [PASS] npm run lint (server ESLint + admin oxlint)
- [PASS] npm run format (oxfmt)
- [PASS] npm run test (server Jest)
- [PASS] npm run dev (parallel server:3003 + admin:3002, API proxy OK)
- [PASS] npm run typecheck"
```