11 KiB
11 KiB
工程优化审查报告(2026-04-01)
审查范围
- 扫描范围:
src/、scripts/、docs/、.github/、package.json、tsconfig*.json、vite.config.ts、vitest.config.ts - 审查方式:阅读当前工作区代码结构,抽查核心运行时、编辑器、服务层与开发脚本,并执行工程命令验证现状
- 当前快照说明:仓库存在大量未提交改动,本报告基于当前工作区状态,不假定这些改动都已经合入主分支
- 说明:按仓库要求,不把中文乱码本身当成本次审查重点;只讨论工程结构、门禁、可维护性、可测试性和扩展成本
已执行检查
npm run lint:eslint结果:失败。src/components/ItemCatalogEditor.tsx:167存在未使用的isSearchPending和startTransitionnpm run typecheck结果:通过npm run test结果:通过,默认套件实际执行 10 个测试文件、28 个测试npm run build结果:通过,但src/services/customWorldPresentation.ts:163-169出现 duplicate key 警告npm run check:content结果:通过
当前结论
这轮代码库已经明显比前几版更有工程骨架了,至少有这些积极变化:
src/main.tsx+src/routing/appRoutes.tsx已经承担了入口路由分发src/App.tsx已经比过去瘦很多,主流程开始交给 hook 和壳组件src/components/PresetEditor.tsx已经成为较薄的 lazy shell,而不是继续堆成巨型入口src/editor/shared/jsonClient.ts、src/persistence/、src/hooks/combat/、src/hooks/story/这些目录说明仓库已经开始做分层- CI、Vitest、ESLint、内容校验脚本都已经接上,不再是完全裸奔状态
但从工程角度看,当前最值得优先优化的,不是继续加功能,而是把“半完成的工程化”补齐。核心问题集中在 6 个方面。
P0:质量门禁和真实风险点仍然脱节
现状
仓库已经引入了 lint、typecheck、test、build 和 content checks,但关键热区并没有真正纳入统一门禁。
证据
.eslintrc.cjs:47-63的ignorePatterns直接跳过了多个高复杂度核心文件:src/components/AdventurePanel.tsx、src/components/NpcVisualEditor.tsx、src/components/preset-editor/PresetEditorPanels.tsx、src/hooks/useStoryGeneration.ts、src/services/customWorldPresentation.tstsconfig.typecheck-guardrails.json:6-15只对非常有限的一小组文件开启严格类型检查,远没有覆盖主运行时链路vitest.config.ts:8-10把customWorldPresentation映射到 stub,vitest.config.ts:20还排除了真实存在的src/services/ai.test.ts- 当前
src/下共有 161 个文件,测试文件共有 11 个,但默认套件只执行其中 10 个 npm run build已经能暴露src/services/customWorldPresentation.ts:163-169的 duplicate key 警告,但这块文件同时被 ESLint ignore、被 Vitest stub 掉,说明真实风险没有被完整看见
影响
- 工程信号不一致:
test绿、build过,不代表关键模块真的健康 - 复杂模块越是难测,越容易被长期豁免,最后演变成“最关键的地方最不受控”
- 后续重构会缺乏可靠的回归保护,review 只能更多依赖人工记忆
建议
- 先缩小
.eslintrc.cjs的 ignore 范围,优先把useStoryGeneration.ts、customWorldPresentation.ts、PresetEditorPanels.tsx拉回 lint - 把
src/services/ai.test.ts重新纳入默认测试套件,除非有明确且短期的阻塞原因 - 不要长期依赖
tsconfig.typecheck-guardrails.json的 allowlist,至少把src/hooks/、src/services/、src/components/game-shell/逐步纳入 strict 范围 - 对 build warning 建立明确策略:要么在 CI 中失败,要么把 warning 收敛到零
P0:当前工作区不在真正的绿色基线
现状
当前代码不是“纯优化空间”问题,而是已经存在直接可见的门禁破口。
证据
package.json:11-15把lint:eslint和typecheck定义成正式脚本,说明它们本来就属于项目基线- 实际执行
npm run lint:eslint时,src/components/ItemCatalogEditor.tsx:167报出未使用变量错误 src/components/ItemCatalogEditor.tsx:167引入了useTransition()返回值,但当前组件没有消费它npm run build虽然成功,但src/services/customWorldPresentation.ts:163-169仍然有重复 object key 警告
影响
- 团队会越来越难区分“可接受的技术债”和“已经破坏基线的问题”
- 继续叠加功能会把问题扩散到更多文件,后面补起来成本更高
建议
- 先恢复工作区绿色基线,再继续推进大功能
- 把“lint 零错误、build 零 warning”作为下一轮工程整理的硬目标
P1:运行时主链路仍然被少数超级模块吸住
现状
入口已经变薄,但主复杂度仍集中在少数大文件里,尤其是故事推进、战斗同步和界面编排三层。
证据
src/hooks/useStoryGeneration.ts当前约 2210 行src/hooks/useStoryGeneration.ts:694导出主 hook,src/hooks/useStoryGeneration.ts:1416接入useTreasureFlow,后面还继续承接 NPC 互动、库存、打字机、AI、历史推进和故事回写src/hooks/useCombatFlow.ts:134是主战斗 hook,src/hooks/useCombatFlow.ts:796-832仍然负责逃跑流程与 story sync 的耦合src/components/GameShell.tsx当前约 791 行,src/components/GameShell.tsx:260-269管理一组本地 UI 状态,src/components/GameShell.tsx:482继续处理场景切换时的选择编排- 构建产物里
dist/assets/App-*.js约 389 kB,dist/assets/index-*.js约 198 kB,说明主运行时 chunk 仍然偏重
影响
- 任何一个功能变化都容易跨 story、combat、transition、panel 几条链一起改
- hook 单测越来越难写,因为副作用、异步和 UI 编排仍然混在一起
- App 主 chunk 偏重,会继续拖累首屏和回归速度
建议
- 继续把
useStoryGeneration收敛成 orchestration 层,把 treasure、NPC、inventory、chat、typewriter、AI 回写拆成更纯的领域 action - 让
useCombatFlow更明确地区分“战斗结算”和“播放同步” - 把
GameShell进一步下沉为 scene transition、selection flow、overlay panel 三类 view-model
P1:编辑器共享层只迁移了一半,重复基础设施还在
现状
编辑器入口已经做了 shell 化,但真正的复杂度仍然堆在大型面板组件里,而且共享层没有吃干净。
证据
src/components/PresetEditor.tsx:41的入口已经很薄,说明方向是对的- 但
src/components/preset-editor/PresetEditorPanels.tsx仍然约 2163 行 src/components/preset-editor/PresetEditorPanels.tsx:55仍然自带cloneValuesrc/components/preset-editor/PresetEditorPanels.tsx:117仍然自带saveJsonObjectsrc/components/preset-editor/PresetEditorPanels.tsx:189仍然自带SectionCard- 与之对应,
src/editor/shared/jsonClient.ts:29-40已经提供了共享版fetchJson/saveJsonObject src/components/preset-editor/PresetEditorPanels.tsx:364、:1128、:1500、:1806仍然把四个大型 panel 放在同一个文件里
影响
- 编辑器的保存、错误处理、基础 UI 容器会继续多处复制,后续很难统一行为
- 迁移看起来开始了,但没有真正收尾,维护者仍然需要在“大文件 + 共享层”之间来回切换
建议
- 继续把
PresetEditorPanels.tsx拆成按 tab 或按领域分文件 - 统一复用
src/editor/shared/下的保存客户端、基础容器、表单片段 - 对编辑器做一次“小型迁移收尾”,目标是消灭重复的基础 helper
P1:本地开发 API 层与构建工具耦合过深
现状
本地 API 插件已经把很多临时逻辑吸收进项目内部,这是好事;但它现在承担的职责太多,且全部挂在 Vite 插件层。
证据
vite.config.ts:7-18直接把createLocalApiPlugins(__dirname, env)注入到 Vite configscripts/dev-server/localApiPlugins.ts当前约 394 行scripts/dev-server/localApiPlugins.ts:150定义 LLM proxy 插件scripts/dev-server/localApiPlugins.ts:216定义通用 JSON 文件编辑插件scripts/dev-server/localApiPlugins.ts:265直接把编辑器保存结果写回src/data/*.jsonscripts/dev-server/localApiPlugins.ts:429再统一把所有插件拼到一起
影响
- dev server、preview server、编辑器持久化和 LLM 代理被绑在一个文件里,测试与替换成本都偏高
- 随着编辑器继续扩张,这个文件会继续演化成“隐形后端”
- 生产与开发环境的边界容易模糊,问题排查也更依赖熟悉 Vite 插件机制的人
建议
- 至少先按职责把
localApiPlugins.ts拆成llm-proxy、json-editor-api、asset-catalog三块 - 下一阶段可以考虑把编辑器 API 抽成独立本地服务层,而不是继续塞在 Vite 插件里
- 给 JSON 写入接口补 schema 校验,而不只是“是 object 就写入”
P2:构建体积仍有继续优化空间
现状
路由 lazy load 和部分 modal lazy load 已经做了,但主游戏运行时包仍然偏大。
证据
dist/assets/App-*.js约 389 kBdist/assets/index-*.js约 198 kBdist/assets/index-*.css约 117 kBsrc/components/GameShell.tsx、src/hooks/useStoryGeneration.ts、src/services/prompt.ts仍然是较大的主链路文件
影响
- 新人本地启动、构建和回归阅读成本仍然偏高
- 主运行时模块越重,越不利于后续继续做场景扩展和编辑器共存
建议
- 优先沿着“运行时 orchestration 拆分”去减主 chunk,而不是单纯追求更多 lazy import
- 对
prompt、自定义世界、编辑器预览等非首屏关键代码继续做边界拆分 - 每轮重构后用真实构建产物复测,而不是只凭代码体感判断
建议的落地顺序
- 先恢复绿色基线:修掉
ItemCatalogEditorlint 错误,处理customWorldPresentation的 duplicate key warning - 再补齐门禁:缩小 ESLint ignore、把
ai.test.ts拉回默认测试、扩大 strict typecheck 覆盖 - 然后拆主链:优先处理
useStoryGeneration、useCombatFlow、GameShell - 再做编辑器迁移收尾:拆
PresetEditorPanels.tsx,统一共享层 - 最后处理 dev API 分层和 bundle 体积
一句话结论
这个仓库已经从“功能堆叠期”进入“工程收尾期”了。当前最值得做的不是再加一层玩法,而是把门禁补齐、把超级模块拆开、把半迁移状态收尾;只要这一步做稳,后续继续扩展剧情、编辑器和自定义世界的成本都会明显下降。