Files
gongxue-base/docs/superpowers/plans/2026-07-02-migrate-to-turborepo.md

736 lines
18 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.

---
change: migrate-to-turborepo
design-doc: docs/superpowers/specs/2026-07-02-migrate-to-turborepo-design.md
base-ref: 72db78daed6d840f2ddc7c0103f69325253b9098
archived-with: 2026-07-02-migrate-to-turborepo
---
# 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`,便于独立审查和回滚
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```
archived-with: 2026-07-02-migrate-to-turborepo
---
### 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"
```