首页
/ Strapi 开源贡献实战指南:从 Monorepo 环境搭建到测试体系与提交规范

Strapi 开源贡献实战指南:从 Monorepo 环境搭建到测试体系与提交规范

2026-09-03 15:33:25作者:郁楠烈Hubert

Strapi 的贡献流程围绕一个大型 Yarn Workspaces + Nx monorepo 展开,涵盖环境初始化、示例应用调试、API 集成测试、Playwright E2E 测试与 Conventional Commits 提交约束等多个环节。本文以仓库根目录的 CONTRIBUTING.md 为主体骨架,结合根目录 package.json.commitlintrc.tstests/scripts/run-api-tests.js 等源码逐节印证:读完你能完整跑通从 fork 克隆、yarn setup 初始化,到本地生成测试应用、执行全量测试并符合提交规范的贡献闭环。

协作模型与贡献前置约定

Strapi 是开源项目,由 Strapi 团队维护,所有工作在公开的代码托管仓库上进行。官方建议在投入大量时间写 PR 之前先与维护者沟通,确认方向与项目路线图一致;无论来自官方还是社区,每个 PR 都走同一套评审流程,核心团队会在评审后选择合并、要求修改或关闭。

几条必须了解的前置约定:

  • 特性请求(Feature Requests):社区鼓励提交新请求或为已有请求投票,渠道是官方的 feedback 站点(CONTRIBUTING.md 中指向 feedback.strapi.io)。
  • RFC 流程:影响面较大的改动需要先经过充分的设计讨论,RFC 要在单独的 rfcs 仓库创建。官方明确提示:由于提案需要深入讨论,不要期待立即被合并接受。
  • 行为准则:本项目及所有参与者受 CODE_OF_CONDUCT.md 约束,参与前应先通读全文了解可接受的行为边界。
  • CLA 贡献者许可协议:个人首次提交 PR 需签署 CLA(在 cla.strapi.io 完成一次即可,CLA bot 也会在合并前自动提醒);代表公司贡献则需要签署企业 CLA,通过邮件 contributions@strapi.io 联系。
  • 文档贡献的去处:面向最终用户、针对最新稳定版的文档修复应提交到独立的 documentation 仓库;而面向贡献者的开发文档就在本仓库的 docs/ 目录(对应 contributor.strapi.io 站点,基于 Docusaurus,入口见 docs/docusaurus.config.ts)。
  • 缺陷管理:Bug 通过 GitHub Issues 管理。提交 issue 前需自查:确实是技术问题、没有重复的开放 issue(找到相关已关闭 issue 要链接过去)、标题简洁、提供复现步骤,并已完成一系列排查(换应用、遵循 issue 模板、CTRL+C 重启服务、确认 node_modules 干净——未执行过 yarn link、未改动过 node_modules 内文件、不存在全局依赖环;最彻底的验证方式是删除 node_modules 后重新 yarn cache clean && yarn install && yarn setup)。

环境前置条件

CONTRIBUTING.md 声明的贡献者前置要求:

  • Node.js 版本 >= v22 and <= v26
  • Yarn v1.2.0+(仓库实际已升级到 Yarn 4);
  • 熟悉 Git。

仓库内的实际配置印证并补充了这些要求:

  • package.jsonengines 字段为 "node": ">=20.0.0 <=26.x.x",且声明 "packageManager": "yarn@4.12.0""isStrapiMonorepo": true
  • .yarnrc.yml 通过 yarnPath: .yarn/releases/yarn-4.12.0.cjs 锁定 Yarn 4.12.0,并配置 nodeLinker: node-modules(即仍采用 node_modules 目录布局而非 PnP),同时用 catalog 统一 vitest 版本;
  • .nvmrc 中记录的参考 Node 版本为 20

从源码结构看,文档中 >= v22 的要求与 engines>=20.0.0 略有出入,贡献时以 CI 实际运行的 Node 版本为准最稳妥;Yarn 版本则明确是 4.x(packageManager 字段会让 corepack 自动启用正确版本)。

开发工作流:从 Fork 到本地跑通

第 1–2 步:Fork 并克隆

在自己的账号中 fork 官方仓库后克隆到本地:

git clone git@github.com:YOUR_USERNAME/strapi.git

注意 AGENTS.md 中明确说明:PR 的目标分支是 develop(而不是 main),新分支也应从 develop 切出。

第 3 步:安装依赖并初始化

在仓库根目录执行:

cd strapi
yarn install
yarn setup
yarn ai:sync  # link AI skills into your local tool directories (.agents/, .claude/, .cursor/)

对照根 package.json 的脚本定义,yarn setup 实际展开为:

yarn && yarn clean && yarn build --skip-nx-cache && tsx scripts/ai-tooling/post-setup.ts

