资讯动态

从零搭建Pi蓝皮书:VitePress+GitHub+Cloudflare Pages静态站点实战

发布时间:2026/10/26 21:02:54 来源:尧图企业网站定制
1. 缘起为什么要折腾一本自己的 Pi 蓝皮书1.1 一个很现实的问题资料散落在各处玩 Pi 这块板子的人应该都有同感——资料不是没有而是太散了。官方文档是一份社区帖子是一份各种博客教程又是一份而且版本对不上、引脚图对不上、系统镜像对不上的情况太常见了。我自己的习惯是每次调通一个外设、踩过一个坑就随手记在备忘录里结果半年下来备忘录里躺着几十条零散笔记想找的时候翻半天想分享给别人的时候又得重新整理一遍。真正让我下决心做这个项目的是帮一个刚入门的朋友配环境。他问我“Pi 上跑那个采集程序到底要装哪些依赖”我翻了三个网页、两个仓库的 README才把完整步骤拼出来。那一刻我就想与其每次现拼不如把这些东西沉淀成一本结构化的、能持续更新的电子书。这就是“Pi 蓝皮书”的起点——它不是官方文档的替代品而是一个个人视角的、经过实测的、可复现的知识库。1.2 为什么选“开源 静态站点”这条路做知识库的方案其实很多Notion、语雀、飞书文档都能写为什么非要折腾开源静态站点我的考量有三点。第一是长期可维护性。第三方平台随时可能改版、限流、甚至关停我写的东西如果绑死在某个平台上迁移成本极高。而 Markdown 文件存在自己的 Git 仓库里十年后照样能打开这是最朴素的“数据主权”思维。第二是协作与版本管理。开源项目最大的价值在于别人可以提 Issue、发 PR。我写错了一个引脚定义读者可以直接改改完还有记录可查。这种“众包纠错”机制是任何单人维护的文档都比不了的。第三是部署成本几乎为零。静态站点生成器 免费托管平台这套组合已经非常成熟。VitePress 负责把 Markdown 编译成站点GitHub 负责存代码和触发构建Cloudflare Pages 负责全球分发。整条链路下来我只需要为域名付一点钱其余全是免费的。对于个人项目来说这个性价比没有理由拒绝。提示如果你只是想快速记录不想折腾构建流程那静态站点确实有点“重”。但只要你有“长期维护 对外分享 接受协作”这三个需求中的任意两个这套方案就是值得的。1.3 这本蓝皮书适合谁看我把目标读者分成三类。第一类是刚拿到 Pi 的新手需要一份从烧录系统到点亮第一个 LED 的完整路径不用在论坛里大海捞针。第二类是有一定基础但被某个具体问题卡住的开发者比如 I2C 设备扫描不到、串口权限报错这类问题蓝皮书里会有专门的排查章节。第三类是想自己搭一套知识库的人哪怕你不玩 Pi这套“VitePress GitHub Cloudflare Pages”的建站流程本身就可以直接抄走。所以这篇文章我会分两条线讲一条是内容层面蓝皮书里到底写什么、怎么组织另一条是工程层面这套站点是怎么从零搭起来、怎么部署、怎么持续更新的。两条线交织着讲因为内容结构其实会影响技术选型技术选型反过来也约束了内容怎么组织。2. 整体架构设计内容与技术怎么配合2.1 内容结构从“线性教程”到“网状知识库”一开始我想按传统教程那样第一章讲环境、第二章讲 GPIO、第三章讲通信协议线性往下排。但写了两章就发现不对劲——真实的使用场景不是线性的。一个人可能今天想调 SPI 屏幕明天想接个传感器后天想跑个摄像头。如果所有内容都塞进一条主线读者每次都要从头翻。后来我改成了**“基础 专题 速查”三层结构**。基础层是必读的入门路径保证新手能跑通专题层是按功能模块拆开的独立章节每个章节自成闭环可以单独阅读速查层是引脚表、常用命令、报错对照表这类高密度信息专门给老手用。这种结构的好处是新手有路径可循老手能直接跳到需要的部分不用被“教程顺序”绑架。在 VitePress 里这套结构对应的是侧边栏的分组配置。基础层放一组专题层每个模块一个折叠组速查层单独一组。读者打开站点左边一眼就能看到全貌而不是被一条长长的目录吓到。2.2 技术选型为什么是 VitePress 而不是别的静态站点生成器这个赛道选择其实不少。我对比过几个主流方案最后选 VitePress理由如下表。方案优势我放弃的原因VitePress基于 Vite构建快Markdown 扩展强默认主题适合文档无明显短板最终选择Docusaurus生态成熟插件多支持多语言构建偏重配置项多个人项目有点杀鸡用牛刀MkDocsPython 生态配置简单主题定制不如 VitePress 灵活前端交互弱一些Hugo构建极快单二进制模板语法学习成本高改主题比较痛苦GitBook开箱即用界面漂亮免费版限制多数据在别人手里不符合“数据主权”原则VitePress 最打动我的点是**“Markdown 优先 按需增强”**。我写内容的时候就是纯 Markdown需要交互的时候再引入 Vue 组件不需要为了写文档去学一套复杂的框架。而且它的默认主题对代码块、表格、侧边栏的支持已经足够好几乎不用改样式就能直接上线。另一个隐性优势是构建速度。VitePress 底层是 Vite热更新几乎是瞬时的。我写长文档的时候左边改右边立刻能看到效果这种即时反馈对写作体验的提升非常大。相比之下有些方案改一行要等好几秒重新构建写起来就很烦躁。2.3 部署链路GitHub 存代码Cloudflare Pages 做分发部署这块我选的是 GitHub Cloudflare Pages 的组合。GitHub 负责版本管理和触发构建Cloudflare Pages 负责编译和全球 CDN 分发。整个流程是这样的本地写完 Markdownpush 到 GitHub 仓库Cloudflare Pages 监听到 push 事件自动拉取代码、执行构建命令、把产物部署到 CDN几十秒后线上就更新了。为什么不用 GitHub Pages主要是两个原因。一是构建速度和稳定性GitHub Pages 的构建队列有时候会排队Cloudflare Pages 相对更稳定。二是自定义域名和 HTTPSCloudflare 的配置更顺手而且免费额度对个人项目完全够用。当然GitHub Pages 也完全能用如果你不想多注册一个平台直接用 GitHub Pages 也没问题只是构建体验上略有差异。注意Cloudflare Pages 构建时需要指定 Node 版本。VitePress 对 Node 版本有要求如果平台默认版本太低构建会直接失败。这个坑我踩过后面会详细讲怎么解决。3. 从零搭建VitePress 站点的完整实操3.1 环境准备与项目初始化先说环境。本地需要 Node.js建议用 18 或 20 的 LTS 版本。我一开始用的是系统自带的旧版本结果npm install各种报错后来用 nvm 切到 20 就一切正常了。所以第一步确认你的 Node 版本node -v # 期望输出 v18.x 或 v20.x如果版本不对用 nvm 装一个nvm install 20 nvm use 20然后初始化项目。我习惯先建一个空目录再在里面初始化mkdir pi-bluebook cd pi-bluebook npm init -y npm install -D vitepress装完之后用 VitePress 自带的初始化命令生成基础结构npx vitepress init这个命令会问你几个问题站点放在哪个目录、标题叫什么、描述是什么、要不要默认主题。我一般选./docs作为内容目录标题填“Pi 蓝皮书”主题选默认。生成完之后目录结构大概是这样pi-bluebook/ ├── docs/ │ ├── .vitepress/ │ │ └── config.mts │ ├── index.md │ └── ... ├── package.json └── ...config.mts是整个站点的核心配置文件侧边栏、导航栏、搜索、主题样式都在这里改。后面会详细讲怎么配。3.2 目录组织与侧边栏配置内容目录我按前面说的三层结构来组织docs/ ├── index.md # 首页 ├── guide/ # 基础层 │ ├── getting-started.md │ ├── system-install.md │ └── first-program.md ├── topics/ # 专题层 │ ├── gpio.md │ ├── i2c-spi.md │ ├── camera.md │ └── network.md └── reference/ # 速查层 ├── pinout.md ├── commands.md └── errors.md对应的侧边栏配置写在config.mts里export default defineConfig({ title: Pi 蓝皮书, description: 一本经过实测的 Pi 使用手册, themeConfig: { nav: [ { text: 首页, link: / }, { text: 入门, link: /guide/getting-started }, { text: 专题, link: /topics/gpio }, { text: 速查, link: /reference/pinout } ], sidebar: { /guide/: [ { text: 入门路径, items: [ { text: 开箱与准备, link: /guide/getting-started }, { text: 系统烧录, link: /guide/system-install }, { text: 第一个程序, link: /guide/first-program } ] } ], /topics/: [ { text: 功能专题, items: [ { text: GPIO 控制, link: /topics/gpio }, { text: I2C 与 SPI, link: /topics/i2c-spi }, { text: 摄像头, link: /topics/camera }, { text: 网络配置, link: /topics/network } ] } ], /reference/: [ { text: 速查手册, items: [ { text: 引脚定义, link: /reference/pinout }, { text: 常用命令, link: /reference/commands }, { text: 报错对照, link: /reference/errors } ] } ] } } })这里有个细节值得说侧边栏按路径前缀分组。/guide/下的页面自动用第一组侧边栏/topics/下的用第二组。这样每个大板块的侧边栏是独立的读者在专题区不会看到入门区的目录视觉上更聚焦。3.3 本地预览与写作工作流配置好之后启动本地开发服务器npx vitepress dev docs默认在http://localhost:5173打开。这时候你改任何 Markdown 文件浏览器都会热更新几乎无延迟。我的写作工作流是这样的左边开编辑器写 Markdown右边开浏览器看效果写完一段就扫一眼渲染结果确认代码块、表格、链接都正常。写内容的时候有几个 VitePress 特有的语法值得掌握。代码块支持行高亮bash npm install vitepress # [!code highlight] 还支持代码组把多个语言的实现放在一个标签页里切换::: code-group python print(hello) javascript console.log(hello) :::这些语法在写“同一功能不同语言实现”的章节时特别有用读者不用在多个代码块之间来回滚动。实操心得写长文档时我习惯先列大纲再填内容。大纲阶段就用##和###把结构定下来然后逐个填充。这样能避免写着写着结构跑偏也方便后期调整章节顺序——VitePress 的侧边栏是手动配的结构清晰的话改起来很快。4. 部署上线GitHub 与 Cloudflare Pages 的联动4.1 推送到 GitHub 与仓库结构本地写完之后第一步是推到 GitHub。先在 GitHub 上建一个空仓库然后本地关联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这里有个容易忽略的点.gitignore一定要配好。node_modules和docs/.vitepress/dist、docs/.vitepress/cache这些目录不应该进仓库否则仓库会变得很大构建也会变慢。我的.gitignore长这样node_modules/ docs/.vitepress/dist/ docs/.vitepress/cache/ .DS_Store *.log仓库结构保持“源码 配置”的干净状态构建产物交给平台去生成这是静态站点部署的基本原则。4.2 Cloudflare Pages 的构建配置在 Cloudflare Pages 里新建项目关联刚才的 GitHub 仓库。关键在构建配置这几项配置项值说明框架预设VitePress选了这个会自动填下面两项构建命令npm run docs:build对应 package.json 里的脚本输出目录docs/.vitepress/distVitePress 默认产物路径Node 版本20通过环境变量指定package.json里的脚本要提前配好{ scripts: { docs:dev: vitepress dev docs, docs:build: vitepress build docs, docs:preview: vitepress preview docs } }Node 版本这个坑我必须重点说。Cloudflare Pages 默认的 Node 版本可能比较旧而 VitePress 新版本要求 Node 18 以上。如果不管它构建日志里会报Unsupported engine或者各种语法错误。解决办法是在项目根目录加一个.node-version文件内容就一行20或者在 Cloudflare Pages 的环境变量里加NODE_VERSION20。两个方法都行我用的前者因为跟着仓库走换平台也不用重新配。4.3 自定义域名与 HTTPS构建成功后Cloudflare 会给一个xxx.pages.dev的临时域名。想用自己的域名在 Pages 项目的“自定义域”里添加即可。如果域名也托管在 Cloudflare基本是点几下就完事DNS 记录自动配好HTTPS 证书自动签发。如果域名不在 Cloudflare就需要手动加一条 CNAME 记录指向xxx.pages.dev。这时候要注意CNAME 记录的主机名不要和根域名冲突。我一般用docs.xxx.com这种子域名配置起来最省事。根域名做跳转或者单独处理避免和邮箱等其他服务打架。注意DNS 生效有延迟刚配完可能访问不了等几分钟到几小时都正常。别急着反复改配置先等一等用dig或在线工具查一下解析结果再说。5. 内容运营让蓝皮书持续生长5.1 写作规范让每篇文档都能被复现站点搭起来只是开始真正决定蓝皮书价值的是内容质量。我给自己定了几条写作规范这里分享出来供参考。第一条是每个操作步骤都要有前置条件。比如写“配置 I2C”不能上来就说“运行raspi-config”得先说清楚“假设你已经烧录好系统并能 SSH 登录”。读者卡住的时候往往是卡在前置条件上而不是当前步骤。第二条是命令和输出成对出现。只给命令不给预期输出读者不知道自己跑对没有。我习惯把关键命令的预期输出也贴出来哪怕只是截取几行读者一对比就知道对不对。第三条是报错信息原文保留。很多人写文档喜欢把报错“翻译”成中文但读者搜索的时候用的是英文原文。所以我在排查章节里会保留完整的英文报错再在下面解释含义和解决办法。这样既方便搜索又不影响理解。5.2 接受协作Issue 和 PR 的处理方式开源项目最怕的是“开了源但没人参与”。我的做法是降低参与门槛。仓库里放一个CONTRIBUTING.md写清楚怎么提 Issue、怎么改文档、怎么本地预览。哪怕只是改一个错别字流程也要写得明明白白。Issue 模板我分了三种内容纠错、内容补充、站点问题。每种模板带几个必填项比如“涉及页面”“当前描述”“期望描述”。这样提上来的 Issue 信息完整处理起来效率高很多。PR 的处理原则是小步快跑。小的修改直接合并大的改动先在 Issue 里讨论清楚再动手。我遇到过有人一口气提了几百行的 PR结果方向和我规划的不一致最后只能关掉双方都挺尴尬。所以现在我会在 Issue 里先对齐思路确认了再让对方动手。5.3 持续更新把零散笔记变成正式章节蓝皮书的内容不是一次性写完的而是持续生长的。我的做法是维护一个“草稿区”平时遇到新问题、新技巧先随手记在草稿区格式不用讲究能看懂就行。每隔一段时间把草稿区里成熟的内容整理成正式章节补上前置条件、预期输出、报错排查然后合并进主目录。这个流程的好处是写作压力小。不用每次都憋一篇完整文档而是先记碎片再定期整理。整理的过程本身也是复习很多当时没想明白的问题过段时间回头看就清楚了。实操心得我在草稿区用TODO标记待补充的内容用FIXME标记可能有误的内容。整理的时候先搜这两个关键词一目了然。这个习惯是从写代码那边带过来的用在文档维护上同样好使。6. 常见问题与排查实录6.1 构建失败Node 版本与依赖问题构建失败是部署环节最常见的问题我整理了一个速查表。报错关键词可能原因解决办法Unsupported engineNode 版本过低加.node-version文件指定 20Cannot find module依赖没装全检查package.json本地npm install后重新提交 lock 文件Build script returned non-zero构建命令写错确认是npm run docs:build而不是npm run buildOutput directory not found输出目录配错确认是docs/.vitepress/dist构建超时依赖太多或网络慢精简依赖或换用更快的镜像源这里重点说Cannot find module这个。有一次我本地跑得好好的推到 Cloudflare 就报模块找不到。查了半天发现是package-lock.json没提交平台按package.json重新解析依赖装出来的版本和本地不一致。解决办法很简单把 lock 文件一起提交保证本地和平台的依赖树完全一致。6.2 页面 404路径与大小写问题静态站点部署后 404十有八九是路径问题。VitePress 的链接是大小写敏感的本地开发时可能不觉得因为有些系统文件系统不区分大小写但部署到 Linux 环境就暴露了。比如你写[链接](/guide/Getting-Started)但实际文件是getting-started.md本地可能能打开线上就 404。解决办法是统一用小写加连字符命名文件链接也照着写。我现在的习惯是文件名全小写单词之间用-连接链接直接复制文件名避免手打出错。另一个常见原因是侧边栏链接和实际路径不匹配。侧边栏里写的是/guide/getting-started但文件放在/guide/basics/getting-started.md路径就对不上。改配置的时候一定要对着实际目录结构核对一遍。6.3 样式异常主题定制与缓存有时候改了样式本地生效线上不生效。这通常是缓存导致的。Cloudflare 的 CDN 会缓存静态资源浏览器也会缓存。解决办法是强制刷新CtrlShiftR或者在 Cloudflare 后台清除缓存。如果样式本身就不对那可能是主题定制的方式有问题。VitePress 的默认主题定制要通过.vitepress/theme/index.ts来扩展直接改node_modules里的文件是没用的因为构建时会重新安装依赖。正确的做法是// docs/.vitepress/theme/index.ts import DefaultTheme from vitepress/theme import ./custom.css export default { extends: DefaultTheme }然后在custom.css里写覆盖样式。这样构建时会自动应用而且升级 VitePress 版本也不会丢。6.4 搜索不生效本地搜索的配置要点VitePress 支持本地搜索不需要接第三方服务。开启方式是在config.mts里加themeConfig: { search: { provider: local } }但有个坑本地搜索只索引构建后的内容。开发模式下搜索可能不全要构建一次才能看到完整效果。另外如果内容里有大量代码块搜索索引会变大首次加载会慢一点。这个权衡看个人取舍对文档站点来说本地搜索的便利性远大于那点加载开销。7. 我在这套流程里踩过的坑7.1 别在内容还没成型时过度折腾样式我一开始花了不少时间调主题颜色、改字体、加动画结果内容没写几篇。后来想明白了文档站点的核心是内容样式够用就行。VitePress 默认主题已经很好看了与其花时间调 CSS不如多写两篇实测文档。现在我的原则是样式问题攒一批再统一改不打断写作节奏。7.2 图片资源要提前规划Pi 相关的文档少不了接线图、实物照片。图片放哪里、怎么引用最好一开始就定好。我的做法是在docs/public/下建一个images目录所有图片放这里引用的时候用绝对路径/images/xxx.png。这样不管文档在哪个子目录图片路径都不会错。图片体积也要注意。手机拍的照片动辄几 MB直接扔进仓库会让仓库膨胀得很快。我一般先用工具压缩到 200KB 以内再提交清晰度够看就行。毕竟读者看的是接线方式不是摄影作品。7.3 版本管理内容也要打标签蓝皮书里的内容是有时效性的。比如某个系统版本的配置方法过几个版本可能就变了。我的做法是在文档里标注适用版本比如“本文基于系统版本 X 实测”。如果后来版本变了旧内容不删而是加一个提示框说明“此方法适用于旧版本新版本请参考 XX”。这样处理的好处是老读者回来查旧内容还能找到新读者也不会被过时信息误导。文档不是代码不需要“最新版本覆盖旧版本”保留历史反而更有价值。8. 后续可以怎么扩展这套框架搭起来之后能扩展的方向其实很多。我目前规划了几个一是加一个示例代码仓库文档里讲原理仓库里放可直接运行的完整代码两者互相引用二是加一个版本对比页把不同系统版本的差异列成表格方便读者快速定位三是接入评论系统让读者能在具体页面下提问问题沉淀在对应章节旁边比散落在 Issue 里更好找。技术层面VitePress 还支持多语言、全文搜索优化、PWA 离线访问这些特性等内容量上来了再逐步加。现在的原则是先把内容做扎实功能按需增加避免为了用而用把站点搞得花里胡哨却没人看。如果你也想做一本自己的蓝皮书我的建议是别等“准备好”再开始。先建仓库、先写第一篇、先部署上线哪怕只有三页内容。上线之后你才会有真实的反馈才知道下一步该写什么。我最初那版只有五页现在慢慢长到了几十页这个过程本身就是最大的收获。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