18 KiB
change, design-doc, base-ref, archived-with
| change | design-doc | base-ref | archived-with |
|---|---|---|---|
| migrate-to-turborepo | docs/superpowers/specs/2026-07-02-migrate-to-turborepo-design.md | 72db78daed6d840f2ddc7c0103f69325253b9098 | 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 统一格式化,oxlint(admin 前端)+ ESLint(server 后端)混合 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 使用) -
Step 1: 创建顶层目录结构
mkdir -p apps packages
- Step 2: 使用 git mv 将 backend 移动至 apps/server
git mv backend apps/server
预期结果:无错误,git status 显示 renamed: backend/... -> apps/server/...
- Step 3: 使用 git mv 将 frontend 移动至 apps/admin
git mv frontend apps/admin
预期结果:无错误,git status 显示 renamed: frontend/... -> apps/admin/...
- Step 4: 创建 packages/typescript-config/package.json
{
"name": "@gongxue/typescript-config",
"version": "0.0.0",
"private": true,
"license": "UNLICENSED",
"files": ["base.json", "nestjs.json", "react-vite.json"]
}
- Step 5: 创建 packages/typescript-config/base.json
{
"compilerOptions": {
"target": "ES2023",
"skipLibCheck": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true
}
}
- Step 6: 创建 packages/typescript-config/nestjs.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
}
}
- Step 7: 创建 packages/typescript-config/react-vite.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
}
}
- Step 8: 验证目录结构
ls -d apps/server apps/admin packages/typescript-config
预期输出:三个目录路径均存在。
- Step 9: 提交 Task 1
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 使用) -
Step 1: 更新根 package.json
将根 package.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。
- Step 2: 创建 turbo.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"]
}
}
}
- Step 3: 更新 .gitignore
在现有 .gitignore 末尾追加以下条目(现有内容保持不变):
# Turborepo
.turbo/
# Monorepo pattern matches
apps/server/node_modules/
apps/server/dist/
apps/admin/node_modules/
apps/admin/dist/
- Step 4: 删除旧的 node_modules 和 lock 文件,重新安装
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 被安装。
- Step 5: 验证 turbo 可用
npx turbo --version
预期输出:Turbo 版本号(如 2.x.x)。
- Step 6: 提交 Task 2
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 验证使用)
-
Step 1: 安装 oxfmt
npm install --save-dev oxfmt
- Step 2: 创建根目录 .oxfmtrc.json
{
"singleQuote": true,
"trailingComma": "all"
}
此配置与原来的 apps/server/.prettierrc 完全一致。
- Step 3: 为 apps/server 添加 format 脚本
修改 apps/server/package.json 的 scripts 字段,添加:
"format": "oxfmt"
保持其他脚本不变。
- Step 4: 为 apps/admin 添加 format 脚本
修改 apps/admin/package.json 的 scripts 字段,添加:
"format": "oxfmt"
- Step 5: 验证 oxfmt 格式化
npx oxfmt --check apps/server/src apps/admin/src
预期结果:No formatting issues found(或报告格式化差异,使用 npx oxfmt --write 自动修复)。
- Step 6: 安装 oxlint
npm install --save-dev oxlint
- Step 7: 创建根目录 oxlint.config.ts
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;
- Step 8: 将 apps/admin 的 lint 脚本迁移为 oxlint
修改 apps/admin/package.json 的 scripts 字段,将 lint 脚本替换为:
"lint": "oxlint --config ../../oxlint.config.ts"
并从 devDependencies 中移除以下 ESLint 相关依赖:
-
@eslint/js -
eslint -
eslint-plugin-react-hooks -
eslint-plugin-react-refresh -
globals -
typescript-eslint -
Step 9: 删除 apps/admin 的 ESLint 配置文件
rm apps/admin/eslint.config.js
- Step 10: 从 apps/server 移除 Prettier 集成
修改 apps/server/eslint.config.mjs,删除 Prettier 相关行。新内容:
// @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" }]规则 -
Step 11: 从 apps/server 移除 Prettier 依赖
修改 apps/server/package.json,从 devDependencies 中移除:
eslint-config-prettiereslint-plugin-prettierprettier
将 format 脚本更新为:
"format": "oxfmt"
- Step 12: 删除 apps/server 的 .prettierrc
rm apps/server/.prettierrc
格式化配置已统一由根目录 .oxfmtrc.json 管理。
- Step 13: 验证 lint 工具链
cd apps/server && npx eslint "{src,test}/**/*.ts" && cd ../..
cd apps/admin && npx oxlint --config ../../oxlint.config.ts && cd ../..
预期结果:两个 Lint 检查均通过(或报告现有代码问题,此时应手动修复或将规则降级为 warn)。
- Step 14: 提交 Task 3
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 workspaces(Task 2 产出) -
产出: server 和 admin 均通过 typecheck(Task 6 验证使用)
-
Step 1: 更新 apps/server/package.json — name 和 TypeScript 版本
修改 apps/server/package.json:
-
将
"name"从"backend"改为"@gongxue/server" -
将
"typescript"从"^5.7.3"改为"~6.0.2" -
在
devDependencies中添加:"@gongxue/typescript-config": "*" -
Step 2: 更新 apps/server/tsconfig.json
{
"extends": "@gongxue/typescript-config/nestjs.json",
"compilerOptions": {
"outDir": "./dist",
"baseUrl": "./"
}
}
- Step 3: 更新 apps/admin/package.json — name 和依赖
修改 apps/admin/package.json:
-
将
"name"从"frontend"改为"@gongxue/admin" -
在
devDependencies中添加:"@gongxue/typescript-config": "*" -
Step 4: 更新 apps/admin/tsconfig.app.json
{
"extends": "@gongxue/typescript-config/react-vite.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"types": ["vite/client"]
},
"include": ["src"]
}
- Step 5: 更新 apps/admin/tsconfig.node.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"]
}
- Step 6: 重新安装依赖
npm install
预期结果:npm workspaces 解析 @gongxue/typescript-config: "*" 工作区内部引用,安装成功。
- Step 7: 验证 TypeScript 类型检查
cd apps/server && npx tsc --noEmit && cd ../..
cd apps/admin && npx tsc -b --noEmit && cd ../..
预期结果:两个项目的类型检查均通过。
- Step 8: 提交 Task 4
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 验证使用)
-
Step 1: 更新 docker-compose.yml 的 build.context
将 backend 服务的 build: 从 ./backend 改为 ./apps/server:
backend:
build: ./apps/server
将 frontend 服务的 build: 从 ./frontend 改为 ./apps/admin:
frontend:
build: ./apps/admin
容器名 dorm_billing_backend 和 dorm_billing_frontend 保持不变。
- Step 2: 验证 Docker Build
docker compose build
预期结果:两个镜像均构建成功,无错误。
- Step 3: 提交 Task 5
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 的所有产出
-
产出: 完整验证报告,确认迁移成功
-
Step 1: 添加 typecheck 脚本
在 apps/server/package.json 的 scripts 中添加:
"typecheck": "tsc --noEmit"
在 apps/admin/package.json 的 scripts 中添加:
"typecheck": "tsc -b --noEmit"
- Step 2: 验证 npm install
npm install
验证 @gongxue/typescript-config 符号链接:
ls -la apps/server/node_modules/@gongxue/typescript-config
ls -la apps/admin/node_modules/@gongxue/typescript-config
- Step 3: 验证 npm run build
npm run build
验证构建产物:
ls apps/server/dist/main.js
ls apps/admin/dist/index.html
- Step 4: 验证 npm run lint
npm run lint
- Step 5: 验证 npm run format
npm run format
- Step 6: 验证 npm run test
npm run test --workspace=apps/server
- Step 7: 验证 npm run dev
npm run dev
预期:server :3003 + admin :3002 并行启动,API 代理正常。
- Step 8: 验证 npm run typecheck
npm run typecheck
- Step 9: 提交 Task 6
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"