即:再次执行 install(保证 workspaces 链接完整)→ nx run-many --target=clean 清理所有包 → 全量构建代码与类型声明 → 执行 AI 工具链后置脚本。yarn build 本身是 nx run-many --targets build:code,build:types --nx-ignore-cycles,说明整个 monorepo 的构建由 Nx 编排(见 nx.json),lerna.json 仅保留少量元信息。

yarn ai:sync 对应 tsx scripts/ai-tooling/index.ts sync,用于把 .ai/skills/ 中的技能目录软链到 .agents/.claude/.cursor/ 等 AI 工具目录(目标目录本地生效、不进版本库),配套命令还有 yarn ai:unlinkyarn ai:status

如果你用 Git worktree 创建新检出(多分支并行开发时很常见),有专门的初始化命令,定义在 package.json 中:

git worktree add <path> <commit-ish>
cd <path>
yarn setup:worktree   # 实际执行: yarn install && yarn build && yarn ai:sync

第 4 步:启动示例应用

cd ./examples/getstarted
yarn develop

examples/getstarted 是一个可直接运行的完整 Strapi 应用,其 package.jsondevelop 脚本即 strapi develop(另有 develop:ce 通过 STRAPI_DISABLE_EE=true 强制社区版)。该应用的更多说明见 examples/getstarted/README.md

第 5 步:以开发模式运行管理面板

管理面板(React 应用)需要独立启动 watch 编译:

cd ./packages/core/admin
yarn watch

packages/core/admin/package.jsonwatch 脚本为 run -T rollup -c -w,即常驻监听模式的 Rollup 构建。然后让示例应用以 watch 模式运行管理面板:

cd ./examples/getstarted
yarn develop --watch-admin

CONTRIBUTING.md 强调两个命令必须同时运行,这样你在 packages/core/admin 中的代码改动才会实时反映到 examples/getstarted 的页面上。

常用开发命令一览

CONTRIBUTING.md 列出的命令表如下,括号内为对照根 package.json 得到的实际底层实现,方便理解每条命令的成本与作用:

命令 作用 底层实现(摘自 package.json scripts)
yarn watch 全部包启动 watch 构建 nx watch --all -- 'nx run-many --targets build:code,build:types --projects $NX_PROJECT_NAME'
yarn build 构建全部包(管理面板开发时使用) nx run-many --targets build:code,build:types --nx-ignore-cycles
yarn commit 交互式提交 CLI,按 git 规范引导写 message 调用 commit(@commitlint/prompt-cli)
yarn setup 安装依赖并完整初始化 yarn && yarn clean && yarn build --skip-nx-cache && tsx scripts/ai-tooling/post-setup.ts
yarn lint 全仓库 lint nx run-many --target=lint --nx-ignore-cycles && yarn lint:other(lint:other 为 prettier 检查)
yarn test:clean 删除各测试套件覆盖率报告 run-s -c test:api:clean test:e2e:clean test:cli:clean
yarn test:front 前端测试 cross-env IS_EE=true nx run-many --target=test:front -- --runInBand(注意默认带 IS_EE=true,另有 test:front:ce 显式关闭 EE)
yarn test:front:watch 前端交互 watch 测试 cross-env IS_EE=true run test:front --watch
yarn test:unit 后端单元测试 nx run-many --target=test:unit --nx-ignore-cycles
yarn test:api API 集成测试(自动重建测试应用) node tests/scripts/run-api-tests.js
yarn test:generate-app 生成测试应用 yarn build:ts && node tests/scripts/generate-test-app.js
yarn test:run-app / yarn test:start-app 运行/启动测试应用 tests/scripts/run-test-app.js 等承载

补充几个文档未列出但在 package.json 中存在、贡献时会高频用到的命令:yarn test:e2e / yarn test:e2e:ce / yarn test:e2e:ee(E2E 三档模式)、yarn test:unit:coverageyarn lint:fixyarn format(prettier 全量格式化)、yarn version:check(用 scripts/check-package-versions.mjs + syncpack 校验各包版本一致性)。

PR 合并前的测试门槛

CONTRIBUTING.md 要求 PR 提交前必须通过三套测试:

yarn test:unit
yarn test:front
yarn test:e2e --setup --concurrency=1

其中 E2E 首次运行可能需要先安装浏览器:yarn playwright install;运行企业版(EE)E2E 时需在 tests/e2e/.env 中设置 STRAPI_LICENSE(模板见 tests/e2e/.env.example,其内容就是 STRAPI_LICENSE=your_license_key),细节见下文与 docs/docs/guides/e2e/00-setup.md。最后还要保证 yarn lint 通过;如果 PR 修复了某个 issue,务必在 PR 描述中链接该 issue。

API 集成测试的运行机制

