按站主要求,门面档(fontProfile="interface")整体换成霞鹜新致宋。
文章页不受影响,仍是思源黑体 —— 宋体在长正文里不如黑体好读。
- BaseLayout:门面档额外加载 ZeoSeven 的 22 号字体,替换掉原来的霞鹜文楷
(文楷 regular + bold 两档一起删掉)
- global.css:--font-display-sans 换成新致宋;恢复按下 font-profile-interface
覆盖字族的规则,让门面整体走宋体(思源黑体兜底)
- 站点名与首页那句话本来就挂在 --font-display-sans 上,无需改动
为什么必须用 ZeoSeven 而不是 jsdelivr
jsdelivr 上的 lxgw-neo-zhisong-webfont@1.0.0 是**单文件 4.45 MB、没有
unicode-range 分包**,挂上去等于每个访客都要下 4.45 MB,不能用。
ZeoSeven 的 /22/main/result.css 把字体切成 145 个 unicode-range 分包
(CSS 158 KB / gzip 54 KB),浏览器只下当前页面命中的那几个。
Fontsource 没有收录这款字(三个包名都 404),所以没有更统一的来源。
实测 ZeoSeven 响应稳定(连续 3 次均 200,耗时约 0.11s),分包可下。
已知取舍
新致宋只有 400 一个字重,门面里的 font-medium / font-semibold / font-bold
会由浏览器合成加粗。宋体的合成加粗偏糊,如果观感不好,把那几处字重去掉
改用常规字重即可。这一点已写进操作指南。
体积(样式表 gzip)
门面:原 127.4 KB(思源黑 + 思源宋 + Inter + Playfair + 文楷两档)
→ 118.9 KB(思源黑 + 思源宋 + Inter + Playfair + 新致宋)
文章页:不变
验证:pnpm build 退出码 0
- 首页加载 zeoseven/22/main/result.css;文章页不加载
- 两类页面均无 lxgw-wenkai 残留
- 产物 CSS 里 --font-display-sans 为 "LXGW Neo ZhiSong",
body.font-profile-interface 覆盖规则与思源黑体兜底均在
391 lines
14 KiB
Markdown
391 lines
14 KiB
Markdown
# 操作指南
|
||
|
||
这个博客的日常操作:写文章、写偶得、加照片、本地预览、部署上线。
|
||
|
||
---
|
||
|
||
## 0. 首次准备
|
||
|
||
```bash
|
||
cd /home/tianxuetao/文档/VermilionVoid-main
|
||
pnpm install # 只需在第一次、或依赖变动后执行
|
||
```
|
||
|
||
平时不需要重复装依赖。
|
||
|
||
---
|
||
|
||
## 1. 本地预览(写得最多的一步)
|
||
|
||
```bash
|
||
pnpm dev
|
||
```
|
||
|
||
打开 **http://localhost:4321**。改任何文件浏览器会自动刷新,不用重启。
|
||
|
||
停止:在终端按 `Ctrl + C`。
|
||
|
||
> 端口被占用时 Astro 会自动换到 4322、4323……看终端输出的那行 `Local` 网址即可。
|
||
|
||
---
|
||
|
||
## 2. 写一篇正式文章
|
||
|
||
### 建文件
|
||
|
||
```bash
|
||
pnpm new-post "树莓派装 Docker 全程记录" --category 教程 --tags Docker,树莓派
|
||
```
|
||
|
||
常用选项:
|
||
|
||
| 选项 | 作用 |
|
||
|---|---|
|
||
| `--category 教程` | 分类,同时决定放进哪个子目录 |
|
||
| `--tags Docker,树莓派` | 标签,逗号分隔 |
|
||
| `--description "摘要"` | 摘要,用于 SEO 和列表卡片 |
|
||
| `--image /assets/images/xxx.webp` | 封面图 |
|
||
| `--file my-slug` | 自定义文件名(默认用标题) |
|
||
| `--pinned` | 置顶 |
|
||
| `--draft` | 草稿,构建时不会输出 |
|
||
|
||
生成的文件长这样:
|
||
|
||
```yaml
|
||
---
|
||
title: "树莓派装 Docker 全程记录"
|
||
published: 2026-09-14
|
||
description: "摘要"
|
||
tags:
|
||
- "Docker"
|
||
- "树莓派"
|
||
category: "教程"
|
||
---
|
||
```
|
||
|
||
### 写正文
|
||
|
||
直接在 `---` 下面往下写 Markdown。支持:
|
||
|
||
- 标题、列表、表格、引用、代码块(带行号和复制按钮)
|
||
- 数学公式:`$行内$` 和 `$$独立成段$$`
|
||
- 提示框:
|
||
|
||
```markdown
|
||
> [!NOTE]
|
||
> 这是一条提示。也可以用 TIP / IMPORTANT / CAUTION / WARNING
|
||
```
|
||
|
||
- 图片:``
|
||
|
||
### 不想用脚本
|
||
|
||
手动在 `src/content/posts/` 下建 `.md` 文件也可以,**只有 `title` 和 `published` 是必填的**,其余字段都能省略。
|
||
|
||
### 加密文章(可选)
|
||
|
||
```yaml
|
||
encrypted: true
|
||
password: "你的密码"
|
||
```
|
||
|
||
正文会被加密,需要输密码才能阅读。
|
||
|
||
---
|
||
|
||
## 3. 写一条「偶得」
|
||
|
||
```bash
|
||
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>/`,**构建时自动扫描目录**,不用在配置里逐个登记。
|
||
|
||
加一个新相册 = 两步:
|
||
|
||
1. 建目录并放照片:`public/gallery/我的相册/`
|
||
2. 在 `src/data/gallery.ts` 的 `albums` 里加一项:
|
||
|
||
```ts
|
||
{
|
||
id: "我的相册", // 必须和目录名一致
|
||
name: "相册显示名",
|
||
description: "一句话描述",
|
||
location: "甘肃-张掖", // 可选
|
||
date: "2026-09-14", // 可选
|
||
tags: ["旅行"], // 可选,用于索引页筛选
|
||
}
|
||
```
|
||
|
||
封面优先级:`cover` 字段 > 目录里的 `cover.*` 文件 > 第一张图。
|
||
|
||
> 📏 **放进去之前先压图。** `public/` 下的资源由服务器原样下发,**不经过 Astro 优化**。
|
||
> 一张 4K 原图可能十几 MB,会让页面加载非常慢。建议先压成 WebP 再放。
|
||
|
||
---
|
||
|
||
## 5. 检查与构建
|
||
|
||
```bash
|
||
pnpm check # 类型 + 内容校验,frontmatter 写错会在这里报出来
|
||
pnpm build # 构建到 dist/,并建立搜索索引
|
||
pnpm preview # 本地预览构建产物(搜索功能只有这里才生效)
|
||
```
|
||
|
||
写完一篇后建议跑一次 `pnpm check`,能提前发现 frontmatter 字段写错。
|
||
|
||
---
|
||
|
||
## 6. 部署上线
|
||
|
||
```bash
|
||
./deploy.sh
|
||
```
|
||
|
||
它会构建一次,然后 rsync 到树莓派和云服务器,覆盖生产前会问你一句确认。
|
||
|
||
两个目标都是 **Caddy** 在服务,而且都开了压缩(`twikoo.min.js` 506 KB → 160 KB)。
|
||
|
||
- 云服务器:1Panel 管的 Caddy 容器,配置 `/opt/1panel/apps/caddy/caddy/data/conf/Caddyfile`
|
||
- 树莓派:Caddy 容器 `blog-caddy`,配置 `/home/pi/caddy/Caddyfile`
|
||
|
||
| 命令 | 用途 |
|
||
|---|---|
|
||
| `./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`。
|
||
|
||
**只想更新书单**(不动别的):
|
||
|
||
```bash
|
||
pnpm reading
|
||
```
|
||
|
||
会打印抓到的每本书和进度。**默认抓整架**;想只抓最近动过的几本就 `pnpm reading --top 12`。
|
||
|
||
读完的书会自动出现在「书籍」区底部的「微信读书 · 已读完」分组里,不用手工搬。
|
||
|
||
**平时不用管**:`pnpm build` 和 `./deploy.sh` 都会自动先抓一次。抓不到就沿用上一次的数据,**不会让部署失败**。
|
||
|
||
**首次配置**(只做一次):
|
||
|
||
1. 打开 <https://weread.qq.com/r/weread-skills> 扫码,拿到 `wrk-` 开头的 Key
|
||
2. 在项目根目录的 `.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):
|
||
|
||
```bash
|
||
sudo sysctl fs.inotify.max_user_watches=524288
|
||
```
|
||
|
||
**偶得的日期差一天**
|
||
看第 3 节:`published` 必须带时区。
|
||
|
||
**图片不显示**
|
||
检查路径是否以 `/` 开头(`/assets/images/x.webp`),以及文件是否真在 `public/` 下对应位置。
|
||
注意 `public/` 里的文件路径就是 URL 路径,**没有 `public` 这一段**。
|
||
|
||
**评论区空白 / 不显示**
|
||
|
||
先确认页面类型——评论**只出现在文章页、关于页、友链页**,首页、偶得、相册、书架、专题都没有,这是正常的。
|
||
|
||
如果文章页也是空的,按顺序查:
|
||
|
||
1. `src/data/comments.ts` 里的 `twikooEnvId` 是否填了(留空则整个评论区不渲染)
|
||
2. 打开浏览器控制台,看有没有 `[twikoo] 初始化失败` 或 404
|
||
3. 确认 `public/assets/js/twikoo.min.js` 和 `public/assets/css/twikoo.css` 都在,且版本与后端一致
|
||
4. 直接测后端:
|
||
|
||
```bash
|
||
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)。
|
||
|
||
**想换字体 / 字体是从哪加载的**
|
||
|
||
全部由 `src/layouts/BaseLayout.astro` 顶部的 `fontStylesheets` 数组决定,
|
||
走 jsdelivr 上的 Fontsource 包(**不用 Google Fonts**,国内访问不稳):
|
||
|
||
| 层级 | 字体 | 用在哪 |
|
||
|---|---|---|
|
||
| 门面整体(宋)| 霞鹜新致宋 `LXGW Neo ZhiSong` | 门面档全部文字(站点名、首页那句话、卡片标题、UI)|
|
||
| 标题(宋)| 思源宋体 `Noto Serif SC Variable` | 文章页标题、页面标题 |
|
||
| 正文/UI(黑)| 思源黑体 `Noto Sans SC Variable` | 文章正文、界面、按钮 |
|
||
| 西文 | `Inter Variable` + `Playfair Display` | 西文与数字、展示衬线 |
|
||
|
||
门面(`fontProfile="interface"`)整体走宋体,文章页保持黑体 —— 宋体在长正文里
|
||
不如黑体好读。门面之所以能用宋体,是因为它没有大段正文。
|
||
|
||
> ⚠️ **霞鹜新致宋只有 ZeoSeven 有分包版本。** jsdelivr 上的
|
||
> `lxgw-neo-zhisong-webfont` 是**单文件 4.45 MB、没有 unicode-range**,
|
||
> 每次全量下载,**不能用**。ZeoSeven 把它切成 145 个 unicode-range 分包,
|
||
> 浏览器只下页面用到的那几个。
|
||
> 另外它**只有 400 一个字重**,门面里的 `font-medium/semibold/bold`
|
||
> 都是浏览器合成的加粗;嫌糊就把那几处改成常规字重。
|
||
|
||
字族名的对应关系写在 `src/styles/global.css` 的 `--font-*` token 里。
|
||
改字体只需动这两处,不用碰组件。
|
||
|
||
两个要点:
|
||
|
||
- **CJK 用可变字体**(一份 CSS 覆盖 100–900 全字重),不要改成按字重加载 ——
|
||
那样每个字重一份 105 KB 的 CSS,四档就是 420 KB
|
||
- 每份 CSS 内含约 100 条带 `unicode-range` 的 `@font-face`,浏览器只下载当前页面
|
||
实际用到的那几个分包。完整思源黑体是 3.3 MB,但一页通常只命中 100–300 KB
|
||
- 霞鹜文楷**只在门面档加载**(`fontProfile="interface"`);文章页没加载它,
|
||
所以 `--font-display-sans` 里它排在思源黑体前面、由浏览器自动回退
|
||
|
||
**改了 markdown 插件却不生效**
|
||
|
||
Astro 会把渲染好的文章缓存到 `node_modules/.astro`,而这个缓存**只按 markdown
|
||
文件内容算 key,不看插件代码**。所以改完 `src/plugins/satteri/*.mjs` 之后,
|
||
已经渲染过的文章不会重新跑插件 —— 你会以为改动没生效,其实是吃了缓存。
|
||
|
||
```bash
|
||
rm -rf node_modules/.astro .astro && pnpm build
|
||
```
|
||
|
||
(这个坑是给标题锚点补 `aria-label` 时踩到的:插件明明改了,
|
||
产物里的 HTML 却还是老样子。)
|
||
|
||
**`pnpm dev` 启动时满屏刷红**
|
||
|
||
历史上踩过两个独立的原因,都已修好,这里记下来免得再犯:
|
||
|
||
1. **源码里出现字面量的 script 开标签**(`Sketch.astro` 的 frontmatter 里曾经有)。
|
||
Astro 编译器靠**扫描源码文本**收集内联脚本,它分不清「这是真的标签」还是
|
||
「在字符串/注释里」。一旦扫到,就会把后面的内容当成组件脚本交给 Vite 解析,
|
||
报 `Expected "}" but found "{"` 或 `Unexpected "。"`,整个 `/src` 刷红。
|
||
→ 用 `"\x3Cscript>"` 拼出来。**注释里也不能写**,第一版就是栽在注释上。
|
||
|
||
2. **`.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` 集合目前是空的,专题页会显示空态。
|
||
|
||
**想回退到之前的状态**
|
||
```bash
|
||
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)
|
||
```
|