1. 缘起:为什么我要折腾一本自己的 Pi 蓝皮书
第一次接触树莓派是在一个二手论坛上,花两百块收了一块 3B+,卖家附赠一张 16G 的卡,说"系统已经烧好了,插电就能用"。结果我插上电,屏幕黑着,网口灯闪了两下就灭了。折腾了整整一个周末,才搞明白是电源供电不足——5V 2A 的充电头带不动那块板子。这件事让我意识到一个问题:关于树莓派的资料,网上不是没有,而是太散了。散落在各种论坛帖、博客、视频评论区里,你搜一个问题,能翻出二十个版本,其中十五个是过时的,三个是抄来抄去的,剩下两个才勉强能用。
后来我在 GitHub 上看到有人用 VitePress 搭文档站,界面干净,搜索快,还能直接部署到 Cloudflare Pages,免费额度对个人项目完全够用。我就想,为什么不把这几年来踩过的坑、验证过的配置、写过的脚本,整理成一本结构化的"蓝皮书"?不是那种官方文档的翻译搬运,而是真正从实操角度出发,记录每一步为什么这么做、不这么做会怎样。
这个项目从零开始,核心工具链就四样:Node.js做运行时,VitePress做静态站点生成,GitHub做代码托管和版本管理,Cloudflare Pages做自动化部署。听起来简单,但每一步都有细节。比如 Node.js 版本选哪个、VitePress 的 base URL 怎么配、GitHub 在国内网络环境下怎么稳定访问、Cloudflare Pages 的构建命令和输出目录怎么填——这些在官方文档里往往一笔带过,但实际操作时卡住你的恰恰就是这些。
这篇文章适合两类人:一类是手里有树莓派或者想入手树莓派,但被各种零散教程搞晕的;另一类是想用 VitePress 搭一个属于自己的知识库或文档站,但不确定从哪开始的。我会把整个流程拆开,从环境准备到部署上线,每一步都给出具体的命令、配置和参数解释,同时穿插我实际踩过的坑和验证过的技巧。你不需要有前端经验,但需要有一台能联网的电脑和一点折腾的耐心。
2. 整体设计与技术选型:为什么是这套组合
2.1 核心需求拆解:我要的到底是什么
在动手之前,我先问自己三个问题:第一,这本蓝皮书是给谁看的?第二,它需要具备哪些功能?第三,我打算投入多少维护成本?
第一个问题的答案决定了内容深度。如果是给完全没接触过树莓派的人看,那就要从"什么是 GPIO"讲起;如果是给有一定基础的开发者看,那重点应该放在系统调优、外设驱动、自动化脚本这些进阶内容上。我最终定位是"从入门到能独立完成一个完整项目",所以内容覆盖了基础操作、常见外设、网络配置、服务部署这几个模块。
第二个问题决定了技术选型。我需要的是:静态页面、快速搜索、Markdown 写作、自动部署、自定义域名。不需要的是:用户登录、数据库、后台管理。这就排除了 WordPress、Ghost 这类动态 CMS,也排除了 Notion、语雀这类托管平台——前者太重,后者数据不在自己手里。
第三个问题决定了工具链的复杂度。我不想每次更新内容都要手动上传服务器,也不想为了一个文档站去学 Docker 和 Nginx 配置。所以自动化部署是刚需,而且最好是推送到 GitHub 就自动触发构建。
这里有个经验:很多人一开始就想搞"大而全",结果光配置环境就耗掉一周,内容一个字没写。我的建议是先跑通最小闭环——本地能预览、推送到 GitHub、自动部署上线——然后再往里填内容。
2.2 为什么选 VitePress 而不是 Hexo 或 Docusaurus
静态站点生成器这个领域,选择其实不少。我试过 Hexo,也试过 Docusaurus,最后落在 VitePress 上,原因有三个。
第一是构建速度。VitePress 基于 Vite 构建,冷启动基本在秒级。我实测过,同样一百多篇 Markdown 文档,Hexo 首次生成要四十多秒,VitePress 不到五秒。这个差距在内容多了之后会非常明显,尤其是你写一段就想预览一下效果的时候,等待时间直接决定写作节奏。
第二是默认主题的完成度。VitePress 的默认主题自带侧边栏、导航栏、本地搜索、暗色模式、代码高亮、目录锚点,这些开箱即用。Hexo 需要装一堆插件,Docusaurus 配置项太多,而 VitePress 的配置文件结构非常直观,改起来不费劲。
第三是 Markdown 扩展能力。VitePress 支持在 Markdown 里直接写 Vue 组件,这意味着你可以在文档里嵌入交互式示例。比如讲 GPIO 的时候,可以直接放一个引脚图组件,鼠标悬停显示功能说明。这个能力在写硬件教程时特别有用。
当然,VitePress 也不是没有缺点。它的插件生态比 Hexo 小,主题定制需要懂一点 Vue。但对我来说,默认主题已经够用,偶尔改个样式用 CSS 变量覆盖就行,不需要深入 Vue 开发。
2.3 部署方案对比:Cloudflare Pages 凭什么胜出
部署静态站点,常见的选择有 GitHub Pages、Vercel、Netlify、Cloudflare Pages。我四个都用过,最后选 Cloudflare Pages,理由如下表:
| 平台 | 免费额度 | 构建速度 | 自定义域名 | 国内访问 | 配置复杂度 |
|---|---|---|---|---|---|
| GitHub Pages | 1GB 存储,100GB 流量/月 | 较慢,排队明显 | 支持 | 不稳定 | 低 |
| Vercel | 100GB 流量/月 | 快 | 支持 | 一般 | 低 |
| Netlify | 100GB 流量/月,300 构建分钟 | 快 | 支持 | 一般 | 低 |
| Cloudflare Pages | 无限请求,500 次构建/月 | 很快 | 支持 | 相对较好 | 低 |
Cloudflare Pages 的优势在于:构建次数给得多,每月 500 次对个人项目绰绰有余;全球 CDN 节点多,国内访问虽然不算快但至少能打开;和 GitHub 集成后,推送即部署,不需要额外配置 CI 文件。
注意:Cloudflare Pages 的构建环境默认使用 Node.js 18,如果你本地用的是 20 或 22,需要在项目里加一个
.nvmrc文件指定版本,否则构建时可能因为版本不一致报错。这个坑我踩过,本地预览正常,部署后白屏,查了半天才发现是 Node 版本问题。
2.4 内容架构设计:蓝皮书应该怎么组织
一本蓝皮书不是博客合集,它需要有清晰的层级和阅读路径。我最终定的结构是四大部分:基础篇(系统安装、网络配置、SSH 连接)、外设篇(GPIO、I2C、SPI、摄像头、屏幕)、服务篇(文件共享、媒体中心、自动化脚本)、项目篇(完整案例,比如家庭监控、环境监测)。
每个部分下面按主题分章节,每章包含:概念解释、硬件准备、操作步骤、验证方法、常见问题。这个结构的好处是,读者可以按顺序读,也可以直接跳到需要的章节。VitePress 的侧边栏配置支持多级嵌套,正好匹配这个结构。
3. 环境准备:Node.js 安装与 GitHub 访问优化
3.1 Node.js 版本选择与安装实操
VitePress 对 Node.js 版本有要求,官方建议 18 以上。我推荐用 20 LTS 或 22 LTS,这两个版本长期支持,社区插件兼容性最好。不要用奇数版本(如 19、21),那些是过渡版本,生命周期短。
Windows 安装:直接去 Node.js 官网下载 LTS 版本的.msi安装包,双击下一步就行。安装时注意勾选"Add to PATH",否则命令行里找不到node命令。装完后打开 PowerShell,输入node -v和npm -v,能显示版本号就成功了。
macOS 安装:推荐用 Homebrew,命令是brew install node@20。装完后可能需要手动链接:brew link --overwrite node@20。如果你之前装过其他版本,先用brew uninstall node清理干净。
Ubuntu 安装 Node.js 20+:这是问得最多的场景。Ubuntu 自带的 apt 源里 Node 版本通常很旧,直接apt install nodejs会装到 12 或 14,不满足要求。正确做法是用 NodeSource 的源:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs执行完后再node -v确认版本。如果显示的还是旧版本,检查一下which node的路径,可能是旧版本残留在/usr/bin/node,而新版本在/usr/local/bin/node。用sudo apt remove nodejs卸载旧的,再重新装。
实操心得:在 Ubuntu 上装完 Node 后,npm 的全局包目录权限经常出问题,导致
npm install -g报 EACCES 错误。解决办法是配置 npm 使用用户目录:npm config set prefix ~/.npm-global,然后把~/.npm-global/bin加到 PATH 里。这样就不需要每次都用 sudo 了。
3.2 GitHub 访问优化与仓库创建
GitHub 在国内的访问稳定性是个老问题。我不建议用任何形式的代理工具,而是通过以下方式提升体验:
第一,配置 hosts 文件。通过 DNS 查询工具找到 GitHub 相关域名的可用 IP,写入系统 hosts 文件。这个方法简单直接,但 IP 会变,需要定期更新。
第二,使用镜像站。国内有一些 GitHub 镜像站可以加速下载,比如用于git clone的镜像地址。但注意,镜像站只适合下载公开仓库,推送代码还是得走原站。
第三,配置 Git 的代理设置。如果你有可用的网络通道,可以给 Git 单独配置:
git config --global http.proxy http://127.0.0.1:端口 git config --global https.proxy http://127.0.0.1:端口取消代理用git config --global --unset http.proxy。
仓库创建很简单:登录 GitHub,点右上角加号,选"New repository",填仓库名(比如pi-bluebook),选 Public 或 Private,勾选"Add a README file",然后创建。创建完后,在本地项目目录里执行:
git init git remote add origin https://github.com/你的用户名/pi-bluebook.git git add . git commit -m "初始化项目" git push -u origin main如果推送时报错failed to push some refs,通常是因为远程仓库有 README 而本地没有,先执行git pull --rebase origin main再推送。
3.3 VitePress 项目初始化与依赖安装
环境准备好后,开始搭项目。我习惯用 npm 而不是 yarn 或 pnpm,因为 VitePress 官方文档以 npm 为主,遇到问题搜到的答案也多是 npm 的。
mkdir pi-bluebook cd pi-bluebook npm init -y npm install -D vitepress npx vitepress initnpx vitepress init会进入一个交互式配置向导,问几个问题:项目根目录在哪、站点标题是什么、描述是什么、是否使用默认主题、是否添加 TypeScript 支持。我的选择是:根目录./docs,标题"Pi 蓝皮书",描述"从零开始的树莓派实战指南",使用默认主题,不加 TypeScript。
初始化完成后,目录结构是这样的:
pi-bluebook/ ├── docs/ │ ├── .vitepress/ │ │ └── config.mts │ ├── index.md │ └── ... ├── package.json └── ...config.mts是核心配置文件,后面所有导航、侧边栏、搜索、base URL 都在这里改。
注意:VitePress 的配置文件扩展名可能是
.mts、.ts或.js,取决于初始化时的选择。.mts是 ESM 格式的 TypeScript,如果你不熟悉,可以手动改成.mjs或.js,但要注意语法差异。
4. 核心配置与内容编写:从骨架到血肉
4.1 config.mts 关键配置逐项解析
配置文件是 VitePress 的大脑,我把它拆成几个模块来讲。
站点基础信息:
export default defineConfig({ title: "Pi 蓝皮书", description: "从零开始的树莓派实战指南", lang: "zh-CN", base: "/", })base这个参数特别容易出错。如果你部署在自定义域名的根路径下,base就是/;如果部署在子路径下(比如https://example.com/pi-bluebook/),base必须写成/pi-bluebook/。Cloudflare Pages 默认部署在根路径,所以用/就行。但如果你同时用 GitHub Pages,仓库名是pi-bluebook,那base就得改成/pi-bluebook/,否则所有静态资源都会 404。
主题配置:
themeConfig: { nav: [ { text: "首页", link: "/" }, { text: "基础篇", link: "/basics/" }, { text: "外设篇", link: "/peripherals/" }, { text: "服务篇", link: "/services/" }, { text: "项目篇", link: "/projects/" }, ], sidebar: { "/basics/": [ { text: "基础篇", items: [ { text: "系统安装", link: "/basics/install" }, { text: "网络配置", link: "/basics/network" }, { text: "SSH 连接", link: "/basics/ssh" }, ], }, ], // 其他部分的侧边栏... }, search: { provider: "local", }, socialLinks: [ { icon: "github", link: "https://github.com/你的用户名/pi-bluebook" }, ], }侧边栏的link路径要和实际文件对应。比如link: "/basics/install"对应的是docs/basics/install.md。如果路径写错,点击后会是 404 页面。
本地搜索配置:VitePress 内置了基于 minisearch 的本地搜索,不需要额外服务。配置provider: "local"即可。搜索索引在构建时生成,所以内容更新后需要重新构建才能搜到新内容。
4.2 Markdown 写作规范与内容组织
VitePress 的 Markdown 支持标准语法加上一些扩展。我在写蓝皮书时遵循以下规范:
文件命名:全部用小写英文加连字符,比如gpio-basics.md、camera-setup.md。不要用中文文件名,虽然 VitePress 支持,但在某些部署环境下会出现编码问题。
标题层级:每篇文档只用一个一级标题(#),作为页面标题。下面的小节用##、###。VitePress 会自动根据标题生成右侧目录。
代码块:必须标注语言类型,这样才有语法高亮。比如:
sudo apt update sudo apt upgrade -y提示框:VitePress 支持自定义容器,用来标注注意事项:
::: tip 提示 这是提示内容。 ::: ::: warning 注意 这是警告内容。 ::: ::: danger 危险 这是危险操作警告。 :::这三种容器在渲染后会有不同的颜色和图标,比单纯的加粗文字更醒目。
图片引用:图片放在docs/public/目录下,引用时用绝对路径/图片名.png。比如docs/public/gpio-pinout.png,在 Markdown 里写。
实操心得:写硬件教程时,图片比文字重要。我习惯用手机拍实物照片,然后用 draw.io 画引脚示意图。图片压缩用 TinyPNG,能把几 MB 的图压到几百 KB,加快页面加载速度。
4.3 本地预览与热更新调试
内容写了一段后,用npm run docs:dev启动本地开发服务器。默认地址是http://localhost:5173。VitePress 的热更新很快,保存文件后浏览器几乎立刻刷新。
如果端口被占用,可以指定其他端口:npm run docs:dev -- --port 3000。
本地预览时注意一个问题:base配置会影响资源路径。如果你把base设成了/pi-bluebook/,本地预览时访问http://localhost:5173/pi-bluebook/才能看到页面,直接访问根路径会 404。所以本地开发时建议把base临时改成/,部署前再改回去。
调试样式问题时,浏览器的开发者工具是最好用的。VitePress 的默认主题用 CSS 变量控制颜色和间距,你可以在docs/.vitepress/theme/下新建custom.css,覆盖这些变量:
:root { --vp-c-brand-1: #3b82f6; --vp-c-brand-2: #2563eb; --vp-sidebar-width: 280px; }然后在config.mts里引入:
import "./theme/custom.css"5. 部署上线:GitHub 与 Cloudflare Pages 联动
5.1 推送到 GitHub 的完整流程
本地内容写好后,推送到 GitHub。如果你还没初始化 Git 仓库:
git init git add . git commit -m "完成基础篇内容" git branch -M main git remote add origin https://github.com/你的用户名/pi-bluebook.git git push -u origin main如果已经初始化过,直接git add . && git commit -m "更新内容" && git push就行。
推送前建议加一个.gitignore文件,把不需要版本控制的东西排除掉:
node_modules/ docs/.vitepress/dist/ docs/.vitepress/cache/ .DS_Storenode_modules和dist目录体积大且可以重新生成,不需要提交。.DS_Store是 macOS 的系统文件,提交上去会污染仓库。
注意:GitHub 对单个文件大小有限制,超过 100MB 会被拒绝。如果你有大的视频或数据集,不要直接提交,用 Git LFS 或者放到对象存储里。
5.2 Cloudflare Pages 项目创建与构建配置
登录 Cloudflare 控制台,进入"Workers 和 Pages"页面,点"创建应用程序",选"Pages",然后"连接到 Git"。授权 Cloudflare 访问你的 GitHub 账号,选择pi-bluebook仓库。
接下来是构建配置,这是最关键的一步:
| 配置项 | 值 | 说明 |
|---|---|---|
| 生产分支 | main | 推送到这个分支触发自动部署 |
| 框架预设 | VitePress | 选这个会自动填构建命令和输出目录 |
| 构建命令 | npm run docs:build | 对应 package.json 里的脚本 |
| 构建输出目录 | docs/.vitepress/dist | VitePress 默认输出位置 |
| Node.js 版本 | 20 | 通过环境变量NODE_VERSION=20指定 |
如果框架预设里没有 VitePress,选"None",然后手动填上面这些值。
环境变量在"设置"→"环境变量"里添加。除了NODE_VERSION,如果你有自定义域名,还可以加VITE_SITE_URL之类的变量,在代码里通过import.meta.env读取。
点"保存并部署",Cloudflare 会拉取代码、安装依赖、执行构建、部署到全球 CDN。首次部署大概需要两三分钟。部署完成后,会分配一个*.pages.dev的域名,可以直接访问。
5.3 自定义域名绑定与 HTTPS 配置
*.pages.dev的域名能用,但不够正式。绑定自定义域名的步骤:在 Pages 项目里点"自定义域",输入你的域名,然后按提示在域名注册商那里添加 CNAME 记录,指向你的项目名.pages.dev。
Cloudflare 会自动签发 SSL 证书,HTTPS 是默认开启的。证书续期也是自动的,不需要手动操作。
实操心得:如果你用 Cloudflare 管理 DNS,绑定自定义域名会特别快,因为不需要等待 DNS 传播。如果域名在其他注册商,可能需要等几分钟到几小时。绑定后记得在 Cloudflare 的 SSL/TLS 设置里把加密模式设为"完全"或"完全(严格)",避免混合内容警告。
5.4 自动部署触发与回滚机制
配置好之后,每次git push到 main 分支,Cloudflare 都会自动触发构建和部署。构建日志可以在 Pages 项目的"部署"标签页里查看,如果构建失败,日志会显示具体哪一步出错。
回滚也很简单:在部署列表里找到之前成功的版本,点"回滚"就能恢复到那个版本。这个功能在内容更新出问题时特别有用,不用改代码就能快速恢复。
如果构建频繁失败,检查这几个地方:Node 版本是否匹配、构建命令是否正确、输出目录是否填对、依赖是否在package.json里声明。我遇到过一次构建失败,原因是本地装了某个包但忘了加到package.json的devDependencies里,本地能跑,云端拉不到依赖就挂了。
6. 常见问题与排查技巧实录
6.1 构建与部署阶段的高频问题
问题一:部署后页面白屏,控制台报 404。
原因通常是base配置不对。检查config.mts里的base是否和实际部署路径匹配。Cloudflare Pages 根路径部署用/,子路径部署用/子路径/。
问题二:构建时报Cannot find module。
本地能跑云端不能跑,九成是依赖没写进package.json。执行npm install 缺失的包名 -D,然后提交更新后的package.json和package-lock.json。
问题三:Node 版本不兼容。
VitePress 新版本可能要求 Node 18 以上,而 Cloudflare 默认可能是 16。在项目根目录加.nvmrc文件,内容写20,或者在环境变量里设NODE_VERSION=20。
问题四:搜索功能不工作。
本地搜索的索引在构建时生成,如果构建成功但搜索没结果,检查config.mts里search.provider是否设为local。另外,搜索只索引已构建的页面,草稿或未链接的页面不会被索引。
6.2 内容编写与预览阶段的典型故障
问题五:本地预览正常,部署后样式错乱。
通常是 CSS 文件路径问题。如果你在config.mts里引入了自定义 CSS,确认路径是相对路径且文件已提交到仓库。另外,Cloudflare 构建时对大小写敏感,Custom.css和custom.css是两个不同的文件。
问题六:图片不显示。
检查图片是否放在docs/public/目录下,引用路径是否以/开头。如果图片放在其他目录,VitePress 不会自动复制到输出目录。
问题七:中文搜索效果差。
minisearch 对中文的分词支持一般,搜索"树莓派"可能搜不到"树莓派配置"这样的内容。解决办法是在搜索配置里加自定义分词,或者改用 Algolia DocSearch(需要申请,免费但审核周期长)。
6.3 网络与访问相关的疑难杂症
问题八:GitHub 推送超时。
先检查网络连接,然后尝试git config --global http.postBuffer 524288000增大缓冲区。如果还是不行,改用 SSH 方式推送,比 HTTPS 稳定一些。
问题九:Cloudflare Pages 构建排队时间长。
免费版构建有并发限制,高峰期可能需要排队。如果急着上线,可以在本地构建好dist目录,然后用wrangler pages deploy命令直接上传,跳过云端构建。
问题十:自定义域名解析不生效。
用dig或nslookup检查 DNS 记录是否生效。CNAME 记录的值应该是你的项目名.pages.dev,注意不要加https://前缀。如果用了 Cloudflare 的 DNS,确认代理状态是"已代理"(橙色云朵)还是"仅 DNS"(灰色云朵),两种模式对 SSL 证书的要求不同。
避坑技巧:每次改完配置后,先在本地跑一遍
npm run docs:build,确认构建成功再推送。本地构建能发现大部分语法错误和路径问题,比等云端构建失败再排查快得多。
7. 内容扩展与长期维护的一些思路
蓝皮书上线只是开始,后面怎么持续更新才是关键。我的做法是:每完成一个树莓派项目,就把过程整理成一篇文档,补充到对应的章节里。这样内容自然增长,不需要刻意"写书"。
版本管理方面,用 Git 的 tag 功能标记重要节点。比如内容覆盖了基础篇和外设篇后,打个v0.1的 tag;项目篇完成后打v1.0。这样读者能清楚知道当前版本的覆盖范围。
如果以后想加评论功能,可以用 Giscus,基于 GitHub Discussions,不需要自己搭后端。想加访问统计,Cloudflare 自带的 Web Analytics 就够用,在 Pages 项目里开启即可,不涉及任何用户隐私数据。
内容多了之后,考虑加一个"更新日志"页面,记录每次新增或修改的内容。VitePress 支持从 Git 提交历史自动生成,但需要额外配置,我目前是手动维护一个changelog.md,简单直接。
最后说一个实际体会:写文档最怕的是"完美主义瘫痪"。我一开始总想把每篇都写到无可挑剔再发布,结果一个月过去了一篇都没上线。后来改成"先发布再迭代",哪怕只有大纲和关键步骤,先推上去,后面慢慢补细节。事实证明,读者的反馈比自己的闭门造车有用得多,很多我没想到的问题都是读者在 issue 里提出来的。