☰
GitBook 开源渲染引擎开发指南:AGENTS.md 中的命令、架构、测试与贡献工作流
2026/10/1 2:07:24 网站建设 项目流程
  • 前端
  • 后端
  • 知识管理

【免费下载链接】gitbook

The open source frontend for GitBook doc sites

项目地址:https://gitcode.com/gh_mirrors/gi/gitbook
点击查看免费下载

本文面向希望参与 GitBook 开源仓库(GitBook 发布内容的前端渲染引擎)开发的工程师,系统梳理仓库根目录 AGENTS.md 中定义的开发工作流:从环境准备、日常命令,到本地代理调试、monorepo 架构、测试体系、Changesets 版本管理与注释规范。读完本文,你将掌握该仓库"从bun install到提交 changeset"的完整开发闭环,并能结合源码理解http://localhost:3000/url/<site>代理机制的真实实现。

一、AGENTS.md 是什么:仓库协作的单一事实来源

在仓库根目录中,CLAUDE.md 的全部内容只有一行@AGENTS.md,这意味着 AGENTS.md 被设计为面向代码协作 Agent(以及人类开发者)的唯一权威开发说明。它不介绍产品功能,而是回答一个实际问题:在这个 monorepo 里,如何安装、运行、构建、测试、提交一个改动。

整个文档围绕六个主题展开:Commands(命令)、Development(本地开发)、Architecture(架构)、Testing(测试)、Changesets(版本管理)、Formatting 与 Comments(代码风格与注释规范)。下文将逐节展开,并结合仓库中的 package.json、turbo.json 与 middleware.ts 等实现细节进行佐证。

二、环境准备与核心命令

AGENTS.md 首先给出了一套以 Bun 为核心的命令集。仓库的 package.json 中声明了packageManager: bun@1.3.7与engines.node: ^22.3.0,即要求 Node.js 22.3+ 与 Bun 1.2.15+(Bun 文本格式锁文件bun.lock在 1.2.15 之前不被支持)。

bun install # 安装依赖 bun dev # 启动开发服务器(所有包) bun run build # 构建所有包 bun run lint # 用 Oxlint 检查 bun run format # 用 Oxfmt 格式化(每次改动后运行) bun run typecheck # 对所有包做类型检查 bun run unit # 运行单元测试

这些命令在根 package.json 中均有对应脚本,且大多通过 Turborepo 编排:

命令实际执行的脚本说明
bun devturbo run dev --concurrency 20以 20 并发启动所有包的 dev 任务
bun run buildturbo run build递归构建所有包(含被依赖的包)
bun run lintoxlint --quietOxlint 静态检查,仅输出问题
bun run formatoxfmt使用 Oxfmt 格式化全部代码
bun run typecheckturbo run typecheck对所有包执行类型检查
bun run unitturbo run unit对所有包执行单元测试
bun run e2eturbo run e2e端到端测试(需先构建应用)

值得注意的是,构建工具链中 lint 与 format 均采用 Rust 生态的 Oxc 工具(oxlint/oxfmt),而不是 ESLint/Prettier;这与"速度优先"的工程取向一致,也意味着提交前必须用 Oxfmt 而非 Prettier 格式化。

turbo.json 中还定义了任务间的依赖关系,理解它有助于理解"为什么有些命令会比较慢":

  • typecheck依赖^typecheck与build,即先构建再检查,保证类型检查针对的是最新产物;
  • unit依赖^unit、^build与generate,即单元测试前会先构建依赖包并执行代码生成脚本;
  • dev被标记为persistent: true且cache: false,因为它是一个常驻进程;
  • e2e需要BASE_URL与SITE_BASE_URL两个环境变量。

根目录的 bun.lock 是文本格式锁文件,因此务必使用 Bun 而非 npm/yarn 安装依赖,否则锁文件会被破坏。

三、本地开发:dev server 如何代理已发布的 GitBook 站点

AGENTS.md 中最具特色的开发模式是:本地开发服务器会代理线上已发布的 GitBook 站点。启动bun dev后,访问任意已发布站点的方式是:

http://localhost:3000/url/<published-gitbook-url>

官方示例:

  • http://localhost:3000/url/gitbook.com/docs
  • http://localhost:3000/url/open-source.gitbook.io/midjourney

这意味着你不需要在本地准备任何内容数据——任何已发布的 GitBook 站点都可以通过本地实例访问,你对代码库做的任何修改都会实时反映在浏览器中。这正是 GitBook"渲染引擎开源"的典型工作流:本地只负责渲染,数据通过 API 从线上拉取。