API 集成测试依赖一个真实可运行的 Strapi 应用。yarn test:api 实际执行 node tests/scripts/run-api-tests.js,从 tests/scripts/run-api-tests.js 可以看到完整链路:

  1. 强制 NODE_ENV=test,测试应用固定落在 test-apps/api
  2. 默认 --generate-app=true:先 cleanTestApp 用 rimraf 删除旧应用,再 generateTestApp 重新生成——这就是文档中“每次跑 API 集成测试都必须有全新测试应用,否则套件会失败”的原因;
  3. jest --config jest.config.api.js --runInBand --forceExit 执行测试,并注入 STRAPI_DISABLE_EE(未设置 STRAPI_LICENSE 时为 true,即默认按社区版跑)、JWT_SECRET 等环境变量,Node 参数追加 --experimental-vm-modules 以兼容 Jest 下的动态 import()

jest.config.api.js 进一步说明测试的匹配与加载规则:testMatch**/?(*.)+(spec|test).api.(js|ts),即只有 .api.test.ts / .api.spec.ts 这类文件属于 API 集成测试setupFilesAfterEnv 指向 tests/setup/jest-api.setup.js,TypeScript 通过 @swc/jest 转换。测试用例本身分布在 tests/api/coretests/api/plugins 下(如 tests/api/core/*.api.js)。

切换数据库:默认生成使用 SQLite 的应用,可切换到 Postgres / MySQL:

yarn test:api --db=sqlite
yarn test:api --db=postgres
yarn test:api --db=mysql

三个数据库的连接参数硬编码在 tests/scripts/run-api-tests.js 中,与本地开发用 docker-compose.dev.yml 提供的容器完全对齐:

数据库 连接配置(run-api-tests.js)
postgres 127.0.0.1:5432,库 strapi_test,用户 strapi/密码 strapi,schema myschema
mysql 127.0.0.1:3306,库 strapi_test,用户 strapi/密码 strapi
sqlite 文件 ./tmp/data.dbuseNullAsDefault: true

docker-compose.dev.yml 中 postgres 服务注入 POSTGRES_USER=strapiPOSTGRES_PASSWORD=strapi,mysql:8 服务注入 MYSQL_USER=strapiMYSQL_PASSWORD=strapi,端口同为 5432/3306——启动 docker compose -f docker-compose.dev.yml up -d 后即可满足测试连接要求(注意 compose 文件中的默认库名是 strapi,而测试连接指向 strapi_test,本地需确保该库存在)。

手动生成测试应用yarn test:generate-app --db=sqlite|postgres|mysql 执行的是 yarn build:ts && node tests/scripts/generate-test-app.js(注意会先构建类型)。从 tests/scripts/generate-test-app.js 看,它除接受 sqlite/postgres/mysql 三个具名库外,还支持传自定义连接参数(--dbclient/--dbhost/--dbport/--dbname/--dbusername/--dbpassword/--dbfile),并带 appPath(默认 test-apps/base)、template--run 等选项;生成逻辑复用 tests/helpers/test-app.js 中的 createStrapicreate-strapi-app 包),依赖会固定为 monorepo 内各 @strapi/* 包当前版本。

Jest 参数透传run-api-tests.js 使用 yargs 的 unknown-options-as-args 配置,因此任意 Jest 选项都能直接追加,例如更新快照 yarn test:api -u

企业版(EE)测试:测试套件默认运行社区版(CE)。要跑 EE 测试需提供有效 license:

STRAPI_LICENSE=<license> yarn test:api

tests/scripts/run-api-tests.js 可确认其原理:环境变量中 STRAPI_DISABLE_EE: !process.env.STRAPI_LICENSE——一旦设置了 license,EE 开关即被放开,应用会尝试以企业版启动。

E2E 测试要点

yarn test:e2e --setup --concurrency=1 是 PR 必跑项。围绕 E2E 的仓库事实(详见 docs/docs/guides/e2e/00-setup.mdtests/e2e/README.md):

  • 统一 runner 是 tests/scripts/run-e2e-tests.js,会为每个 domain(tests/e2e/tests/ 下的顶层目录,如 admin、content-manager)生成独立测试应用,并自动把依赖链接回 monorepo;
  • CE / EE 三档模式yarn test:e2e(自动检测:STRAPI_LICENSE 存在则 EE 否则 CE)、yarn test:e2e:ce(强制 CE 并从进程环境剥离 license)、yarn test:e2e:ee(缺少 STRAPI_LICENSE 直接报错退出);
  • license 必须写在 tests/e2e/.env 而不是仓库根目录的 .env(runner 用 dotenv 加载前者,不加载后者);离线 license 可再加 STRAPI_DISABLE_LICENSE_PING=true 对齐 CI 行为;
  • 并发控制 -c X 限制同时运行的测试应用数(domain 内 spec 文件始终串行);--domains=admin -- login.spec.ts 这类用法通过 -- 把文件过滤与 Playwright 参数(--project--grep--reporter--debug)转发给 Playwright;
  • 测试应用异常时用 yarn test:e2e:clean 清理 test-apps 目录后重新生成。

Git 提交规范与自动化检查

Commit message 约定

仓库采用如下格式,目的是生成可直接面向用户沟通的 changelog:

type: subject

body

type 基于 GitHub 标签体系,CONTRIBUTING.md 给出子集(fix 修 bug、chore 内部清理/工具/重构、docs 写文档、feat 新功能)。完整枚举在 .commitlintrc.ts 中定义(即文档所指的“完整列表”):

chore, ci, docs, enhancement, feat, fix, release, revert, security, test, future

该配置继承 @commitlint/config-conventional,对 type-enum 设为 Error 级别(不允许用列表外的 type),关闭了 body-max-line-length 限制,并对 Merge branch '...' into ... 这类合并信息做了忽略处理。

subject 应概括“这个提交是关于什么”,而不是描述代码在做什么,官方示例:

feat: introduce document service
fix: unable to publish documents due to missing permissions
chore: refactor data-fetching in EditView to use react-query
docs: document service API reference

特别警告:fix 类型必须说明修复了什么问题,而不是解决方案是什么。

本地自动检查:husky + commitlint + lint-staged

约定不是纯口头约束,仓库通过 git hooks 强制落地:

  • .husky/commit-msgyarn exec commitlint --edit "$1" —— 每次 git commit 后按 .commitlintrc.ts 校验 message,不合规直接拒绝;
  • .husky/pre-commityarn exec lint-staged --concurrent 8 —— 对暂存文件并发执行 lint-staged;
  • package.jsonpostinstall: husky 保证 yarn install 后 hooks 自动安装;
  • lint-staged 采用“最近配置优先”策略:根 lint-staged.config.mjs 只对暂存文件做 prettier 格式化兜底;各 workspace 内如有自己的 lint-staged.config.mjs,则走 lint-staged.shared.mjs 中定义的 ESLint + Prettier 组合,且共享配置会先用 ESLint#isPathIgnored 过滤被 ignore 的文件,避免 “file ignored” 警告在 --max-warnings=0 下变成硬失败阻塞提交。

配合 yarn commit(交互式 commitlint prompt),贡献者基本不会写出不合规的 message。

仓库组织:Yarn Workspaces + Nx monorepo

CONTRIBUTING.md 在 Miscellaneous 中说明:Strapi 选择 monorepo 设计,采用 Yarn Workspaces(与 React、Babel 的组织方式类似),以维护整个生态的一致性与最新状态;develop 分支力求随时保持测试通过,但演进速度可能快于发布节奏,稳定版以 npm 上的 release 为准。

package.json 的 workspaces 声明印证了这一结构:

"workspaces": [
  "packages/*",
  "packages/*/*",
  "examples/*",
  "examples/plugins/*",
  "examples/*/src/plugins/*",
  ".github/actions/*",
  "scripts/*"
]

