两个独立问题叠在一起,用户看到的只是第一个(扫描失败会中止启动,
第二个来不及暴露)。
1) Sketch.astro 的 frontmatter 里出现字面量的 script 开标签
Astro 编译器靠扫描源码文本收集内联脚本,分不清真标签和字符串/注释。
原代码用模板字符串拼 iframe 里的 resize 脚本,那个字面量开标签被当成
组件脚本抽出来交给 Vite,里面的 ${JSON.stringify(...)} 直接报
`Expected "}" but found "{"`,dev 依赖扫描失败、整个 /src 刷红。
-> 改成 "\x3Cscript>" / "\x3C/script>" 拼接。
注意闭标签原本写作 <\/script> 所以没被误判,只有开标签要处理。
修完第一版又把解释写进注释、注释里带了字面量开标签,于是换了条错误
(`Unexpected "。"`)继续报;这次注释也改成不带字面量的写法。
2) .pnpm-store 被 Vite 的 watcher 一起监听
项目根目录下的 .pnpm-store 是 pnpm 内容寻址仓库(54269 个文件 / 672MB,
已被 .gitignore 忽略),Vite 默认 watch 项目根,直接撑爆 inotify
(max_user_watches = 65536),启动后无限刷
`ENOSPC: System limit for number of file watchers reached`。
-> astro.config.mjs 加 vite.server.watch.ignored: ["**/.pnpm-store/**"]。
顺带:package.json 加 "type": "module",消掉 Node 对
src/plugins/*.js 的 MODULE_TYPELESS_PACKAGE_JSON 警告(两个文件本来就是 ESM)。
验证
- 删掉 node_modules/.vite 强制重新做依赖扫描后启动 pnpm dev:
ERROR 0 / Failed to scan 0 / ENOSPC 0,ready in 496ms
/、/bookshelf/、/bookshelf/books/ 均 200
- pnpm build 退出码 0,MODULE_TYPELESS 警告 0
- 仅剩 [WARN] glob-loader 提示 src/content/studies 为空,属预期
- 操作指南补了这条 FAQ,说明两个原因和"注释里也不能写"这个坑
11 KiB
操作指南
这个博客的日常操作:写文章、写偶得、加照片、本地预览、部署上线。
0. 首次准备
cd /home/tianxuetao/文档/VermilionVoid-main
pnpm install # 只需在第一次、或依赖变动后执行
平时不需要重复装依赖。
1. 本地预览(写得最多的一步)
pnpm dev
打开 http://localhost:4321。改任何文件浏览器会自动刷新,不用重启。
停止:在终端按 Ctrl + C。
端口被占用时 Astro 会自动换到 4322、4323……看终端输出的那行
Local网址即可。
2. 写一篇正式文章
建文件
pnpm new-post "树莓派装 Docker 全程记录" --category 教程 --tags Docker,树莓派
常用选项:
| 选项 | 作用 |
|---|---|
--category 教程 |
分类,同时决定放进哪个子目录 |
--tags Docker,树莓派 |
标签,逗号分隔 |
--description "摘要" |
摘要,用于 SEO 和列表卡片 |
--image /assets/images/xxx.webp |
封面图 |
--file my-slug |
自定义文件名(默认用标题) |
--pinned |
置顶 |
--draft |
草稿,构建时不会输出 |
生成的文件长这样:
---
title: "树莓派装 Docker 全程记录"
published: 2026-09-14
description: "摘要"
tags:
- "Docker"
- "树莓派"
category: "教程"
---
写正文
直接在 --- 下面往下写 Markdown。支持:
-
标题、列表、表格、引用、代码块(带行号和复制按钮)
-
数学公式:
$行内$和$$独立成段$$ -
提示框:
> [!NOTE] > 这是一条提示。也可以用 TIP / IMPORTANT / CAUTION / WARNING -
图片:

不想用脚本
手动在 src/content/posts/ 下建 .md 文件也可以,只有 title 和 published 是必填的,其余字段都能省略。
加密文章(可选)
encrypted: true
password: "你的密码"
正文会被加密,需要输密码才能阅读。
3. 写一条「偶得」
pnpm new-thought "换了散热,温度降了 15 度。" --location 张掖 --tags 硬件
| 选项 | 作用 |
|---|---|
--title |
可选标题 |
--location |
地点,显示在日期旁 |
--weather |
天气 |
--images a.png,b.png |
配图,逗号分隔 |
--tags 生活,硬件 |
标签 |
--pinned |
置顶 |
⚠️
published一定要带时区(脚本会自动写成2026-09-14T12:36:47.215Z)。 手写成不带时区的2026-09-14 12:36,YAML 会按 UTC 解析,显示的日期会差一天。
偶得页有两种模式:专注(一次一条,←/→ 切换)和时间线(按年份分组 + 标签筛选)。
4. 加照片到相册
照片放在 public/gallery/<相册id>/,构建时自动扫描目录,不用在配置里逐个登记。
加一个新相册 = 两步:
- 建目录并放照片:
public/gallery/我的相册/ - 在
src/data/gallery.ts的albums里加一项:
{
id: "我的相册", // 必须和目录名一致
name: "相册显示名",
description: "一句话描述",
location: "甘肃-张掖", // 可选
date: "2026-09-14", // 可选
tags: ["旅行"], // 可选,用于索引页筛选
}
封面优先级:cover 字段 > 目录里的 cover.* 文件 > 第一张图。
📏 放进去之前先压图。
public/下的资源由服务器原样下发,不经过 Astro 优化。 一张 4K 原图可能十几 MB,会让页面加载非常慢。建议先压成 WebP 再放。
5. 检查与构建
pnpm check # 类型 + 内容校验,frontmatter 写错会在这里报出来
pnpm build # 构建到 dist/,并建立搜索索引
pnpm preview # 本地预览构建产物(搜索功能只有这里才生效)
写完一篇后建议跑一次 pnpm check,能提前发现 frontmatter 字段写错。
6. 部署上线
./deploy.sh
它会构建一次,然后 rsync 到树莓派和云服务器,覆盖生产前会问你一句确认。
| 命令 | 用途 |
|---|---|
./deploy.sh |
构建 + 部署两个目标 |
./deploy.sh -y |
同上,跳过确认(适合脚本) |
./deploy.sh --pi-only |
只推树莓派,先在内网看效果 |
./deploy.sh --cloud-only |
只推云服务器(正式上线) |
./deploy.sh --dry-run |
空跑,只显示会同步哪些文件 |
./deploy.sh --skip-build |
不重新构建,直接推现有 dist/ |
推荐节奏:先 --pi-only 在树莓派上确认没问题,再 --cloud-only 上生产。
目标地址和 SSH 密钥在
deploy.sh顶部的配置区。 脚本在构建失败或产物异常时会直接中止——因为推送用的是rsync --delete, 拿一个残缺的dist/上去会清空线上目录。
7. 改站点信息
日常最常改的三个文件:
| 想改什么 | 改哪里 |
|---|---|
| 站名、域名、描述、主题色、统计 | src/data/site.ts |
| 昵称、签名、头像、GitHub/邮箱 | src/data/profile.ts |
| 首页打字机文案 | src/components/hero.tsx 顶部的 phrases |
主题色只改 site.ts 里的 themeHue 一个数字:0 红、25 朱红(当前)、200 青、250 蓝绿、345 粉。
7.5 刷新「最近在读」
书架分成两个页面:在读 /bookshelf/(顶部导航「书架」的落点)、书籍 /bookshelf/books/,侧栏「馆藏」互相跳转。
「在读」是从微信读书抓来的,数据存在 src/data/reading.json。
只想更新书单(不动别的):
pnpm reading
会打印抓到的每本书和进度。默认抓整架;想只抓最近动过的几本就 pnpm reading --top 12。
读完的书会自动出现在「书籍」区底部的「微信读书 · 已读完」分组里,不用手工搬。
平时不用管:pnpm build 和 ./deploy.sh 都会自动先抓一次。抓不到就沿用上一次的数据,不会让部署失败。
首次配置(只做一次):
-
打开 https://weread.qq.com/r/weread-skills 扫码,拿到
wrk-开头的 Key -
在项目根目录的
.env里加一行:WEREAD_API_KEY=wrk-你的key.env已被 gitignore,不会提交,也不会随deploy.sh上传到服务器。
不想出现在页面上就改 scripts/fetch-reading.mjs 里的过滤条件(默认跳过私密阅读和从没打开过的书)。
8. 常见问题
改了文件但浏览器没变
先手动刷新。若仍无效,Ctrl + C 停掉再 pnpm dev 重启。
构建时报 ENOSPC: System limit for number of file watchers reached
系统的 inotify 监视器配额用完了,不是代码问题。页面照常访问,但热更新可能失效。
彻底解决需要放宽内核参数(要 sudo):
sudo sysctl fs.inotify.max_user_watches=524288
偶得的日期差一天
看第 3 节:published 必须带时区。
图片不显示
检查路径是否以 / 开头(/assets/images/x.webp),以及文件是否真在 public/ 下对应位置。
注意 public/ 里的文件路径就是 URL 路径,没有 public 这一段。
评论区空白 / 不显示
先确认页面类型——评论只出现在文章页、关于页、友链页,首页、偶得、相册、书架、专题都没有,这是正常的。
如果文章页也是空的,按顺序查:
-
src/data/comments.ts里的twikooEnvId是否填了(留空则整个评论区不渲染) -
打开浏览器控制台,看有没有
[twikoo] 初始化失败或 404 -
确认
public/assets/js/twikoo.min.js和public/assets/css/twikoo.css都在,且版本与后端一致 -
直接测后端:
curl -s -X POST https://twikoo.tianxuetao.top \ -H 'Content-Type: application/json' \ -d '{"event":"GET_FUNC_VERSION"}'正常会返回
{"code":0,"version":{"VERSION":"1.7.20"}}。若版本和前端脚本不一致,去 <https://cdn.jsdelivr.net/npm/twikoo@<后端版本>/dist/> 下载twikoo.min.js和twikoo.css两个文件一起替换。
评论按页面路径归属,且存的是浏览器提交的百分号编码路径。 换域名或改 URL 结构后,老评论会因为路径对不上而「消失」——数据还在后端,只是不再匹配。
评论区排版错乱(按钮变得巨大、表情面板塌成一列、「选择文件」露出来)
症状是点链接切到另一篇文章后才崩,按 F5 刷新就正常。
原因:twikoo 脚本只执行一次,第二次进文章页时不会重新执行;而 ClientRouter 切页时会清掉
它运行时注入到 <head> 的 <style>,样式就没了。
修复早已内置:Comments.astro 里用静态 <link> 引入 public/assets/css/twikoo.css(放在
twikoo-custom.css 之前)。如果又出现这个症状,先确认这两行 <link> 还在,
并且 public/assets/css/twikoo.css 没被误删。
「最近在读」空了 / 数据不更新
先看构建日志里有没有 ⚠️ 抓取失败,继续用上一次的数据构建,后面会跟具体原因:
| 日志里的话 | 怎么办 |
|---|---|
WEREAD_API_KEY 无效或已过期 |
Key 失效了,重新扫码拿一个,更新 .env |
缺少 WEREAD_API_KEY |
.env 里没配,见第 7.5 节 |
fetch failed / 超时 |
网络问题,重跑 pnpm reading 即可 |
重要:以上任何一种都不会让 pnpm build 失败 —— 页面会继续用 src/data/reading.json 里上一次的数据。所以「站点发布成功但书单是旧的」是正常现象,不是 bug。
如果连空态提示都看不到,检查 src/data/reading.json 是否存在(这个文件要提交进 git)。
pnpm dev 启动时满屏刷红
历史上踩过两个独立的原因,都已修好,这里记下来免得再犯:
-
源码里出现字面量的 script 开标签(
Sketch.astro的 frontmatter 里曾经有)。 Astro 编译器靠扫描源码文本收集内联脚本,它分不清「这是真的标签」还是 「在字符串/注释里」。一旦扫到,就会把后面的内容当成组件脚本交给 Vite 解析, 报Expected "}" but found "{"或Unexpected "。",整个/src刷红。 → 用"\x3Cscript>"拼出来。注释里也不能写,第一版就是栽在注释上。 -
.pnpm-store被 Vite 的 watcher 一起监听。它是 pnpm 的内容寻址仓库, 5.4 万个文件 / 672MB,直接把 inotify 撑爆(max_user_watches = 65536), 报ENOSPC: System limit for number of file watchers reached。 → 已在astro.config.mjs里排除:vite.server.watch.ignored: ["**/.pnpm-store/**"]。
看到 [WARN] [glob-loader] No files found ... src/content/studies 是正常的 ——
studies 集合目前是空的,专题页会显示空态。
想回退到之前的状态
git log --oneline # 看提交
git reset --hard <提交号>
附:目录速查
src/content/posts/ 文章(按分类分子目录)
src/content/thoughts/ 偶得
src/content/studies/ 专题(目前为空)
src/data/site.ts 站点配置
src/data/profile.ts 个人信息
src/data/gallery.ts 相册配置
src/data/comments.ts 评论配置
src/components/hero.tsx 首页打字机文案
public/assets/images/ 文章配图
public/gallery/ 相册照片
scripts/ 辅助脚本
dist/ 构建产物(gitignore)