☰
从零搭建Pi蓝皮书:VitePress+GitHub+Cloudflare Pages全流程
2026/10/26 5:27:30 网站建设 项目流程

1. 缘起:为什么要折腾一本自己的 Pi 蓝皮书

第一次冒出“写一本 Pi 蓝皮书”的念头,是在连续被同一个问题问了不下二十遍之后。那段时间我在几个嵌入式社群里比较活跃,隔三差五就有人私信我:Pi 的板子到底怎么选、系统镜像烧录完第一件事做什么、GPIO 引脚怎么对应、跑一个传感器采集程序为什么总是报权限错误。问题本身都不复杂,但散落在各种聊天记录、论坛帖子和零散的笔记里,每次都要重新翻一遍,效率极低。

于是我想,与其一遍遍重复回答,不如把这些内容系统化地整理成一本“蓝皮书”——一本围绕 Pi 生态、从入门到进阶、结构清晰、可以持续更新的开源文档。这里的“Pi”我指的是以 Raspberry Pi 为代表的单板计算机生态,也包括各种兼容的国产替代板卡。之所以叫“蓝皮书”,是因为我希望它像一本随手可查的手册,而不是那种读完就忘的教程合集。

这个项目最终落地成了一个开源文档站点,技术栈用的是VitePress,托管在GitHub,部署走Cloudflare Pages。整套方案零成本、自动化、可协作,任何人 fork 之后改改配置就能变成自己的文档站。这篇文章我会把从零搭建的完整过程、每一步背后的取舍逻辑、以及我踩过的坑全部摊开讲清楚。适合谁看?如果你手头有一堆零散的技术笔记想整理成体系,或者想给团队/社群做一份长期维护的文档,又或者单纯想学一套现代化的静态站点工作流,这篇内容都能直接抄作业。

我先把最终形态说清楚,让你有个预期:一个支持全文搜索、暗色模式、侧边栏多级导航、代码高亮、自动部署的文档站,域名可以自定义,每次 push 到 GitHub 就自动构建上线,全程不花一分钱。下面进入正题。

2. 整体方案设计与技术选型拆解

2.1 为什么是 VitePress 而不是其他文档工具

文档站工具这几年卷得厉害,主流的几个选择我基本都试过。Docusaurus 功能全但配置重,主题定制要动 React 组件,对只想写文档的人来说心智负担偏高;GitBook 早期很好用,但后来重心转向商业化,本地化部署越来越别扭;MkDocs 基于 Python,插件生态不错,但前端交互和默认观感偏老派;至于各种在线文档平台,数据不在自己手里,导出和迁移都受制于人。

VitePress 打动我的点很直接:它基于 Vite 和 Vue 3,构建速度极快,Markdown 写起来就是纯 Markdown,几乎零配置就能跑起来,默认主题的排版和交互已经足够好看。更关键的是,它的配置就是一个.vitepress/config.js文件,想改导航、侧边栏、搜索、页脚,全在这一个文件里搞定,不需要理解复杂的插件机制。

我实测过一个中等规模的文档站,大概 80 个 Markdown 页面,VitePress 冷启动开发服务器不到 2 秒,热更新几乎是即时的。这个体验对写作者来说太重要了,因为你写文档的时候最怕的就是改一个字等半天才看到效果。

2.2 托管与部署:GitHub + Cloudflare Pages 的组合逻辑

代码托管选 GitHub 没什么好纠结的,开源协作的事实标准,Issue、PR、Actions 一整套流程都成熟。真正需要解释的是部署为什么选 Cloudflare Pages 而不是 GitHub Pages。

GitHub Pages 当然能用,而且和仓库天然集成。但它有两个让我最终放弃的点:一是构建队列偶尔会排队,尤其是免费账户,push 之后等几分钟才上线是常事;二是自定义域名配 HTTPS 的流程相对繁琐,而且国内访问速度不稳定。Cloudflare Pages 的免费额度对个人文档站来说绰绰有余,每月 500 次构建,每次构建速度快,全球 CDN 分发,自定义域名绑定后自动签发证书,整个流程顺滑得多。

提示:Cloudflare Pages 和 GitHub 仓库的连接是通过授权实现的,构建触发是自动的,你不需要在本地做任何额外操作,push 即部署。

2.3 内容组织策略:蓝皮书的结构怎么设计

工具选好了,接下来是内容架构。一本蓝皮书如果结构混乱,工具再好也白搭。我采用的是“三层结构”:顶层是大的板块(比如硬件认知、系统安装、编程入门、外设实战、项目案例),中间层是每个板块下的具体主题,底层是具体的操作页面。

