
Taier 官网(Docusaurus)使用与结构拆解
在做一个开源项目的官网时,我们常常会遇到这样一个具体问题:项目代码已经开源,但缺少一个结构清晰、能持续维护、还能兼顾品牌形象的官网文档站。手写静态页维护困难,纯博客框架又不适合承载多层级文档,而自研一套又成本过高。于是我们把目光投向了成熟的开源文档站框架。本文以 DTStack 开源项目 Taier(分布式 DAG 任务调度系统)的官网为真实案例,完整走一遍从技术选型 → 快速启动 → 结构拆解 → 功能模块 → 总结复盘的全过程。
案例信息:/Users/edy/changlu_workspace/opensource/Taier-master/website
来源地址:https://github.com/DTStack/Taier
website 位置:https://github.com/DTStack/Taier/tree/master/website
一、技术栈使用
问题引导:搭建开源项目官网,到底该选哪个框架?为什么 Taier 最终选择了 Docusaurus?
1.1、方案对比:三种主流选择怎么选?
在动手前,我们先对常见的三种文档站方案做一次对比:
| 方案 | 代表 | 优点 | 弊端说明 | 适用场景 |
|---|---|---|---|---|
| 方案一:静态生成框架 | Docusaurus(本案例) | React 生态、首页可深度定制、文档能力强、社区活跃 | 需一点 React 基础;版本迭代需跟随 | 需要官网 + 多层级文档、且要深度定制 |
| 方案二:配置化托管 | Mintlify | 配置驱动、上手快、内置多语言多版本 | 深度定制受限、偏托管 | 快速上线、内容为主 |
| 方案三:轻量文档框架 | VitePress / VuePress | 构建快、Vue 生态、主题简洁 | 官网 Landing 定制不如 React 灵活 | 纯文档站、社区为主 |
重点:Taier 的诉求是「官网 Landing 要好看 + 文档要能承载 20+ 任务类型的多层级结构 + 要能自定义品牌主题」,这三点恰好落在 方案一 Docusaurus 的能力区间——既能用 Markdown 写文档,又能用 React 自由定制首页。因此最终选定 Docusaurus。
1.2、技术栈总览
确定框架后,Taier 官网实际采用的技术栈如下:
| 层次 | 技术 | 版本/说明 |
|---|---|---|
| 站点生成器 | Docusaurus | 2.0.0-beta.14(classic 预设) |
| 预设 | @docusaurus/preset-classic |
集成 docs / blog / theme / gtag |
| 前端框架 | React | ^17.0.1 + react-dom ^17.0.1 |
| 内容格式 | Markdown / MDX | .md 为文档主体,.mdx 可嵌 React |
| 样式方案 | Infima(默认)+ Sass / CSS Modules | docusaurus-plugin-sass ^0.2.2、sass ^1.54.5 |
| 代码高亮 | prism-react-renderer |
github(亮)/ dracula(暗),附加 nginx、java |
| 工具库 | clsx |
条件拼接 className |
| MDX 运行时 | @mdx-js/react ^1.6.21 |
MDX v1 |
| 访问统计 | gtag(Google Analytics) |
G-09MSEFN7VC |
| 包管理 | npm | 工程自带 yarn.lock,npm 亦可正常使用 |
1.3、关键机制说明
- classic 预设:一次性提供文档系统、博客系统、主题、统计,无需自己组装插件。
- Sass 扩展:通过
plugins: ["docusaurus-plugin-sass"]引入,工程可直接写.scss与*.module.scss(CSS Modules)。 - 主题定制两级机制:
- 轻量定制 → 覆盖 Infima 的
--ifm-*CSS 变量(custom.css); - 深度定制 →
docusaurus swizzle弹出官方主题组件后自行改写。
- 轻量定制 → 覆盖 Infima 的
- 暗色模式:Infima 原生支持
data-theme="dark",工程通过变量与useThemeContext双套适配。
依赖清单(package.json 摘要):
{
"dependencies": {
"@docusaurus/core": "2.0.0-beta.14",
"@docusaurus/preset-classic": "2.0.0-beta.14",
"@mdx-js/react": "^1.6.21",
"clsx": "^1.1.1",
"docusaurus-plugin-sass": "^0.2.2",
"prism-react-renderer": "^1.2.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"sass": "^1.54.5"
}
}
注意:该工程基于 Docusaurus 2.0.0-beta.14 + React 17,属于较早版本;若今天新建项目,建议直接使用 Docusaurus 3.x,API 更稳定、生态更完整。
二、快速启动
问题引导:选好框架后,如何把这个官网在本地跑起来?下面是本次实测的完整执行步骤。
2.1、环境要求
- Node.js:推荐 Node 16.x(Docusaurus 2.0.0-beta.14 对其兼容最好;本次实测
v16.20.2)。 - 包管理:yarn 1.x(工程自带
yarn.lock,用 yarn 安装最稳妥)。 - 可选:Git(用于
yarn deploy发布 GitHub Pages)。
弊端说明:本工程未提供
package-lock.json,直接用npm install会因镜像 integrity 校验问题报EINTEGRITY(尤其在国内 npmmirror 镜像下)。因此实测推荐使用 yarn,它按yarn.lock安装更可靠。
2.2、安装 Node 16(如已具备可跳过)
有 nvm 时切换 Node 版本:
# 查看可用版本
nvm ls
# 切换到 Node 16
nvm use 16
node -v # 应输出 v16.x
注意:若
nvm use报globalconfig/prefix不兼容,可直接把 Node 16 的 bin 目录加入 PATH:export PATH="$HOME/.nvm/versions/node/v16.20.2/bin:$PATH" node -v && npm -v
2.3、安装 yarn 工具
corepack 是什么? 它是 Node.js 官方内置的「包管理器版本管理器」,从 Node 16.9 起随 Node 一起发布(目前仍为实验特性)。它让项目按声明自动使用正确的包管理器及其版本,无需再手动 npm i -g yarn——执行 corepack enable 后会在 Node 的 bin 目录生成 yarn、pnpm 的转发 shim,之后调用 yarn 时由 corepack 读取项目要求并自动下载对应版本,从而保证团队使用完全一致的包管理器。
Node 16 自带 corepack,因此无需全局 npm 安装即可启用 yarn:
# 启用 corepack(生成 yarn 等 shim)
corepack enable
# 激活 yarn 1.22.22(与工程的 yarn.lock v1 格式匹配)
corepack prepare yarn@1.22.22 --activate
# 验证
yarn --version # 应输出 1.22.22
重点:
corepack enable只是生成 shim,真正决定版本的是corepack prepare yarn@<版本> --activate。若项目package.json中声明了packageManager字段,corepack 会优先按该字段严格校验版本。
2.4、安装依赖
# 进入 website 目录
cd website
# 按 yarn.lock 安装依赖
yarn install
重点:安装耗时取决于网络,可加超时参数
yarn install --network-timeout 600000;国内镜像(npmmirror)已配置到.npmrc,yarn 会复用。
2.5、启动服务
# 本地开发(热更新),默认端口 3000
yarn start --port 3000
启动成功后终端输出:
[SUCCESS] Docusaurus website is running at http://localhost:3000/Taier/.
访问地址:http://localhost:3000/Taier/
重点:工程
baseUrl: "/Taier/",因此本地访问必须带/Taier/前缀,否则页面 404。若改为部署到域名根路径,需把baseUrl改为/。
2.6、构建与预览
# 生产构建 → website/build/
yarn build
# 本地预览构建产物
yarn serve
# 构建异常时先清理缓存
yarn clear
2.7、常用命令表
| 命令 | 作用 |
|---|---|
yarn start |
启动开发服务器,热更新预览 |
yarn build |
生产构建,输出到 build/ |
yarn serve |
本地静态预览 build/ |
yarn clear |
清理缓存(构建异常时先执行) |
yarn swizzle |
弹出主题内部组件以深度定制 |
yarn deploy |
构建并发布到 GitHub Pages |
yarn write-translations |
生成翻译文件(i18n) |
yarn write-heading-ids |
为标题生成稳定锚点 id |
注意:若坚持使用 npm,命令为
npm install/npm start/npm run build/npm run serve/npm run clear;除start外自定义脚本都要加run。
三、目录结构 + 模块拆解
问题引导:项目能跑起来之后,它是怎么组织的?哪些文件控制配置,哪些承载内容?
3.1、顶层目录结构
website/
├── docusaurus.config.js # 站点总配置(标题/baseUrl/导航/页脚/主题/插件)
├── sidebars.js # 侧边栏结构(文档左侧目录树)
├── package.json # 依赖与命令
├── babel.config.js # Docusaurus 预设 babel(固定模板)
├── yarn.lock / .gitignore # 锁文件 / 忽略 node_modules、build、.docusaurus
├── docs/ # 所有文档页(Markdown)
├── src/ # 自定义 React 源码(首页、组件、全局样式)
└── static/ # 静态资源(图片等,原样拷贝到构建根)
3.2、模块拆解
(1)根配置模块
| 文件 | 职责 |
|---|---|
docusaurus.config.js |
站点元信息、baseUrl、导航栏 navbar、页脚 footer、主题 prism、gtag、sass 插件 |
sidebars.js |
显式声明文档侧边栏的分组、顺序、折叠态与嵌套层级 |
package.json |
依赖版本与 npm scripts |
babel.config.js |
固定三行,加载 Docusaurus babel 预设 |
(2)docs/ 内容模块
docs/
├── guides/ # 关于 Taier
│ ├── introduction.md
│ ├── explain.md
│ └── taier-architecture.md
├── quickstart/ # 快速开始
│ ├── rely.md / build.md / idea.md / start.md / faq.md
│ └── deploy/ # 快速部署(quick / docker / cluster)
├── functions/ # 功能介绍
│ ├── multi-cluster.md / datasource.md / maintenance.md
│ ├── depend.md / task-param.md / environmental-parameters.md / metrics-monitor.md
│ ├── component/ # 组件配置(sftp/yarn/hdfs/spark/flink/datax...)
│ └── task/ # 任务类型(20+:spark-sql/flink-sql/hive-sql/shell...)
├── expand/ # 自定义扩展开发(task.md / component.md)
├── contributing.md # 贡献指南
├── tutorial-basics/ # 模板残留(含 _category_.json)
└── tutorial-extras/ # 模板残留
- 目录即分类:
docs/的子目录对应官网的四大分类。 _category_.json:自动模式下的目录元数据(label + position),Taier 主体改用sidebars.js显式定义。- front matter:每页头部
title/sidebar_label/sidebar_position。
(3)src/ 自定义模块
src/
├── pages/
│ ├── index.js # 首页入口:组装 Intro + Features + Case
│ └── index.scss # 首页 banner 渐变样式
├── components/
│ ├── intro.jsx # 首屏 Hero(标题/描述/快速开始按钮/插画组)
│ ├── features.jsx # 三大特性卡(稳定性/可扩展性/易上手)
│ ├── case.jsx # 大图展示区(多任务/调度信息)
│ ├── icon.jsx # SVG 图标
│ └── *.module.scss # 各组件的 CSS Modules 样式
└── css/
├── custom.css # 全局样式 + Infima 变量覆盖(亮/暗)
└── footer.css # 页脚样式
- 页面入口:
src/pages/index.js即/路由;Docusaurus 会把src/pages下文件自动映射为路由。 - 组件复用:首页完全用 React 自定义,通过
@site别名导入图片,通过useThemeContext适配暗色。 - 样式隔离:组件样式用
*.module.scss(局部作用域);全局主题用custom.css。
(4)static/ 资源模块
static/
├── .nojekyll # 禁用 GitHub Pages 的 Jekyll 处理
└── img/
├── logo.svg / favicon.png
├── assets/ # 首页插画与展示图
├── readme/ # 文档正文截图(login.png / spark-sql.png ...)
└── tutorial/ # 模板残留图
- 文件按原路径拷贝到构建根:
static/img/readme/x.png→ URL/img/readme/x.png。 - 文档中引用:
。
弊端说明:
docs/tutorial-basics/、docs/tutorial-extras/是官方模板残留目录,实际项目中应删除,否则会污染文档结构。
3.3、文档站内容结构汇总表
整个文档站的内容按「一级分类 → 二级模块 → 文档文件」组织,全部内容汇总如下(与 sidebars.js 一一对应):
| 一级分类 | 二级模块 | 目录/文件 | 文档数 | 内容说明 |
|---|---|---|---|---|
| 关于 Taier | 介绍 / 名词 / 架构 | docs/guides/ |
3 | 项目定位、名词解释、系统架构 |
| 快速开始 | 依赖 / 部署 / 编译 / 上手 / FAQ | docs/quickstart/(含 deploy/) |
8 | 部署依赖、快速/Docker/集群部署、源码编译、IDEA 启动、快速上手、常见问题 |
| 功能介绍 | 核心功能 | docs/functions/*.md |
7 | 多集群、数据源、运维、依赖、任务参数、环境参数、指标监控 |
| 功能介绍 | 组件配置 | docs/functions/component/ |
9 | SFTP、YARN、HDFS、Flink、Spark、DataX 等组件对接 |
| 功能介绍 | 任务类型 | docs/functions/task/ |
24 | SQL 类(Spark/Flink/Hive/MySQL…)、数据同步、实时采集、工作流等 |
| 自定义扩展开发 | 自定义任务 / 组件 | docs/expand/ |
2 | 任务与组件的二次扩展开发 |
| 贡献指南 | — | docs/contributing.md |
1 | 贡献流程、代码与提交规范 |
| 合计 | — | docs/ |
54 | 侧边栏注册的全部文档 |
重点:
docs/下实际共有 56 个.md文件,其中 54 个已在sidebars.js注册并显示;剩余 2 个(functions/task.md、functions/component/spark-thrift.md)未注册,不会出现在侧边栏中。tutorial-basics/、tutorial-extras/不含正文 md,仅为模板残留。
(1)关于 Taier(3 篇)
| 文档 | 路径 |
|---|---|
| Taier 介绍 | guides/introduction.md |
| 名词解释 | guides/explain.md |
| 系统架构 | guides/taier-architecture.md |
(2)快速开始(8 篇)
| 模块 | 文档 | 路径 |
|---|---|---|
| 依赖 | 部署依赖 | quickstart/rely.md |
| 快速部署 | 快速部署 | quickstart/deploy/deployment-quick.md |
| 快速部署 | Docker 部署 | quickstart/deploy/docker.md |
| 快速部署 | 集群部署 | quickstart/deploy/cluster-deploy.md |
| 开发 | 源码编译 | quickstart/build.md |
| 开发 | IDEA 启动 | quickstart/idea.md |
| 上手 | 快速上手 | quickstart/start.md |
| 支持 | 常见问题 FAQ | quickstart/faq.md |
(3)功能介绍 - 核心功能(7 篇)
| 文档 | 路径 |
|---|---|
| 多集群管理 | functions/multi-cluster.md |
| 数据源 | functions/datasource.md |
| 运维中心 | functions/maintenance.md |
| 任务依赖 | functions/depend.md |
| 任务参数 | functions/task-param.md |
| 环境参数 | functions/environmental-parameters.md |
| 指标监控 | functions/metrics-monitor.md |
(4)功能介绍 - 组件配置(9 篇)
| 组件 | 路径 |
|---|---|
| SFTP | functions/component/sftp.md |
| YARN | functions/component/yarn.md |
| HDFS | functions/component/hdfs.md |
| Flink on YARN | functions/component/flink-on-yarn.md |
| Flink on Standalone | functions/component/flink-on-standalone.md |
| Script on YARN | functions/component/script-on-yarn.md |
| Script on Standalone | functions/component/script-on-standalone.md |
| Spark | functions/component/spark.md |
| DataX | functions/component/datax.md |
(5)功能介绍 - 任务类型(24 篇)
| 分组 | 任务类型 | 路径前缀 functions/task/ |
|---|---|---|
| 同步 / 采集 / 脚本 | 数据同步、数据采集、Python、Shell、DataX | sync.md、data-acquisition.md、python.md、shell.md、datax.md |
| 流程编排 | 工作流、虚节点 | workflow.md、virtual.md |
| 计算引擎 | Flink、Spark Jar、Hadoop MR | flink.md、spark-jar.md、hadoop-mr.md |
| SQL 类 | Flink SQL、Spark SQL、Hive SQL、OceanBase SQL、Doris SQL、ClickHouse SQL、TiDB SQL、GaussDB SQL、MySQL SQL、Vertica SQL、Greenplum SQL、PostgreSQL SQL、SQLServer SQL、MaxCompute SQL | flink-sql.md、spark-sql.md、hive-sql.md、oceanbase-sql.md、doris-sql.md、clickhouse-sql.md、tidb-sql.md、gaussdb-sql.md、mysql-sql.md、vertica-sql.md、greenplum-sql.md、postgre-sql.md、sqlserver-sql.md、maxcompute-sql.md |
(6)自定义扩展开发(2 篇)+ 贡献指南(1 篇)
| 分类 | 文档 | 路径 |
|---|---|---|
| 扩展开发 | 自定义任务 | expand/task.md |
| 扩展开发 | 自定义组件 | expand/component.md |
| 贡献指南 | 贡献指南 | contributing.md |
重点:从内容结构可以看出,官网以「快速开始」(上手)和「功能介绍」(任务类型 24 + 组件配置 9)为重心,共占 33/54 ≈ 61%,符合大数据调度系统「功能优先」的文档特征。
四、文档站功能模块组成
问题引导:这个文档站由哪些功能模块拼装而成?各自由什么配置或代码驱动?
4.1、功能模块总览图
Taier 官网
├── 顶部导航栏 Navbar ── 文档 / 源码下载 / FAQ / GitHub
├── 首页 Landing
│ ├── Hero(Intro)
│ ├── 特性卡(Features)
│ └── 案例展示(Case)
├── 文档系统 Docs
│ ├── 侧边栏(sidebars.js:关于/快速开始/功能/扩展)
│ ├── 文档页(Markdown + 提示块 + 代码高亮)
│ └── 页内 TOC + 上下页导航
├── 页脚 Footer ── Docs / Community / 版权
└── 全局主题 ── Infima 变量 + 暗色模式 + gtag 统计
4.2、各模块说明
(1)顶部导航栏(Navbar)
配置于 docusaurus.config.js → themeConfig.navbar:
- Logo + 站点名
Taier - 左侧:「文档」(docId 指向
guides/introduction)、「源码下载」(外链 releases)、「常见问题」(FAQ 链接) - 右侧:GitHub 图标链接(通过
className: header-github-link由 CSS 绘制内联 SVG)
(2)文档系统(Docs)
- 侧边栏:由
sidebars.js显式定义,四大分类 + 嵌套子分类,collapsed控制折叠。 - 文档页:Markdown 编写,
##/###分层,:::tip / :::caution / :::note提示块,代码块标注语言高亮。 - 页面导航:Docusaurus 自动生成上一页/下一页、右侧页内目录(TOC)。
- 内容检索:classic 预设的搜索能力(默认接入)。
(3)首页 Landing(自定义)
由 src/pages/index.js 组装:
| 区块 | 组件 | 内容 |
|---|---|---|
| 首屏 Hero | intro.jsx |
标语、描述、「快速开始」CTA 按钮、亮暗两套插画 |
| 特性展示 | features.jsx |
稳定性 / 可扩展性 / 易上手 三张卡片 |
| 案例展示 | case.jsx |
Multiple Tasks / Schedule Information 两大图区 |
(4)页脚(Footer)
配置于 themeConfig.footer:
- Docs:Introduction / Quick Start / Contributing
- Community:GitHub
- 版权:
Copyright © {year} DTStack, Inc.
(5)主题与暗色模式
src/css/custom.css覆盖 Infima--ifm-*变量(导航栏、页脚、正文、代码块等)。:root[data-theme="dark"]提供暗色变量;首页组件用useThemeContext切换图片。- 自定义变量(
--banner-*、--homepage-*)供首页 scss 复用。
(6)代码高亮与统计
themeConfig.prism:亮/暗代码主题 + 额外语言(nginx、java)。gtag:Google Analytics 统计G-09MSEFN7VC。
(7)质量与部署设施
onBrokenLinks: "error"/onBrokenMarkdownLinks: "error":死链即构建失败,强制质量。.nojekyll:保证 GitHub Pages 正常托管。editUrl:每篇文档提供「编辑此页」入口(可指向仓库)。
4.3、脚本工具介绍
除了 start / build / serve / clear 这些日常命令,package.json 还内置了几个进阶工具脚本,分别服务于「主题深度定制」「发布上线」「国际化」「锚点维护」四类场景:
| 命令 | 用途 | 使用场景 |
|---|---|---|
yarn swizzle |
弹出(拷贝)主题内部组件到本地以深度定制 | 想改导航栏、页脚、代码块等官方组件的行为或结构 |
yarn deploy |
构建并发布到 GitHub Pages | 官网内容定稿后一键上线 |
yarn write-translations |
提取文案生成 i18n 翻译文件 | 需要支持多语言(中/英等)时 |
yarn write-heading-ids |
为文档标题生成稳定锚点 id | 需要跨页面稳定链接到某个小节时 |
(1)yarn swizzle —— 主题深度定制
Docusaurus 的主题由官方组件构成,普通场景用 CSS 变量覆盖即可;当需要改动组件结构或逻辑时,用此命令把目标组件「弹出」到 src/theme/ 下再自行改写。
yarn swizzle # 交互式选择要弹出的组件
yarn swizzle @docusaurus/theme-classic Navbar --danger
重点:swizzle 属于深度定制,升级 Docusaurus 时被弹出的组件可能不兼容,需自行维护;能用 CSS 变量解决就不要 swizzle。
(2)yarn deploy —— 发布 GitHub Pages
按 docusaurus.config.js 中的 url / baseUrl / organizationName / projectName 构建并推送到 gh-pages 分支。
GIT_USER=<你的GitHub用户名> yarn deploy
注意:需保证仓库有写权限;
static/.nojekyll存在才能正常托管下划线目录。若用 GitHub Actions 托管,则改用yarn build+ actions 部署。
(3)yarn write-translations —— 生成 i18n 翻译文件
把界面文案与文档抽取为可翻译的 JSON,放入 i18n/ 目录,配合 docusaurus.config.js 的 i18n 配置实现多语言站点。
yarn write-translations # 生成待翻译文件
注意:Taier 官网当前为单一中文,未启用多语言;此命令属于扩展能力,需要多语言时才使用。
(4)yarn write-heading-ids —— 生成标题锚点 id
为 Markdown 文档的各级标题写入显式 {#id},避免标题文字改动或重名导致锚点链接失效,适合对外提供稳定深链的文档。
yarn write-heading-ids
重点:生成的 id 会写回 Markdown 源文件,提交前请 review,避免大量无意义 diff。
五、GitHub Pages 自动化部署(deploy.yml 剖析)
问题引导:官网内容改好了,如何让它「推送即上线」,免去本地手动发布?
Taier 官网通过一个 GitHub Actions 工作流 .github/workflows/deploy.yml 实现推送代码即自动构建并发布到 GitHub Pages。本章单独把它剖析清楚,方便后续快速集成到自己项目。
5.1、完整工作流源码
路径:/Users/edy/changlu_workspace/opensource/Taier-master/.github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [master]
paths: [website/**]
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v4
with:
node-version: 14.x
cache: yarn
cache-dependency-path: website/yarn.lock
- name: Build website
working-directory: website
run: |
yarn install --frozen-lockfile
yarn build
# Popular action to deploy to GitHub Pages:
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Build output to publish to the `gh-pages` branch:
publish_dir: website/build
# Assign commit authorship to the official GH-Actions bot for deploys to `gh-pages` branch:
user_name: github-actions[bot]
user_email: 41898282+github-actions[bot]@users.noreply.github.com
5.2、逐行精讲
下面按工作流的书写顺序,逐块拆解每一个字段的含义与作用。
(1)name: Deploy to GitHub Pages
工作流名称,显示在仓库 Actions 标签页的列表里,仅用于标识,不影响逻辑。
(2)触发条件 on
on:
push:
branches: [master]
paths: [website/**]
push:仅在推送时触发;branches: [master]:只有推送到master分支才触发(新仓库多为main,需改);paths: [website/**]:只有website/目录下的文件发生变化才触发。Taier 是一个多模块仓库,后端/前端/官网共存,加paths过滤可避免「改了后端代码却触发官网部署」的无用构建。
重点:
paths是「精确触发」的利器;若你的文档站独立成库,可删掉paths。
(3)jobs.deploy 与运行环境
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
jobs:一个工作流可含多个 job,这里只有一个deploy;runs-on: ubuntu-latest:在 GitHub 提供的 Ubuntu 虚拟机上运行(每次都是全新环境)。
(4)actions/checkout@v2 —— 拉代码
- uses: actions/checkout@v2
把仓库代码检出到 runner 的工作目录,后续步骤才有源码可用。官方最新为 @v4,建议升级。
(5)actions/setup-node@v4 —— 装 Node 与缓存
- uses: actions/setup-node@v4
with:
node-version: 14.x
cache: yarn
cache-dependency-path: website/yarn.lock
node-version: 14.x:Taier 当时的 Node 版本;Docusaurus 3 建议 Node 20+;cache: yarn:自动缓存 yarn 的全局缓存目录,加速后续安装;cache-dependency-path:关键——因为站点在子目录,yarn.lock不在仓库根,必须显式指定,缓存才生效。
(6)构建步骤 —— working-directory + run
- name: Build website
working-directory: website
run: |
yarn install --frozen-lockfile
yarn build
working-directory: website:该步骤在website/子目录执行,是「站点位于仓库子目录」的核心开关;yarn install --frozen-lockfile:严格按yarn.lock安装,锁文件与package.json不一致直接失败,防止 CI 里依赖漂移(npm 对应npm ci);yarn build:执行 Docusaurus 构建,产物在website/build/。
(7)peaceiris/actions-gh-pages@v3 —— 发布
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: website/build
user_name: github-actions[bot]
user_email: 41898282+github-actions[bot]@users.noreply.github.com
github_token: ${{ secrets.GITHUB_TOKEN }}:GitHub 内置令牌,无需自己创建 Secret;有此令牌才有权限把产物推到gh-pages;publish_dir: website/build:指定要发布的目录(构建产物);user_name/user_email:把提交作者设为 Actions 机器人,避免用自己的账号身份提交。
5.3、运行流程图
开发者 push 到 master(且改动落在 website/**)
│
▼
GitHub Actions 被触发 → 启动 ubuntu-latest runner
│
▼
actions/checkout 拉取仓库源码
│
▼
actions/setup-node 安装 Node 14 + 恢复 yarn 缓存
│
▼
working-directory: website
yarn install --frozen-lockfile
yarn build → 产出 website/build/
│
▼
peaceiris/actions-gh-pages 把 website/build 推送到 gh-pages 分支
│
▼
GitHub Pages 从 gh-pages 分支发布 → 官网可访问
5.4、关键机制拆解
(1)权限与令牌
peaceiris 需要写权限才能推 gh-pages 分支。老仓库默认 token 可写,新仓库默认只读,需二选一:
- 仓库 Settings → Actions → General → Workflow permissions 选 Read and write;
- 或在工作流顶部声明:
permissions:
contents: write
(2)依赖缓存
cache: yarn + cache-dependency-path 决定缓存命中的 key。缓存的是下载的依赖包(不是 node_modules),后续命中可显著缩短安装时间。
(3)发布分支与发布源
peaceiris 把产物推到 gh-pages 分支;再在 Settings → Pages → Source 选 gh-pages 分支作为发布源。二者缺一不可。
(4)触发控制
branches 控制哪个分支触发,paths 控制哪些文件触发。精确配置可避免无用构建、节省 Actions 额度。
5.5、两种发布方案对比
| 方案 | 关键 Action | 发布源 | 权限声明 | 特点 |
|---|---|---|---|---|
| 分支推送(本案例) | peaceiris/actions-gh-pages@v3 |
gh-pages 分支 |
contents: write |
简单直接、兼容老仓库、可自定义提交作者 |
| 官方 Artifact | actions/upload-pages-artifact + actions/deploy-pages |
GitHub Actions | pages: write + id-token: write |
官方推荐、无需维护 gh-pages 分支 |
5.6、快速集成到自己项目(4 步)
- 改部署配置:
docusaurus.config.js中设置url: 'https://<org>.github.io'baseUrl: '/<repo>/'(项目站点必须带仓库名)organizationName/projectName
- 确保
static/.nojekyll存在(否则 GitHub Pages 会忽略以下划线开头的目录)。 - 放置工作流:
.github/workflows/deploy.yml(可直接用下方 5.7 模板)。 - 配置仓库:
- Settings → Actions → General → Workflow permissions 选 Read and write(或工作流里声明
permissions: contents: write); - Settings → Pages → Source 选 Deploy from a branch →
gh-pages/(root)。
- Settings → Actions → General → Workflow permissions 选 Read and write(或工作流里声明
之后推送 master(或 main)即自动发布。
5.7、可直接复用的模板
(1)站点在仓库根目录(最常见)
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch: # 支持手动触发
permissions:
contents: write # peaceiris 推送 gh-pages 需要写权限
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
(2)站点在 website/ 子目录(Taier 形态)
在步骤中改三处即可:cache-dependency-path、working-directory、publish_dir:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
cache-dependency-path: website/yarn.lock
- name: Build website
working-directory: website
run: |
yarn install --frozen-lockfile
yarn build
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: website/build
5.8、变体矩阵(按条件选型)
| 你的情况 | 需要调整 |
|---|---|
主分支是 main |
branches: [main] |
| 站点在子目录 | cache-dependency-path / working-directory / publish_dir 三处指向子目录 |
| 用 npm 而非 yarn | 步骤改 npm ci / npm run build,cache: npm,cache-dependency-path: package-lock.json |
| 用 pnpm | setup-node 前加 pnpm/action-setup,cache: pnpm,步骤改 pnpm install --frozen-lockfile / pnpm build |
| 想免维护分支 | 改用官方 Artifact 方案(upload-pages-artifact + deploy-pages) |
| 想把部署日志收敛 | 删除 paths 过滤(全仓库任一改动都触发) |
5.9、常见报错排查
| 报错/现象 | 原因 | 解决 |
|---|---|---|
remote: Permission denied / push 失败 |
token 只读,无写权限 | 开 Read and write 或加 permissions: contents: write |
yarn.lock ... not found / 缓存不生效 |
cache-dependency-path 路径错 |
指向真实的锁文件路径(子目录要带前缀) |
command not found: yarn build |
working-directory 未设或路径错 |
设 working-directory: website |
| 部署成功但页面白屏 / 资源 404 | baseUrl 未按项目站点配置 |
改为 baseUrl: '/<repo>/' |
| Actions 没被触发 | 分支名或 paths 不匹配 |
核对 branches 与 paths |
| 下划线目录 404 | 缺 .nojekyll |
确保 static/.nojekyll 存在 |
| Node 版本不兼容 | Node 过旧 | 升到 Node 20+ |
5.10、注意事项(易踩坑)
- 分支名对齐:Taier 用
master,新仓库多为main,务必改对。 - 子目录站点三处同步:
working-directory、cache-dependency-path、publish_dir。 - 写权限:新版仓库默认 token 只读,必须显式开放。
baseUrl忘改:项目站点未设置会白屏、静态资源 404。paths过滤:仅在website/**变更时触发;文档目录不同需同步调整。- 本地替代方案:不接 CI 时,本地
yarn deploy(或npm run deploy)同样可发布到gh-pages分支。
5.11、所需配置 & CI 对接到开源项目根目录
问题引导:一个开源项目通常「源码 + 文档」共存,CI 与所需配置应该放在哪里、怎么对接,才能推送到主分支就自动发官网?
答案:CI 工作流与仓库级配置统一放在项目根目录,通过 paths / working-directory 指向文档站子目录即可,互不干扰。
(1)根目录文件树(推荐布局:站点在子目录)
my-open-source-project/ # ← 开源项目根目录
├── .github/
│ └── workflows/
│ └── deploy.yml # ✅ CI:放在「根目录」的 .github/workflows 下
├── website/ # 文档站工程(Docusaurus)
│ ├── docusaurus.config.js # 站点配置(url/baseUrl/org/project 必须改)
│ ├── sidebars.js
│ ├── package.json / yarn.lock
│ ├── docs/
│ ├── src/
│ └── static/
│ └── .nojekyll # 禁用 Jekyll(否则下划线目录 404)
├── src/ # 项目源码(后端/前端,与官网无关)
├── README.md
└── ...
要点:
.github/workflows/必须在仓库根目录(GitHub Actions 只扫描根目录的这个路径);放在website/里不会生效。- 文档站可以放在任意子目录(Taier 是
website/),由工作流的paths/working-directory/publish_dir指向它。 .nojekyll放在 Docusaurus 的static/(构建后会拷贝到产物根),不是放项目根。
(2)所需配置清单
| 配置 | 放置位置 | 是否必需 | 说明 |
|---|---|---|---|
deploy.yml |
项目根 .github/workflows/ |
✅ 必需 | CI 工作流,GitHub 只认根目录 |
docusaurus.config.js |
文档站子目录 | ✅ 必需 | url / baseUrl / organizationName / projectName |
static/.nojekyll |
文档站 static/ |
✅ 必需 | 禁用 Jekyll 处理 |
yarn.lock / package-lock.json |
文档站子目录 | ✅ 建议 | 配合 cache-dependency-path 与 --frozen-lockfile |
versions.json / i18n/ |
文档站子目录 | ⭕ 可选 | 多版本 / 多语言时需要 |
CNAME |
文档站 static/ |
⭕ 可选 | 绑定自定义域名时 |
(3)仓库端设置(3 项,缺一不可)
- Settings → Actions → General → Workflow permissions:选 Read and write(或工作流声明
permissions: contents: write); - Settings → Pages → Source:选 Deploy from a branch →
gh-pages/(root); - 确认触发分支(
master/main)与实际一致。
(4)根目录直用完整工作流
将下面文件保存为项目根目录的 .github/workflows/deploy.yml(把 website 换成你的文档站子目录;若站点就在根目录则整段去掉 paths 与 working-directory,并将 publish_dir 改为 ./build):
name: Deploy Docs to GitHub Pages
on:
push:
branches: [main] # ← 改成你的主分支(Taier 为 master)
paths: [website/**] # ← 仅文档站变更时触发;根目录站点可删
workflow_dispatch: # 支持手动触发
permissions:
contents: write # peaceiris 推送 gh-pages 需要写权限
concurrency:
group: pages
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
cache-dependency-path: website/yarn.lock # ← 指向文档站锁文件
- name: Build website
working-directory: website # ← 进入文档站子目录
run: |
yarn install --frozen-lockfile
yarn build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: website/build # ← 发布文档站产物
user_name: github-actions[bot]
user_email: 41898282+github-actions[bot]@users.noreply.github.com
重点:站点在子目录时,三处路径必须同时指向子目录——
cache-dependency-path、working-directory、publish_dir。漏改任意一处都会构建或发布失败。
(5)对接完成后的效果
git add . && git commit -m "ci: add pages deploy" && git push origin main
│
▼
仅当 website/** 变更 → 触发 Actions → 构建 → 推送 gh-pages → 官网更新
(改动后端源码不触发,避免误发)
六、总结梳理
问题引导:走完全流程后,我们该如何验证与复盘这套官网结构?
6.1、验证测试
新增一篇文档后,用以下闭环验证:
yarn start→ 本地预览,确认页面、侧边栏、图片正常;yarn build→ 确认无 死链报错(onBrokenLinks: "error");yarn serve→ 预览生产产物,确认资源路径正确;- 检查暗色模式切换、导航跳转、页脚链接。
6.2、结构本质:一句话记住
Taier 官网可高度概括为 「4 个配置 + 3 个目录」:
- 4 个配置:
docusaurus.config.js(总配置)、sidebars.js(导航树)、package.json(依赖命令)、babel.config.js(固定)。 - 3 个目录:
docs/(内容)、src/(首页与交互)、static/(静态资源)。
6.3、内容维护三步法
新增一篇文档 = 建 md → 注册 sidebars → 放图:
- 在对应
docs/子目录新建xxx.md,补title/sidebar_label; - 在
sidebars.js的对应分类items中加入'路径/xxx'; - 截图放
static/img/readme/,正文用/img/readme/xxx.png引用; npm start预览、npm run build校验死链。
注意:新增文档若忘记注册
sidebars.js,页面不会出现在侧边栏中。
6.4、改品牌 / 改首页指引
| 目标 | 改动位置 |
|---|---|
| 站点名/标语 | docusaurus.config.js 的 title / tagline |
| 部署路径 | url + baseUrl + organizationName + projectName |
| 导航/页脚 | themeConfig.navbar / themeConfig.footer |
| 首页文案/组件 | src/components/intro.jsx / features.jsx / case.jsx |
| 品牌色/Logo | src/css/custom.css 变量 + static/img/logo.svg / favicon.png |
6.5、复用结论
Taier 官网是一套 「配置驱动导航 + Markdown 承载内容 + React 定制首页」 的经典开源文档站范式。复用到新项目时,只需替换品牌配置、清空/改写 docs/ 内容、替换 static/img/ 资源,即可快速上线一个结构完整、支持暗色模式与搜索的官网文档站。
一句话总结:从「为什么选 Docusaurus」到「如何新增一页文档」,本质就是围绕
docusaurus.config.js+sidebars.js两个配置文件和docs/、src/、static/三个目录展开的工程化协作。
整理者:长路 时间:2026.9.29
评论区请在客户端页面查看