Strapi 源码仓库指南:从 CLAUDE.md 读懂 Strapi Monorepo 的架构、开发流程与测试体系
Strapi 开源仓库根目录下的 CLAUDE.md 只有一行内容 @AGENTS.md,它把真正的指南指向了 AGENTS.md。这份"Agent 指南"是理解 Strapi 代码库最精炼的入口:它概括了 Yarn workspaces + Nx 驱动的 monorepo 组织方式、Strapi 类的生命周期与依赖注入模型、Document Service 与内容类型的核心机制,以及完整的开发、构建、测试与质量门禁命令。读完本文,你能独立完成仓库初始化、跑起开发沙箱、按分层策略运行各类测试,并理解从 PR 提交到 CI 校验的完整质量链路。
仓库基本约定与目录结构
指南开篇给出三条硬性约定,这也是所有贡献者(包括 AI Agent)必须先知道的:
- 技术栈为 Yarn workspaces + Nx monorepo,运行环境要求 Node ≥22 ≤26、Yarn 4;
- 目标分支是
develop(不是main),所有 PR 都必须指向develop; - 仓库结构按职责划分为若干顶层目录:
packages/core/ # 框架本体: strapi, admin, database, content-manager, types, utils…
packages/plugins/ # 官方插件: users-permissions, i18n, graphql, documentation…
packages/providers/ # 邮件与上传 provider 实现
packages/utils/ # 共享工具: logger, eslint-config, tsconfig, vitest-config
packages/cli/ # CLI 工具: create-strapi-app, cloud-cli
examples/ # 仅用于开发的沙箱 — 不发布、不用于生产修复
docs/ # 贡献者文档
tests/ # 集成、E2E 与 CLI 测试基础设施
指南列出的核心包及其职责(非穷举,可用 yarn workspaces list 查看完整集合):
| 包 | 职责 |
|---|---|
@strapi/strapi |
主框架入口(Koa 服务器) |
@strapi/admin |
React 18 管理后台 |
@strapi/core |
核心业务逻辑 |
@strapi/database |
数据库抽象层(MySQL、PostgreSQL、MariaDB、SQLite) |
@strapi/content-manager |
内容管理 UI |
@strapi/types |
共享 TypeScript 类型定义 |
@strapi/permissions |
RBAC 权限引擎 |
@strapi/plugin-users-permissions |
JWT 认证 |
一个容易被忽略的细节是 skills 目录机制:.ai/skills/ 是仓库内唯一被提交(committed)的技能源,每个含 SKILL.md 的子目录即为一个技能;而 .agents/skills/、.claude/skills/、.cursor/skills/ 三个目录是 AI 工具链的"well-known locations",它们只是由 yarn ai:sync 维护的符号链接目标。对应实现在 scripts/ai-tooling/index.ts,在根 package.json 中可以看到三个脚本的定义:
yarn ai:sync # 幂等 —— 在三个工具目录中创建/清理 .ai 链接
yarn ai:unlink # 仅移除 .ai 来源的链接(保留 brain 链接)
yarn ai:status # 只读报告: linked / missing / conflict / stale
注意链接仅在本地生效(目标目录被 gitignore),只有 .ai/skills/ 的内容会被提交。指南还特别提示:在 Windows 上 CLI 会创建目录 junction(无需额外配置),而创建目录符号链接则需要开启开发者模式或使用提权 shell。
核心架构:Strapi 类、双入口与 Document Service
AGENTS 指南的 Architecture 一节是整个仓库的架构浓缩,值得逐条对照源码理解。
Strapi 类:DI 容器与生命周期
Strapi 类既是依赖注入容器也是整个系统的中枢。在 packages/core/core/src/Strapi.ts 中可以确认其定义为 class Strapi extends Container implements Core.Strapi,并依次实现了 start()、load()、register()、bootstrap()、destroy() 等异步方法,与指南描述的生命周期 Register → Bootstrap → Start → Destroy 对应——其中 start() 内部会调用 load(),load() 再串联执行 register 与 bootstrap。
指南强调的依赖注入模式:strapi 实例通过工厂模式注入(例如 createService(strapi)),严禁使用 global.strapi,应始终通过 DI 获取 strapi.documents、strapi.db、strapi.log 等能力。
Server / Admin 双入口
Koa.js HTTP 服务器(@strapi/strapi)与 React/Redux 管理端(@strapi/admin)是两套独立关注点。凡同时包含两者的包都导出双入口:strapi-server(Node.js 逻辑)与 strapi-admin(UI 组件)。插件体系同理——插件通过相同的 strapi-server / strapi-admin 双结构注册路由、控制器、服务、内容类型与中间件,官方插件统一放在 packages/plugins/ 下。
Document Service 与内容类型
- Document Service(
strapi.documents)是读写内容的首选高层 API,取代了已弃用的 Entity Service。指南明确:除正在@strapi/database内部工作外,永远不要写裸 DB 查询。 - 内容类型采用基于 JSON 的记法(并非 JSON Schema 规范),每个内容类型有一个
schema.json,数据库层会据此自动生成表结构——因此也绝不手写针对内容类型变更的 raw migration。 - 多态(morph*)关系的存储与查询机制(
getDeepPopulate、关系遍历如何与morphToOne及 join-based morph 交互)在 AGENTS.md 中指向了docs/docs/01-core/database/01-relations/下的贡献者文档,可作为进阶阅读。
此外还有两点设计约束:部分功能属于企业版(EE),在运行时按开关门控(对应下文测试章节的 IS_EE / RUN_EE 环境变量);@strapi/types 是共享类型的唯一事实来源,应扩展它而不是在本地重复定义。
仓库初始化与本地开发
首次搭建
# 克隆后执行一次
yarn install
yarn setup # clean + 构建全部包;若链接缺失会提示执行 ai:sync
yarn ai:sync # 将 .ai/skills 链接到 .agents/ .claude/ .cursor/
对照根 package.json,setup 脚本的实际定义为 yarn && yarn clean && yarn build --skip-nx-cache && tsx scripts/ai-tooling/post-setup.ts,即"安装 → 清理 → 全量构建 → 收尾检查"四步。指南还给出了 git worktree 场景的引导流程:新建 worktree 后检查 .claude/skills/git-conventions 是否能解析到仓库的 .ai/skills/git-conventions,若链接缺失或过期则运行 yarn setup:worktree(即 yarn install && yarn build && yarn ai:sync)。
开发沙箱与数据库
指南推荐的开发方式是在 examples/getstarted 沙箱中运行:
# 运行开发沙箱
cd examples/getstarted
yarn develop # 默认 SQLite
# 启动非内存数据库 (postgres/mysql)
docker-compose -f docker-compose.dev.yml up -d
DB=postgres yarn develop # PostgreSQL
DB=mysql yarn develop # MySQL
# 两个终端: 监听全部包 + 带 admin watch 的沙箱
yarn watch # 终端 1, 仓库根目录
cd examples/getstarted && yarn develop --watch-admin # 终端 2
根目录的 docker-compose.dev.yml 即用于本地拉起 PostgreSQL/MySQL 实例。yarn watch 对应 package.json 中的 nx watch --all -- 'nx run-many --targets build:code,build:types --projects $NX_PROJECT_NAME',即监听所有包变更并增量重建。
构建与测试体系
构建
yarn build # 全部包(代码 + 类型)
yarn build:code # 更快 —— 跳过 .d.ts 生成
yarn nx build @strapi/admin # 单个包
package.json 中的实现印证了这一分层:build 通过 nx run-many --targets build:code,build:types 同时构建代码与类型,build:code 只跑前者,故更快。
单元测试(最快,优先运行)
单测文件位于各包内部的 __tests__/ 子目录:
yarn test:unit
yarn test:unit:watch
yarn test:unit:update # 更新快照
前端测试(管理后台)
前端测试同样在各包的 __tests__/ 中,关键是 EE 门控开关:
yarn test:front # 以 IS_EE=true 运行(启用 EE 功能)
yarn test:front:ce # 以 IS_EE=false 运行(仅社区版)
yarn test:front:update # 更新快照(EE)
yarn test:front:update:ce # 更新快照(CE)
在 package.json 中可以看到 test:front 的定义为 cross-env IS_EE=true nx run-many --target=test:front ...,即通过环境变量在构建测试时就注入企业版特性,这正是架构一节所说"EE 功能在运行时门控"在测试层的体现。
类型检查
yarn test:ts # 全部包 + 前端 + 后端
API 集成测试
集成测试位于 tests/api/。指南特别提醒:测试应用是自动生成的,务必用 yarn test:generate-app 重新生成,不要复用旧的(过期应用会导致误导性失败)。
yarn test:api # SQLite
yarn test:api --db=postgres
yarn test:api --db=mysql
yarn test:api -u # 更新快照
CLI 测试与 E2E 测试
CLI 测试位于 tests/cli/:
yarn test:cli
yarn test:cli:debug # 带调试输出
yarn test:cli:update # 更新快照
E2E 测试基于 Playwright,位于 tests/e2e/tests/,按领域(admin、content-manager、i18n 等)组织:
yarn playwright install # 一次性安装浏览器
yarn test:e2e --setup --concurrency=1 # 顺序运行全部领域
yarn test:e2e --domains content-manager admin # 只运行指定领域
yarn test:e2e --concurrency=3 # 3 个领域并行
其入口脚本是 tests/scripts/run-e2e-tests.js,package.json 中还有 test:e2e:ce / test:e2e:ee 变体(通过 STRAPI_E2E_EDITION 切换版本),与指南提到的 RUN_EE=true(在 E2E 中启用企业特性)开关配套。
Pre-PR 检查清单
合入前必须至少通过以下组合:
yarn test:unit && yarn test:front && yarn test:ts && yarn lint && yarn prettier:check
E2E(yarn test:e2e)按 CONTRIBUTING.md 要求是必须的但较慢,CI 会在每个 PR 上强制执行。指南还给出了"何时加测试"的判断标准:bug 修复必须(先复现 bug 再写测试);功能开发只测试有意义的行为,不为了凑覆盖率;修改现有行为时同步更新受影响的测试。
质量门禁:提交规范、TypeScript 与格式化
Conventional Commits
提交必须遵循 Conventional Commits 规范,由 Husky 的 commit-msg 钩子与 CI 的 commitlint 双重强制:
<type>(<optional-scope>): <description>
合法 type 包括:feat、fix、chore、ci、docs、enhancement、test、revert、security、future、release。指南给出的示例:
feat(content-manager): add bulk delete action
fix(database): preserve relation order during publish
chore(admin): migrate data-fetching to react-query
交互式提交用 yarn commit;只要动过任何 package.json,就要跑 yarn version:check(其实现为 node scripts/check-package-versions.mjs && syncpack lint,校验各包版本一致性)。
TypeScript 与格式化规则
- 类型一律从
@strapi/types导入,优先扩展它而不是本地重复; - 存在或可合理定义类型时禁止
any,否则优先unknown;推送前跑yarn test:ts。 - 格式化命令:
yarn lint # 全仓 ESLint
yarn lint:fix # 自动修复
yarn format # Prettier (2 空格缩进, 单引号, 分号, 尾逗号, 箭头参数括号, 100 字符宽, LF)
yarn prettier:check # 仅检查
安全红线与 PR 规范
指南的 Security 一节是五条不可妥协的红线:
- 绝不提交密钥、凭据或 API key;
- 绝不禁用或弱化认证/授权检查;
- 使用参数化查询——绝不把用户输入插值进裸 SQL 或数据库查询;
- 在 controller/service 边界验证并清洗所有用户输入;
- 处理 EE 门控功能时不得绕过 license 检查。
PR 规范要求:从 develop 拉分支、目标 develop——永不碰 main;描述中关联所修复的 issue;所有测试通过;PR 描述必须遵循 .github/PULL_REQUEST_TEMPLATE.md 模板,不得自造章节。
给 Agent(与贡献者)的补充说明
AGENTS.md 最后的 "Notes for Agents" 给出了四条对自动化 Agent 尤为重要的仓库潜规则,人工贡献者同样适用:
examples/只是沙箱——仅用于复现与验证修复,除非被明确要求,不要向其中提交改动。例外:examples/complex是迁移测试夹具(schema、种子数据、validate-migration.js、DB 工具),CI 通过tests/migration/对migration_v5运行迁移校验,它未来可能迁入tests/migration/。- workspace 依赖使用锁定 semver——
packages/内部包之间互相引用时用的是固定版本号(如"5.42.0"),而非workspace:*;后者仅用于examples/应用和部分根 devDependencies。 - Entity Service 已弃用——内容操作一律使用 Document Service(
strapi.documents)。 - 生命周期约束——访问任何服务前
strapi.isLoaded必须为true;插件与数据库在load()阶段完成前不可用。
小结
CLAUDE.md 与 AGENTS.md 虽名为 Agent 指南,实则是 Strapi monorepo 的架构速写与工程手册:它用不到 300 行文字回答了"这个仓库怎么组织(packages 分层 + 双入口 + 生命周期)、怎么跑起来(setup/develop 命令)、怎么验证(单测→前端→类型→集成→CLI→E2E 的分层测试)、怎么合入(Conventional Commits + 质量门禁)"四个核心问题。结合 packages/core/core/src/Strapi.ts 中的生命周期实现与根 package.json 中的脚本定义对照阅读,可以从指南进一步下沉到具体源码,这也是理解 Strapi 框架源码的最高效路径。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00