/url/前缀的代理机制可以在 middleware.ts 的getSiteURLFromRequest函数(约 L723-L766)中看到源码级实现。该函数按优先级从三种方式解析"目标站点 URL":

  1. X-GitBook-URL请求头:URL 直接取自该头(mode: 'url-host');
  2. X-Forwarded-Host请求头:Host 取自该头,路径沿用请求路径(mode: 'url-host');
  3. /url/:url路径匹配:当请求落在主 host 且路径以/url/开头时,将路径剩余部分拼成https://<...>作为目标 URL(mode: 'url'),即文档中示例的解析路径。

解析出目标 URL 后,middleware 会调用lookupPublishedContentByUrl从 GitBook API 查询站点内容,再通过NextResponse.rewrite将请求重写到内部路由sites/<routeType>/<mode>/<host>/<rison-encoded-data>/<pathname>(约 L518-L553)。因此,开发时看到的 URL 是/url/...,但实际渲染的是重写后的内部路由。

从 packages/gitbook/package.json 可以看到,gitbook 包的 dev 脚本还会先执行代码生成:

"dev": "bun run generate:assets && env-cmd --silent -f ../../.env.local next --webpack"

其中generate:assets会依次生成 Mermaid 运行时、Scalar 运行时、下载字体(对应 scripts/generate.sh 及其子脚本),这解释了为什么首次bun dev需要较长准备时间。由于启动时需要读取.env.local,仓库提供了bun run download:env(通过 1Password CLI 拉取)作为可选的开发辅助命令。

四、架构总览:monorepo 中的包划分

AGENTS.md 给出了一张精炼的架构树。它描述了渲染引擎的模块化组织方式——所有功能都被拆分为packages/下的独立包:

packages/ gitbook/ # 主 Next.js 应用 src/ app/ # Next.js App Router (sites/) components/ # React 组件 lib/ # 服务端工具、数据获取 intl/ # 国际化 (translations/) openapi-parser/ # OpenAPI 3.0/3.1/Swagger 解析器 react-openapi/ # OpenAPI 渲染组件 react-contentkit/ # ContentKit 组件渲染 embed/ # 可嵌入的 GitBook 组件 shared/ # 共享工具 icons/ # 图标资源 fonts/ # 字体资源 colors/ # 颜色令牌 expr/ # GitBook 表达式求值器 cache-do/ # Cloudflare DO 缓存 cache-tags/ # 缓存标签工具

对照仓库实际的 packages 目录,可以看到当前存在 13 个包:browser-types、cache-tags、colors、embed、emoji-codepoints、expr、fonts、gitbook、icons、openapi-parser、react-contentkit、react-math、react-openapi。其中与文档描述略有出入的是:shared与cache-do并未以独立包出现在顶层(相关能力可能已被合并或重组),而browser-types、emoji-codepoints、react-math是文档未列出的新增包。以仓库实际目录为准即可。

理解包划分的关键在于依赖方向:gitbook主应用依赖其余所有包,packages/gitbook/package.json 中可以看到@gitbook/browser-types、@gitbook/cache-tags、@gitbook/colors、@gitbook/embed、@gitbook/expr、@gitbook/fonts、@gitbook/icons、@gitbook/openapi-parser、@gitbook/react-contentkit、@gitbook/react-math、@gitbook/react-openapi全部以workspace:*形式引用。这种"主应用 + 可独立发布库"的布局,配合 turbo.json 的dependsOn: ["^build", "generate"],保证改动任一子包时依赖链上的包会按拓扑顺序重建。

五、测试体系:bun test 与 Playwright 双轨并行

AGENTS.md 明确了测试的划分方式:

bun run unit # 单元测试,通过 bun test 运行(不是 vitest) bun run e2e # Playwright 端到端测试(需要先构建应用)

运行单个测试文件:

cd packages/gitbook && bun test src/lib/cache.test.ts

两点关键信息:

  1. 单元测试使用 Bun 内置的bun test,而非 vitest/jest。在 packages/gitbook/package.json 中,gitbook 包的单元测试脚本为:
"unit": "bun run generate:assets && bun test {src,packages} --preload ./tests/preload-bun.ts"

它先执行资源生成,再以 tests/preload-bun.ts 作为预加载文件运行src与packages下的测试。仓库中大量测试文件(如 src/lib/cache.test.ts、src/lib/urls.test.ts 等)都遵循*.test.ts的命名约定。

  1. 端到端测试使用 Playwright,且需要先完成构建(bun run build)。gitbook 包的 e2e 脚本:
"e2e": "playwright test e2e/internal.spec.ts e2e/cookie-banner.spec.ts e2e/pdf.spec.ts e2e/select.spec.ts e2e/tabs-overflow.spec.ts --project=chromium"

测试用例集中在 packages/gitbook/e2e/ 目录(如internal.spec.ts、pdf.spec.ts、select.spec.ts、style-perf.spec.ts),并配有 playwright.config.ts。此外还有面向客户站点的e2e-customers(e2e/customers.spec.ts)与样式性能测试e2e-style-perf(e2e/style-perf.spec.ts)。注意 e2e 任务在 turbo.json 中需要BASE_URL与SITE_BASE_URL环境变量。

