Files
Genarrative/docs/technical/【技术方案】npm-workspaces统一依赖边界-2026-08-21.md
T
kdletters c09a511aaa
Project CI / Repository checks (push) Successful in 2m24s
Project CI / Frontend tests (push) Successful in 2m54s
Project CI / Backend tests (push) Successful in 4m33s
Project CI / Native shell tests (push) Successful in 14m29s
Codex/fix pr188 191 ci (#194)
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/194
Co-authored-by: kdletters <kdletters@qq.com>
Co-committed-by: kdletters <kdletters@qq.com>
2026-08-25 15:41:55 +08:00

7.0 KiB
Raw Blame History

npm workspaces 统一依赖边界

更新时间:2026-08-21

目标

Genarrative 的 JavaScript 工程统一使用 npm workspaces。仓库只提交根 package-lock.json,开发、CI、Jenkins 和容器构建都从仓库根执行一次干净安装;各 App、内部包和工具仍由自己的 package.json 声明直接依赖和脚本。

本方案只迁移包管理与依赖边界,不切换 pnpm,不改变 Cargo workspace、SpacetimeDB schema、前后端 DTO 或业务运行时。

Workspace 范围

package.json 固定声明:

{
  "packageManager": "npm@10.9.7",
  "workspaces": [
    "apps/admin-web",
    "apps/ai-game-creator-shell",
    "apps/desktop-shell",
    "apps/mobile-shell",
    "apps/preview-deployer-web",
    "packages/image-canvas-core",
    "packages/image-canvas-react",
    "packages/shared",
    "tools/spine-json-export-validator"
  ]
}

当前纳入:

  • apps/admin-web
  • apps/ai-game-creator-shell
  • apps/desktop-shell
  • apps/mobile-shell
  • apps/preview-deployer-web
  • packages/image-canvas-core
  • packages/image-canvas-react
  • packages/shared
  • tools/spine-json-export-validator

.rag/runtime.worktrees/tmp/、构建目录和各级 node_modules 不属于 workspace。RAG 继续保持独立、gitignored 的本地运行时,不进入根依赖。

Manifest 与依赖所有权

  • 根 manifest 只声明根 H5、仓库级脚本和统一测试/格式化工具的直接依赖,不再为 Mobile、AGC 或工具重复声明其专属依赖。
  • 每个 App 在自己的 manifest 声明运行时直接依赖;测试只由根统一 runner 承担的工具可以留在根,App 自己提供测试脚本时必须声明其直接测试依赖。
  • @genarrative/image-canvas-react 必须显式依赖 @genarrative/image-canvas-core;主站和 AGC 必须显式声明它们直接消费的内部画布包。
  • npm 10.9.7 不支持依赖值 workspace:*。内部 workspace 依赖使用匹配本地包版本的普通 semver,例如 "@genarrative/image-canvas-core": "0.1.0"npm 在根安装时自动生成本地 link
  • npm 默认提升依赖,统一根 node_modules 中存在某包不代表根 H5 拥有该依赖。归属门禁必须检查对应 workspace manifest 和根 lock 中的 workspace package entry,不能按统一 lock 的全局 node_modules/* 条目判断归属。

packages/shared 本次纳入统一安装和 lock,但不顺手重写现有源码 import;后续若要把所有相对源码引用改为 @genarrative/shared,需先补完整 exports/build 合同并单独实施。

唯一 Lockfile

  • 唯一权威 npm lockfile 为根 package-lock.json
  • 删除 apps/ai-game-creator-shell/package-lock.jsontools/spine-json-export-validator/package-lock.json
  • 新增或修改任一 workspace 依赖后,只能从仓库根使用固定 npm 版本更新根 lock。
  • 仓库门禁必须校验 workspace 清单、固定 packageManager、根 lock 的 workspace package/link 条目,并拒绝受管 workspace 再提交嵌套 package-lock.jsonnpm-shrinkwrap.json
  • optional dependency、平台二进制和 bundled dependency 仍由根 lock 完整记录;Linux 生成 lock 后仍需 Windows/macOS 对应构建门禁,不能把单平台安装等同于跨平台通过。

安装与脚本

标准安装入口:

npm ci

开发者首次拉取或主动更新依赖时可使用根 npm install。Husky 的 prepare 只在根执行一次;各 workspace 不重复安装 hook。

现有 npm run agcnpm run mobile-shell:*npm run desktop-shell:*npm run preview-deployer:web:*npm run spine-export-validator:* 等对外入口保持名称稳定。内部可继续使用 npm --prefix,或使用 npm run <script> --workspace=<name>;无论哪种写法,都必须保证 Expo、EAS 和 Tauri 命令在目标 App cwd 中执行。

AGC 的 TypeScript、Vite/Vitest bundle 和 Windows Codex sidecar 不允许硬编码依赖一定位于子 App 的 node_modules。解析必须兼容 npm 将依赖提升到根安装树,并在错误文案中统一要求从仓库根安装。

原生壳边界

  • Mobile workspace 继续使用 Expo 默认 Metro 配置;当前不增加 node-linker 或自定义 watchFolders。首次迁移验收清理 Metro cache。
  • Desktop H5 仍不得声明 @tauri-apps/api 或任何 @tauri-apps/plugin-* guest 依赖。
  • AGC 可以在自己的 workspace manifest 声明 Tauri guest;统一根 lock 出现这些解析包是正常结果,不代表 Desktop 或根 H5 获得 guest 权限。
  • 根 H5 manifest 也不得直接声明 Tauri guest。配置门禁按根、Desktop、AGC 三个 manifest 的所有权分别判断。
  • Windows AGC release 必须从 workspace 或根提升位置找到 @openai/codex-win32-x64 并把固定 sidecar 资源打包;Windows 构建 smoke 是迁移完成条件,不由 Linux lock 检查替代。

CI、Jenkins 与容器

  • Gitea 四个 job 每个只执行一次带重试的根 npm ci,不再单独安装 AGC。
  • Jenkins Web Build 必须在每个独立 shell 中加载 scripts/jenkins-prepare-npm-env.sh;该入口在 Jenkins 运行用户的版本隔离目录准备并优先使用 npm 10.9.7,根 workspace 安装前再精确校验版本;RUN_NPM_CI 只控制一次根 npm ci
  • Gitea CI 镜像只维护一个 npm lock SHA 与一份 npm cache;预热上下文必须包含根 lock 和全部 workspace manifests,使根 npm ci 能解析 workspace。
  • CI 镜像仍分别维护 server-rs、Desktop Tauri、AGC Tauri 三份 Cargo lock cachenpm 单锁不改变 Rust lock 边界。
  • API 镜像的 Web builder 必须显式安装并校验 npm 10.9.7,再复制全部 workspace manifests、执行根 npm ci,之后才复制源码并构建主站与后台。
  • 根 lock 或任一 workspace manifest 变化都需要刷新 CI 镜像 npm cache。缓存未命中只能报告 partial 并受控补齐,不能跳过当前 lock 的干净安装。

验收

最低本地门禁:

npm ci
npm ls --workspaces --include-workspace-root --depth=0
npm run check:npm-workspaces
npm run typecheck
npm run test
npm run admin-web:typecheck
npm run preview-deployer:web:test
npm run mobile-shell:typecheck
npm run mobile-shell:test
npm run desktop-shell:typecheck
npm run ai-game-creator-shell:typecheck
npm run spine-export-validator:typecheck
npm run check:native-shells
npm run check:repository-ci
npm run check:production-ops
npm run check:encoding
git diff --check

干净安装验收必须在没有历史根或子 App node_modules 的隔离工作树执行。平台补充门禁:

  • Linux:根、后台、预览部署器、Spine 工具构建,Desktop/AGC Tauri release smoke。
  • Windows x64:根 npm ci 后执行 AGC Tauri release smoke,核对 Codex sidecar 完整性。
  • AndroidExpo config/export,并在可用 EAS 环境执行一次本地 Android build。
  • macOS/iOS:在可用 runner 执行 simulator build;缺少 runner 时必须标记未验证。

任何 workspace 仍需要第二次 npm ci --prefix、嵌套 lock、未声明直接依赖或依赖某个固定 node_modules 层级时,迁移都不能视为完成。