Files
huajishe-tts/docs/dev-log/03-monorepo-scaffold.md
Claude 24822d0d6a docs(dev-log): add chronological development log
Per user request: split the development process into per-topic docs under
docs/dev-log/. Each entry follows the same structure:
  What was asked → Problems → How solved

Files:
- README.md            index
- 01-initial-scope-and-design.md
- 02-ui-primitives-api-design.md
- 03-monorepo-scaffold.md
- 04-ui-primitive-impl.md
- 05-drag-and-drop.md
- 06-three-games.md
- 07-bugfixes-round-1.md
- lessons-learned.md   all gotchas consolidated
- decisions.md         locked decisions with dates

Total: 1071 lines across 10 files.
2026-08-17 16:49:09 +08:00

2.8 KiB
Raw Permalink Blame History

03 · 项目骨架搭建

做什么

创建 monorepo 骨架:

tts-like/
├── packages/
│   ├── protocol/      共享类型
│   ├── engine/        boardgame.io 封装 + 游戏定义
│   ├── ui/            React 原语
│   └── server/        中转服务器
├── apps/
│   ├── web/           Vite + React SPA
│   └── desktop/       Tauri 壳
├── docs/
└── 配置文件

遇到什么问题

问题 1pnpm 不在 PATH

which pnpm 报 NOT FOUNDcorepack 路径下能找到 shim。

解决:每次 Bash 命令前先 export PATH

export PATH="/home/e2hang/.nvm/versions/node/v22.22.2/lib/node_modules/corepack/shims:$PATH"

问题 2boardgame.io 0.50.2 发布的类型导出不全

Game / Ctx 等类型只在主 entryboardgame.io,指向 dist/types/src/types.d.ts)里有。子包 /react /server /multiplayer 只导出运行时值。

解决

// ✅ 正确
import type { Game, Ctx } from 'boardgame.io';  // 类型从主 entry
import { Client } from 'boardgame.io/react';    // 运行时从子包

问题 3boardgame.io move 用 Immer 风格

最初写 War 游戏时用 return-styletypecheck 报错。

解决:直接 mutate G

// ✅ 正确
moves: {
  flip: ({ G, ctx }) => {
    G.p0Deck = G.p0Deck.slice(0, -1);
    // Immer 在内部处理
  }
}

问题 4pnpm workspace exports 模式

子包 import '@tts-like/engine/games/war' 解析不到。

解决engine/package.jsonexports 字段:

"exports": {
  ".": "./src/index.ts",
  "./games/*": "./src/games/*.ts"
}

注意wildcard 后缀必须带 .ts,否则解析出来没扩展名。

问题 5Vite 项目需要 vite-env.d.ts

否则 import.meta.envProperty 'env' does not exist on type 'ImportMeta'

解决:在 apps/web/src/vite-env.d.ts 写:

/// <reference types="vite/client" />

怎么解决

分三步走:

  1. 建目录 + 写包结构(手写 + Write
  2. pnpm install312 个依赖19 秒)
  3. 逐包 tsc --noEmit(按 protocol → engine → ui → server → web 顺序)

关键决策engine 用 import type 而不是 export type

// ❌ 不好用:在严格 TS 配置下 export type 不一定让名字进入本地 scope
export type { Game, Ctx } from 'boardgame.io';

// ✅ 工作中
import type { Game as BgGame } from 'boardgame.io';
export type Game<G = any> = BgGame<G>;

成果

  • 6 个包全部通过 tsc --noEmit
  • 初始 commit c5e5515 chore: scaffold monorepo skeleton
  • Memory 写入 6 条踩坑记录

关联