对应到 VitePress 的配置,就是导航栏放顶层板块,侧边栏按板块分组展示中间层和底层。这里有个经验:侧边栏不要一次性展开所有层级,页面多了之后会非常长,用户滚动起来很累。VitePress 支持折叠分组,把每个板块做成可折叠的,默认只展开当前所在的板块,体验会好很多。

内容写作上我坚持一个原则:每个页面只解决一个问题,页面之间用相对链接互相引用。比如“GPIO 引脚说明”这个页面,会在“点亮第一颗 LED”和“读取按钮状态”两个页面里被引用。这样既避免了内容重复,又让读者能顺着链接自然深入。

3. 从零搭建:环境准备与项目初始化实操

3.1 本地环境准备与依赖安装

动手之前先把本地环境理清楚。你需要的东西不多:Node.js(建议 18 或更高版本)、一个顺手的编辑器(VS Code 就行)、Git。Node 版本这块我要多说一句,VitePress 对 Node 版本有要求,太老的版本会直接报错,用node -v确认一下,低于 18 的先升级。

安装依赖的过程很标准,但我想强调一个细节:初始化项目时不要用全局安装的方式,而是用npx或者本地 devDependency。原因是全局安装的版本容易和项目实际需要的版本冲突,尤其是你同时维护多个文档项目的时候。我踩过这个坑,全局装了一个版本,结果另一个项目跑不起来,排查了半天才发现是版本问题。

# 创建项目目录并进入 mkdir pi-bluebook && cd pi-bluebook # 初始化 package.json npm init -y # 本地安装 VitePress 作为开发依赖 npm install -D vitepress # 初始化 VitePress 的目录结构 npx vitepress init

执行vitepress init之后会有一系列交互式提问,问你文档放在哪个目录、站点标题是什么、要不要 TypeScript 配置等等。第一次搭建议选默认的docs目录,标题填你的蓝皮书名字,其他保持默认即可。这一步会自动生成.vitepress/config.js、index.md等基础文件。

3.2 目录结构规划与文件命名规范

初始化完成后,目录结构大概长这样:

pi-bluebook/ ├── docs/ │ ├── .vitepress/ │ │ └── config.js │ ├── index.md │ └── ... ├── package.json └── ...

我建议在docs下按板块建子目录,比如hardware/、system/、programming/、peripherals/、projects/。每个子目录里放该板块的 Markdown 文件。文件命名用英文小写加连字符,比如gpio-pinout.md、first-led.md。为什么不用中文文件名?因为 URL 里出现中文虽然现代浏览器能处理,但复制粘贴、分享链接的时候容易出现编码问题,英文命名更稳妥。

每个子目录里我还会放一个index.md作为该板块的入口页,简单介绍这个板块涵盖什么内容,然后列出下面的子页面链接。这样用户从导航点进来不会直接落到某个具体页面,而是先看到板块概览,体验更符合阅读习惯。

3.3 核心配置文件逐项解读

config.js是整个站点的中枢,我把关键配置拆开讲。首先是站点基础信息:

export default defineConfig({ title: "Pi 蓝皮书", description: "从入门到进阶的 Pi 生态实践手册", lang: "zh-CN", base: "/", // ... })

base这个字段要特别注意。如果你部署在自定义域名的根路径下,保持/就行;如果部署在子路径(比如username.github.io/pi-bluebook/),这里必须改成/pi-bluebook/,否则所有静态资源都会 404。我见过太多人卡在这个问题上,页面能打开但样式全丢,就是base没配对。

接下来是主题配置,重点是导航和侧边栏:

themeConfig: { nav: [ { text: "首页", link: "/" }, { text: "硬件认知", link: "/hardware/" }, { text: "系统安装", link: "/system/" }, { text: "编程入门", link: "/programming/" }, { text: "外设实战", link: "/peripherals/" }, ], sidebar: { "/hardware/": [ { text: "硬件认知", items: [ { text: "板卡选型对比", link: "/hardware/board-selection" }, { text: "GPIO 引脚说明", link: "/hardware/gpio-pinout" }, ], }, ], // 其他板块类似 }, }

侧边栏我用了按路径分组的方式,每个板块有独立的侧边栏配置。这样做的好处是,当用户浏览某个板块时,侧边栏只显示该板块的内容,不会把整本书的目录都堆在一边,视觉上清爽很多。

搜索功能 VitePress 内置了本地搜索,只需要在主题配置里加一行search: { provider: 'local' },它会自动为所有页面建立索引,支持中文分词。这个功能对文档站来说是刚需,读者不可能每次都靠导航找内容。

4. 内容填充与写作规范落地

4.1 蓝皮书内容框架的搭建方法

框架不是拍脑袋想出来的,我的做法是先做一次“问题收集”。把过去半年里被问过的问题、自己在实践中卡过的点、论坛里高频出现的求助帖,全部列在一个表格里。然后对这些条目做归类,你会发现它们天然会聚成几个大类,这些大类就是板块的雏形。

归类完之后,每个大类下面按“认知—操作—进阶”的顺序排列页面。认知类页面讲清楚是什么、为什么,操作类页面给出可复现的步骤,进阶类页面讲优化、排错和扩展。这个顺序符合学习规律,读者从零开始也能顺着走下来。

我建议在正式写之前,先把这个框架用 Markdown 列成一个outline.md,放在仓库根目录。这样你对整本书的规模有个直观感受,也方便后续调整。框架定下来之后再动笔,比边写边想效率高得多。

4.2 Markdown 写作中的实用技巧与约定

VitePress 的 Markdown 支持一些扩展语法,用好了能大幅提升文档质量。代码块支持行高亮,比如你想强调某一行,可以在语言后面加{2}表示高亮第二行。这个在讲解配置的时候特别有用,读者一眼就能看到关键行。

export default defineConfig({ base: "/pi-bluebook/", // 这一行会被高亮 title: "Pi 蓝皮书", })

自定义容器也是我常用的功能。VitePress 支持tip、warning、danger、info几种容器,用来标注提示、警告、危险操作和补充信息。比如讲烧录镜像的时候,我会用danger容器强调“写错设备会清空硬盘数据”,这种视觉上的强提醒比普通段落有效得多。

注意:自定义容器的语法是三个冒号加类型名,结束也是三个冒号,别写错了,写错的话渲染出来就是一堆乱码。

还有一个约定是关于图片的。所有图片统一放在docs/public/images/目录下,Markdown 里用绝对路径引用,比如/images/gpio-pinout.png。这样不管页面在哪个子目录,图片都能正确加载。图片命名同样用英文小写加连字符,和页面文件命名规范保持一致。

4.3 让文档可维护:版本管理与更新节奏

文档写起来容易,维护起来难。我的做法是给每个页面加一个“最后更新”的元信息,VitePress 可以通过 Git 提交记录自动生成这个信息,配置里开启lastUpdated: true就行。读者看到页面是最近更新过的,信任感会强很多。

更新节奏上,我不追求一次性写完所有内容,而是采用“滚动发布”的方式。先把框架搭好,每个页面放一个占位内容,然后每周固定时间补充一两个页面。这样站点始终是可用的,不会出现“半成品”的状态。同时我会在仓库的 Issue 里维护一个“待办清单”,读者可以提需求,我按优先级排期。

5. 部署上线:GitHub 与 Cloudflare Pages 联动

5.1 推送到 GitHub 的完整流程

本地内容写得差不多了,就该推到 GitHub 了。先在 GitHub 上新建一个仓库,建议设为 Public,这样别人可以 fork 和提 PR。然后本地关联远程仓库并推送:

git init git add . git commit -m "init: 蓝皮书框架搭建完成" git branch -M main git remote add origin https://github.com/你的用户名/pi-bluebook.git git push -u origin main

这里有个细节:.vitepress目录下的cache和dist不要提交,在.gitignore里加上。cache是构建缓存,dist是构建产物,这两个都不应该进版本库,否则仓库会越来越大,而且每次构建都会产生大量无意义的 diff。

5.2 Cloudflare Pages 的构建配置详解

在 Cloudflare 控制台里选择 Pages,然后连接你的 GitHub 仓库。连接过程中会让你配置构建参数,这几个参数必须填对:

配置项值说明
框架预设VitePress选这个会自动填充部分参数
构建命令npm run docs:build对应 package.json 里的脚本
输出目录docs/.vitepress/distVitePress 默认构建输出位置
Node 版本18 或更高在环境变量里设置NODE_VERSION

构建命令这块要和你package.json里的 scripts 对应上。VitePress 初始化时一般会生成docs:dev、docs:build、docs:preview三个脚本,构建用docs:build。输出目录千万别填错,填成docs或者dist都会导致部署后页面 404。

配置完成后,每次你 push 到 main 分支,Cloudflare 会自动拉取代码、执行构建、部署到 CDN。构建日志在控制台里能实时看到,如果构建失败,日志里会明确告诉你哪一步出错,排查起来很方便。

5.3 自定义域名与 HTTPS 配置

Cloudflare Pages 默认会给你一个xxx.pages.dev的域名,能直接用。如果你有自己的域名,在 Pages 项目的“自定义域”里添加即可。添加后 Cloudflare 会引导你做 DNS 解析,通常是在你的域名服务商那里加一条 CNAME 记录指向xxx.pages.dev。

证书是自动签发的,不需要你手动申请。这里有个经验:DNS 解析生效需要时间,短则几分钟,长则几小时,别刚添加完就急着访问,看到证书还没生效就以为配置错了。等一会儿再试,或者用dig命令查一下解析状态。

提示:如果你用的是 Cloudflare 自己管理的域名,整个过程会更简单,因为 DNS 和 Pages 在同一个平台,解析几乎是即时的。

6. 常见问题与排查技巧实录

6.1 构建失败的高频原因速查

部署过程中最容易出问题的就是构建环节。我整理了一张速查表,覆盖了我遇到过的绝大多数情况:

现象可能原因排查方向
构建报错找不到命令构建命令填错检查 package.json 的 scripts
构建成功但页面 404输出目录填错确认是docs/.vitepress/dist
页面能开但样式丢失base配置错误子路径部署要改 base
构建超时依赖过多或 Node 版本低升级 Node,精简依赖
中文搜索失效搜索未启用或索引未生成检查 search 配置

构建失败的时候,第一件事是看日志。Cloudflare 的构建日志很详细,从拉取代码到安装依赖到执行构建,每一步都有输出。错误信息通常在最后几行,仔细读一遍基本能定位问题。

6.2 本地预览与线上不一致怎么办

有时候本地npm run docs:dev看着好好的,部署上去就不对。这种情况八成是base的问题。本地开发服务器默认跑在根路径,而线上可能部署在子路径,两者的资源引用方式不一样。解决办法是在本地也用npm run docs:build加npm run docs:preview来预览,这个预览走的是构建后的产物,和线上环境一致,能提前发现问题。

另一个常见原因是缓存。Cloudflare 的 CDN 会缓存静态资源,你更新了内容但访问到的还是旧版本。这时候可以在 Cloudflare 控制台里手动清除缓存,或者在 URL 后面加个查询参数强制刷新。不过正常情况下,每次部署都会生成新的资源哈希,缓存问题不会太频繁。

6.3 内容协作中的冲突处理经验

如果有多人一起维护这本蓝皮书,Git 冲突是绕不开的。我的经验是:把内容拆得足够细,每个人负责不同的页面,冲突概率会大幅降低。如果确实要改同一个文件,约定好先 pull 再改,改完尽快 push,减少并行修改的时间窗口。

对于 PR 的处理,我建议开启 Cloudflare Pages 的预览部署功能。每个 PR 会自动生成一个独立的预览链接,reviewer 可以直接在预览站点上看效果,确认没问题再合并。这个功能对文档协作来说非常实用,避免了“合并后才发现排版乱了”的尴尬。

7. 后续扩展与个人实践体会

这套方案跑通之后,能扩展的方向其实很多。比如可以接入评论系统,让读者在页面底部直接反馈问题;可以加一个“编辑此页”的链接,指向 GitHub 上对应的源文件,降低贡献门槛;还可以用 GitHub Actions 做一些自动化检查,比如链接有效性检测、Markdown 格式校验,保证文档质量。

我自己在实际维护过程中最大的体会是:文档的价值不在于写得多全,而在于持续更新。一本三个月没动过的蓝皮书,读者很快就会失去信任。所以与其追求一次写完,不如建立一个可持续的更新机制,哪怕每周只补充一个小节,长期积累下来也是可观的。

另外一个小技巧:我会在每篇文档的末尾留一个“待补充”的标记,提醒自己这里还有内容没写完。这个标记不会展示给读者,只是我自己的备忘。等补充完了再删掉。这个习惯让我不会遗漏重要的内容点,也让文档的完善过程有迹可循。

如果你也想做一本自己的蓝皮书,我的建议是别想太多,先把框架搭起来,写第一篇内容,推上去看到线上效果。那个“自己的文档站真的跑起来了”的瞬间,会给你继续写下去的动力。剩下的,就是一篇一篇往里填的事了。

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

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

立即咨询