六、Changesets:标准化的版本管理与发布流程

GitBook 采用 Changesets 管理多包版本与发布。AGENTS.md 规定:每次提交代码改动后,必须为受影响的包创建 changeset,格式如下:

--- "gitbook": patch --- Provide a short description of the change.

工作流要点:

  • frontmatter 中声明受影响包及其版本类型:"<包名>": <patch|minor|major>。包名对应packages/下各包的 npm 名称(如gitbook、@gitbook/expr、@gitbook/react-openapi等);
  • 正文写简短描述,说明改了什么;
  • 保存为.changeset/<name>.md,并以changeset作为独立的 commit message 提交。

仓库中 .changeset/ 目录真实存在且包含大量已生成的 changeset 文件。以 .changeset/quiet-dogs-merge.md 为例,其内容正是上述模板的实际产物:

--- "gitbook": patch --- Render horizontal and vertical merged table cells on published pages.

其他如fix-rss-discovery.md、mcp-ask-question-tool.md、lazy-mermaid-code-block.md等,均遵循"一个改动 = 一个 changeset 文件"的约定,文件名是随机生成的形容词-名词组合(由 Changesets CLI 自动生成)。根 package.json 中的changeset、changeset-version、publish-all-packages脚本对应完整的发布链路:changeset创建变更集 →changeset version && bun run format && bun update升级版本并格式化 →turbo run publish-to-npm --continue=dependencies-successful按依赖顺序发布到 npm。发布脚本位于 scripts/publish-if-new.sh。

七、格式化与注释规范:Oxc 工具链 + "why 优先"的注释哲学

7.1 格式化规范

AGENTS.md 强调:lint 用 Oxlint,format 用 Oxfmt,提交前必须运行bun run format。这与第二节的命令表一致。由于 Oxfmt 是格式化工具,运行bun run format会实际改写代码,因此正确的提交姿势是:

  1. 完成代码修改;
  2. 运行bun run format格式化;
  3. 运行bun run lint确认无问题;
  4. 创建 changeset 并提交。

7.2 注释规范

AGENTS.md 对注释给出了明确的原则,这在整个仓库的代码风格中都能得到印证:

  • 注释解释"为什么"(why),而非"是什么"(what)——代码本身已经展示了它做了什么;
  • 保持简短,理想情况是单行;
  • 避免用多行块注释去叙述读者能从代码直接跟读的机制,这类注释既增加噪音又容易过时;
  • 把长注释留给真正不明显的理由:比如一个微妙的不可变约束(subtle invariant),或一个 workaround 及其存在的原因。

这条规范在源码中有大量实践。例如 middleware.ts 中,重写 URL 前有一段注释解释了为何移除某些查询参数、为何对 server action 使用X-Action-Redirect头而非重定向响应("当它是 server action 时,不能直接返回重定向响应,因为它可能在重定向上引发 CORS 问题");open-next.config.ts 中dangerous.enableCacheInterception等配置也带有简短意图说明。这些都是"解释 why、单行简短"的典型样本。

八、快速自查清单

参与本仓库开发时,可对照以下清单逐项确认,这也是对 AGENTS.md 全部要求的浓缩:

  • 使用 Bun 安装依赖:bun install(勿用 npm/yarn 触碰bun.lock)
  • 本地调试用bun dev,并通过http://localhost:3000/url/<published-url>访问任意已发布站点
  • 提交前运行bun run format(Oxfmt)与bun run lint(Oxlint)
  • 全量校验运行bun run typecheck与bun run unit;涉及集成行为时运行bun run build后执行bun run e2e
  • 单个测试文件:cd packages/gitbook && bun test <path/to/file.test.ts>
  • 每个改动为受影响包创建.changeset/<name>.md,并以changeset为 message 单独提交
  • 注释只写 why,保持单行简短;把长注释留给真正不明显的约束或 workaround

这套流程保证了 monorepo 在多人/多 Agent 协作下的可维护性:命令统一由 Turbo 编排、代码风格由 Oxc 工具链强制、版本变更由 Changesets 追踪、注释质量由"why 优先"原则把关。对希望为 GitBook 渲染引擎贡献代码的开发者而言,AGENTS.md 就是进入这个工程体系最快的入口。

  • 前端
  • 后端
  • 知识管理

【免费下载链接】gitbook

The open source frontend for GitBook doc sites

项目地址:https://gitcode.com/gh_mirrors/gi/gitbook
点击查看免费下载
上一篇:Liquibase数据库回滚终极指南:如何避免数据丢失的10个技巧
下一篇:瑞士科研机构联合发布全球首个全透明多语言大模型Apertus,引领开放AI新纪元

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询