各目录职责(AGENTS.md 与 CONTRIBUTING.md 交叉印证):

  • packages/core/:框架主体(strapi 主入口、admincontent-managerdatabasetypesutils 等);
  • packages/plugins/:官方插件(users-permissions、i18n、graphql、documentation 等);
  • packages/providers/:邮件与上传 provider 实现;
  • packages/utils/:共享工具(logger、eslint-config、tsconfig、vitest-config 等);
  • packages/cli/create-strapi-app、cloud CLI;
  • examples/:开发沙箱(getstarted、kitchensink 等),仅用于开发调试;
  • docs/:贡献者文档站点源码;
  • tests/:API 集成、E2E、CLI 测试基础设施。

提交 PR 前自查清单

把 CONTRIBUTING.md 的要求汇总为可执行清单:

  1. develop 切新分支,完成 yarn installyarn setup
  2. 修 bug 或新增可测试代码时,补充对应测试
  3. yarn test:unityarn test:frontyarn test:e2e --setup --concurrency=1 全部通过(E2E 先 yarn playwright install;EE 场景在 tests/e2e/.env 配置 STRAPI_LICENSE);
  4. yarn lint 无错误;
  5. 若修复了已有 issue,在 PR 中链接它;
  6. commit message 遵循 type: subject 约定(type 限 .commitlintrc.ts 枚举);
  7. 首次贡献者已完成个人 CLA 签署。

按上述清单走完,PR 即可进入核心团队的合并/修改/关闭三态评审流程——这正是 Strapi 贡献流程的完整闭环。

登录后查看全文
热门项目推荐
相关项目推荐