Redwood 贡献者实战指南:从本地开发环境搭建到提交 PR 的完整工作流
Redwood 贡献者实战指南:从本地开发环境搭建到提交 PR 的完整工作流
导读
本文基于 docs/docs/contributing-walkthrough.md 展开,完整拆解 Redwood 框架贡献者从"零"到"提交一个 PR"的端到端流程:如何区分 Redwood **Project(项目)**与 **Framework(框架)**两个代码库、如何用 yarn build:test-project 搭建功能测试项目、如何用 yarn rwfw project:sync 把本地框架代码链接到测试项目、如何在框架目录下运行构建/检查/测试命令,以及如何在本地与 Gitpod 中完成 PR 提交流程。文中结合当前仓库中真实的脚本源码(tasks/framework-tools/、tasks/test-project/、package.json)进行逐层印证,读完后你将掌握一套可以直接照着操作、且能读懂每一步背后原理的 Redwood 贡献工作流。
一、先弄清楚两个代码库:Redwood Project 与 Redwood Framework
在动手之前,必须厘清贡献者语境下的两个核心概念,后续所有命令都围绕它们展开。
1.1 Redwood Project(项目)
Redwood Project 指你用 Redwood 构建的应用程序代码库——即运行 yarn create redwood-app <path-to-directory> 后生成的那套目录(典型的 api/ + web/ 双端结构,包含 redwood.toml、graphql.config.js、jest.config.js 等配置文件,可参考仓库内 fixtures/test-project/ 或 fixtures/example-todo-main/ 等示例项目)。文档中强调:创建新项目的模板本身也托管在框架仓库中,被称为 CRWA Template 或 Project Template,对应仓库内的 packages/create-redwood-app/templates/ 目录。
1.2 Redwood Framework(框架)
Redwood Framework 是包含所有发布到 npm 的 @redwoodjs/<package-name> 包的 monorepo 代码库,也就是当前这个仓库本身。所有包通过 Yarn workspaces 组织,见 package.json 中的 workspaces 配置(packages/*、packages/adapters/*/*、packages/auth-providers/*/* 等)。在 Redwood Project 里,框架代码以 node_modules/@redwoodjs/* 的形式存在;在框架仓库里,它们则是 packages/ 目录下的源码。
简单记忆:Project 是"用 Redwood 做的应用",Framework 是"Redwood 本身"。你贡献的是 Framework,但需要用 Project 来验证 Framework 的改动。
1.3 贡献文档体系
官方贡献文档是分层组织的,本仓库中对应关系如下:
| 文档 | 定位 | 仓库位置 |
|---|---|---|
| Overview and Orientation | 贡献总览:社区文化、Issue 流程、PR 规范 | docs/docs/contributing-overview.md |
| Step-by-step Walkthrough(本文) | 从本地环境到提交 PR 的逐步实操 | docs/docs/contributing-walkthrough.md |
| Reference: Contributing to the Framework Packages | 框架包贡献参考文档 | CONTRIBUTING.md |
contributing-overview.md 中还指出:redwoodjs.com 上的文档面向"用 Redwood 开发应用"的用户,而框架仓库内的贡献文档面向"为 Redwood 做贡献"的开发者,两者职责不同但需要互相链接(这正是 contributing-walkthrough.md 存在的原因)。
二、开发前的准备:工具链与前置知识
2.1 推荐开发工具
核心团队推荐并实际使用的工具链:
- VS Code:官方推荐编辑器,框架与项目两个代码库打开时会弹出推荐扩展安装提示;
- GitHub Desktop:把 GitHub —— GitHub Desktop —— VS Code 的跨端工作流串联起来,从 clone、commit、push 到发起 PR 都能在图形界面完成(文档示例全程以它演示,但同一流程在命令行下完全等价);
- [Mac] iTerm2 + zsh(可加 Oh My Zsh):比系统自带 Terminal 体验更好,建议先保持简单配置,避免陷入主题化深坑;
- Windows] Git for Windows + Git Bash,或 WSL(2):JS 生态在 Windows 上有不少坑,官方优先级是"先能开发 Redwood 应用",再考虑贡献框架;两个推荐方案见 [docs/docs/how-to/windows-development-setup.md(Git for Windows 与 Git Bash)以及 WSL 社区配置指南;
- Gitpod:浏览器端 VS Code 云开发环境,会自动初始化一个带测试项目的框架工作区,对 Windows 开发者尤其友好,详见下文"Gitpod"章节。
2.2 前置知识:Git 与 GitHub
文档建议在开始贡献前掌握 Git/GitHub 工作流,推荐资源包括 GitHub Learning Lab 的《Introduction to GitHub》《First Day on GitHub》《First Week on GitHub》。动手前先完整跑一遍 Redwood 官方教程,它同时也是学习 Redwood 及其底层技术栈(React、GraphQL、Prisma 等)的最佳途径。
三、本地开发环境搭建(Local Development Setup)
这是整篇文档的核心实操部分,共分为五个步骤:Framework 准备 → 测试项目创建 → 框架与项目链接 → 框架包本地测试 → 提交 PR。
Step 1:准备 Redwood Framework
- Fork 框架仓库到个人 GitHub 账号(可在 GitHub.com 或 GitHub Desktop 中完成);
- 用 GitHub Desktop 以 VS Code workspace 打开框架代码;
- 在框架根目录执行"干净起步"命令:
yarn install # 等价于直接运行 yarn,安装 node_modules 依赖
yarn install --force # 简写 yarn -f,切换分支后强制重装,确保依赖与分支匹配
git clean -fxd # 仅在想要"从头再来"时使用:永久删除所有被 .gitignore 忽略的内容(node_modules、dist 等)
# 警告:它会一并删除 Redwood Project 中的 .env 文件,可用以下命令保留:
git clean -fxd -e .env
- 从
main分支创建新分支:先git pull同步远端最新代码(若是刚 clone 的 fork 则通常已是最新),再创建分支。文档推荐的分支命名规范为<作者姓名首字母>-用连字符连接的描述,例如dsp-add-eslint-config-redwood-toml。用 VS Code、GitHub Desktop 或 CLI 的git checkout均可完成。
在 package.json 中可以看到 yarn install、yarn build、yarn lint 等脚本的实际定义(例如 build 实际是 nx run-many -t build,build:clean 是 node ./tasks/clean.mjs),这些命令正是后续各步骤的基础。
Step 2:准备 Redwood 测试项目(Test Project)
文档特别强调使用测试项目时的三个关键"坑":
- 新建项目总是使用 npm 上最新稳定版的 Redwood 包,它与
main分支的框架代码不同步; - 若要用与
main分支最新代码对应的包,可在项目中执行yarn rw upgrade --tag canary升级到 canary 版本; - 用了 canary 不代表在用你的本地框架分支代码——必须运行
yarn rwfw project:sync才能链接本地框架;且每次切换分支或失步后,可能需要从git clean -fxd重新开始。
在创建项目的方式上,文档给出了四种选项:
选项 1(推荐):用构建脚本创建功能测试项目
# 在 Framework 根目录执行
yarn build:test-project <path/to/directory>
该命令会:用当前框架分支的 Template 代码库安装一个新项目 → 加入教程功能(Tutorial features)→ 初始化数据库(含种子数据)。文档评价它"90% 的情况下可用",也是 Gitpod 默认使用的方案。
从当前仓库源码看,package.json 中 build:test-project 对应 node ./tasks/test-project/test-project,即 tasks/test-project/test-project。该脚本(v2)会依次执行以下任务(见 tasks/test-project/test-project 的 globalTasks 列表):
- 默认从 fixtures/test-project/ 复制现成 fixture(
copyFromFixture,默认true);也可选择"从零构建"(调用yarn node ./packages/create-redwood-app/dist/create-redwood-app.js,见 tasks/test-project/test-project); - 在项目目录运行
yarn install; - (可选
--link时)执行yarn rwfw project:tarsync链接框架; - (可选
--javascript时)执行yarn rw ts-to-js转成 JS 项目; - 默认执行
yarn rw upgrade -t canary升级到最新 canary(与--link互斥,见 tasks/test-project/test-project); - 应用 web/api 侧 codemods、生成 dbAuth 密钥写入
.env、执行yarn rw prisma migrate reset --force初始化数据库、运行yarn rw lint --fix。
另外该脚本还强制要求:项目目录不能是框架目录的子目录(否则 Yarn 会报错,见 tasks/test-project/test-project),且只接受一个目录参数,例如 yarn build:test-project ../test-project。
选项 2:用本地框架 Template 代码安装全新项目
当你的改动涉及 CRWA Template 本身时,需要直接使用本地模板创建项目。文档给出的命令是:
yarn babel-node packages/create-redwood-app/src/create-redwood-app.js <path/to/project>
这等价于 yarn create redwood-app …,但运行的是本地框架包中的 create-redwood-app 和本地 Template 代码库。注意这正是 yarn build:test-project 开头所执行的动作。
选项 3:clone Redwood 教程应用仓库
作为 Redwood 教程第二部分起点,已更新到最新版本并包含 Blog 功能,也常用于本地开发。注意仍需升级到 canary 并留意下一版本的破坏性变更。
选项 4:安装全新项目
yarn create redwood-app <path/to/project>
仅需"最新版本模板 + 无任何功能"的全新安装时使用。同样需要注意升级 canary 与破坏性变更问题。
TypeScript 提示:上述所有创建项目的方式默认生成 JavaScript 项目;如需 TypeScript,可在运行 create-redwood-app 安装的命令后追加
--typescript选项(从 tasks/test-project/test-project 的源码看,构建脚本本身也是先创建 TS 项目、再用ts-to-js转换)。
Step 3:用 rwfw 把本地 Framework 链接到测试 Project
测试项目默认使用 npm 上最新版(或 canary)的 @redwoodjs/* 包,要让项目运行你正在开发的本地框架代码,需要在测试项目目录中执行 Redwood Framework(rwfw) 命令:
RWFW_PATH=<framework directory> yarn rwfw project:sync
示例:
cd redwood-project
RWFW_PATH=~/redwood yarn rwfw project:sync
其中 RWFW_PATH 是本地 Redwood Framework 的路径;一旦提供给 rwfw,它就会记住,之后无需再提供(除非你移动了框架目录)。
Windows 开发者注意:Windows 可能不接受在命令开头设置环境变量的写法,可改用
yarn cross-env RWFW_PATH=~/redwood yarn rwfw …,或先把环境变量写入 shell 再运行命令(当前仓库根 package.json 中lint:fw脚本正是用cross-env设置RWJS_CWD的先例)。
project:sync 启动后,控制台会依次打印以下步骤(对应源码 tasks/framework-tools/frameworkSyncToProject.mjs 的实际执行顺序):
- clean 并 build 框架:先执行
yarn build:clean(node ./tasks/clean.mjs),再执行yarn build(nx run-many -t build); - 把框架的依赖复制到项目:
addDependenciesToPackageJson会把框架各包的非@redwoodjs依赖合并进项目根package.json(见 tasks/framework-tools/lib/project.mjs 与依赖收集逻辑 tasks/framework-tools/lib/framework.mjs)——这是你在项目中看到的唯一显式改动:根package.json里多出一大堆依赖; - 在项目里运行
yarn install; - 把框架包复制到项目:
copyFrameworkFilesToProject会先删除node_modules/<package>再按 npm-packlist 的打包文件清单逐个复制(见 tasks/framework-tools/lib/project.mjs);随后fixProjectBinaries会为各包 bin 创建node_modules/.bin符号链接并写入项目package.json的 scripts(见 tasks/framework-tools/lib/project.mjs); - 等待变更:用 chokidar 监听
packages/目录,任一包文件变化后自动重新构建该包并再次复制到项目(见 tasks/framework-tools/frameworkSyncToProject.mjs)。源码中还有几个值得注意的细节:监听会忽略dist、测试文件、README.md、node_modules等路径(见 tasks/framework-tools/frameworkSyncToProject.mjs);若你修改了某个package.json的dependencies,控制台会提示必须重新运行yarn rwfw project:sync;同步结束后还会自动把项目被改动的package.json与web/vite.config.js|ts(通过 Babel AST 注入optimizeDeps.force: true,见 tasks/framework-tools/lib/viteConfig.mjs)恢复原状。
完成同步后:用 ctrl + c 结束链接进程;确认项目根 package.json 中新增的依赖已消失;若想重置测试项目,运行 yarn install --force。
Step 4:框架包本地测试(Build / Lint / Test / Check)
在框架目录内,使用以下命令验证你的代码(全部定义于 package.json):
yarn build # 构建所有包(nx run-many -t build)
yarn build:clean # 删除所有旧的构建产物目录
yarn lint # 语法与格式检查(并发执行框架与 crwrsca 的 lint)
yarn lint:fix # 自动修复 lint 错误/警告
yarn test # 运行各包单元测试(nx run-many -t test)
yarn e2e # 运行 Cypress E2E 集成测试(node ./tasks/run-e2e)
yarn check # 检查 Yarn resolutions 与 package.json 格式(yarn constraints + yarn dedupe --check)
这些检查全部包含在 GitHub PR 的 CI 自动化中,但文档建议本地先跑一遍以理解各自行为。E2E 测试耗时较长,不是每次都跑,但掌握它很有价值——当 GitHub 上的 CI 失败而需要本地诊断时非常有用。
Windows 开发者注意:Cypress E2E 在 Windows 上无法工作。两个替代方案:使用 Gitpod(见下文);或在创建 PR 时请求维护者协助。
从仓库源码看,各包都配有独立的测试配置,例如 packages/api/vitest.config.mts、packages/router/vitest.config.mts、packages/cli/vitest.config.mts 等,yarn test 通过 Nx 并行调度这些测试任务。
Step 5:提交 PR 🚀
文档用 GitHub Desktop 演示了 PR 提交流程,但强调同样的流程完全适用于命令行或其他客户端:
- 提交文件(Commit):在本地框架仓库选中当前工作分支,勾选左侧列出的修改/新增/删除文件,填写简短的 commit message(第一框),如需更长描述可写在第二框,点击 "Commit to <your-branch-name>" 完成提交;
- 推送文件(Push):提交后出现本地 commit 计数与 "Push origin" 按钮,点击即可把分支推送到你的 fork 远端;也可以继续提交更多 commit 再一次性推送;
- 创建 Pull Request:推送完成后出现 "Create Pull Request" 入口,浏览器会打开 GitHub 的 "Open a pull request" 表单,填写信息、勾选 "Allow edits by maintainers" 后提交。
不使用 GitHub Desktop 时:push 完成后访问 github.com 进入你的 fork,页面顶部会有发起 PR 的按钮。
两个关键建议:
- 务必勾选允许维护者更新分支("Open a pull request" 表单中描述框下方)。因为合并前分支总是需要从
main更新,勾选此选项能显著加速 PR 的推进; - 不要等代码"完美"了才开 PR:大多数沟通和决策都发生在 PR 内。只要代码有一点点改动,就建议以 Draft PR(草稿 PR) 形式开启,用于启动讨论、提问、确认方向。PR 被关闭(常因被更新的 PR 取代)是流程的一部分。先尝试、再求助,比把大量时间花在可能方向错误的代码上要好得多。
关于"什么是一个好的 PR",可参考 docs/docs/contributing-overview.md 中的 What makes for a good Pull Request? 章节:好的 PR 应该"留下面包屑"(链接相关 Issue 与论坛讨论)、写有帮助的描述(代码做什么、解决什么问题、如何用)、尽早开 Draft、在 PR 中提问讨论、@ 维护者请求评审(几天没回复可以再提醒一次),并说明合并后的下一步(如有)。
四、Gitpod:浏览器端开发环境
Redwood 与 Gitpod 深度集成,任何分支或 PR 都能直接初始化一个虚拟工作区。工作区初始化时自动完成:
- 检出你的分支或 PR 代码;
- 运行 Yarn 安装;
- 通过
yarn build:test-project创建功能测试项目; - 将框架代码与测试项目同步(即
project:sync所做的事); - 启动测试项目的 dev server。
浏览器提示:Brave 与 Safari 在 Gitpod 上存在已知 bug,建议使用 Chrome(Edge 和 Firefox 也值得一试)。
两种启动 Gitpod 工作区的方式:
- 方式一:从 PR 启动。每个 PR 都会用 PR 分支触发一次 Gitpod 预构建,在 PR 底部的 checks 列表中找到 Gitpod,点击 "Details" 链接即可进入;
- 方式二:使用 URL 模式。初始化工作区的 URL 模板为:
https://gitpod.io/#<URL for branch or project>
例如,用 Redwood 框架 main 分支启动:
https://gitpod.io/#https://github.com/redwoodjs/redwood
用 PR #3434 启动:
https://gitpod.io/#https://github.com/redwoodjs/redwood/pull/3434
需要再次强调的是:不要因为用 Gitpod 就跳过本地环境搭建章节——Gitpod 内部使用的是同一套工作流与工具来完成初始化,理解它如何工作才能用好它。
五、结合仓库源码的深度印证:核心命令背后的实现
为了让上文中的每一步都"可验证",这里把核心命令与仓库中的真实实现一一对应:
| 文档中的命令/概念 | 仓库中的实际实现 | 关键行为 |
|---|---|---|
yarn build:test-project <path> |
package.json → tasks/test-project/test-project | 复制 fixture 或从 create-redwood-app 构建 → yarn install → canary 升级 → codemods → dbAuth 密钥 → prisma migrate reset → lint --fix |
RWFW_PATH=… yarn rwfw project:sync |
package.json → tasks/framework-tools/frameworkSyncToProject.mjs | clean+build 框架 → 注入框架依赖 → yarn install → 复制包文件/修复 bin → chokidar 监听变更并增量重建 |
yarn rwfw project:tarsync |
package.json → tasks/framework-tools/tarsync/bin.mts | build:test-project --link 时用于把框架以 tarball 方式同步进项目 |
| 框架依赖注入 | tasks/framework-tools/lib/framework.mjs、tasks/framework-tools/lib/project.mjs | 遍历所有 @redwoodjs 包收集非红木依赖(跳过 storybook-framework-redwoodjs-vite),合并进项目根 package.json,重复依赖版本不一致会直接抛错 |
| 包文件复制 | tasks/framework-tools/lib/project.mjs | 用 npm-packlist 计算每个包的发布文件清单,先 rimraf 清空 node_modules/<package> 再逐文件复制 |
| Vite 配置临时修改 | tasks/framework-tools/lib/viteConfig.mjs | 用 Babel 解析 `web/vite.config.js |
yarn check |
package.json | yarn constraints + yarn dedupe --check,检查 Yarn resolutions 与依赖去重 |
这些印证表明:文档描述的"clean → build → 注入依赖 → install → 复制 → 等待变更"五步流程与 tasks/framework-tools/frameworkSyncToProject.mjs 中的实际执行顺序完全一致(该脚本中五步依次对应 yarn build:clean、yarn build、addDependenciesToPackageJson、yarn install、copyFrameworkFilesToProject + fixProjectBinaries),并且脚本在收到 SIGINT/进程退出时会自动把项目 package.json 与 vite 配置恢复原状(见 tasks/framework-tools/frameworkSyncToProject.mjs)——这与文档中"用 ctrl + c 结束链接进程后,确认 package.json 不再有多余依赖"的操作指引互为印证。
六、常见问题速查
Q1:新创建的测试项目为什么用不上我 main 分支的新代码?
因为新建项目默认使用 npm 最新稳定版包。先 yarn rw upgrade --tag canary 升级到 canary,再 yarn rwfw project:sync 链接本地框架代码,两者缺一不可。
Q2:project:sync 改了我的项目文件,怎么还原?
进程退出(含 ctrl + c)时会自动还原根 package.json 与 web/vite.config.js|ts。脚本给出的手动恢复步骤是:撤销对 yarn.lock 的改动 → 删除项目 node_modules → 重新 yarn install。
Q3:切换分支后测试项目状态混乱怎么办?
文档建议从 git clean -fxd(必要时加 -e .env 保留环境变量)开始,重新走 yarn install → project:sync 的完整流程。
Q4:Windows 上无法运行 E2E 或 rwfw 命令?
E2E(Cypress)在 Windows 上不支持,用 Gitpod 或请维护者协助;RWFW_PATH 环境变量前缀写法被拒时,改用 cross-env 前置或先写入 shell 环境变量。
Q5:代码改到一半,适合开 PR 吗? 适合。用 Draft PR 尽早开启讨论与确认方向,避免在错误方向上投入大量时间;PR 被关闭或被取代都是协作流程的正常部分。
结语
从 Fork 框架、搭建功能测试项目、rwfw project:sync 链接本地代码,到跑通 build/lint/test/check 四件套,再到提交 PR 与善用 Draft PR,整套贡献工作流的每一步都能在仓库源码中找到对应的真实实现(tasks/test-project/、tasks/framework-tools/、package.json)。对本仓库有更深入兴趣的读者,还可以继续阅读 CONTRIBUTING.md 获取框架包贡献的参考细节,或浏览 docs/docs/contributing-overview.md 了解社区协作规范与 PR 评审标准。现在,Fork 一份代码、开一个分支,去提交你的第一个 PR 吧。