跳到正文

CHANGELOG

更新历史

内容来自仓库根目录的 CHANGELOG.md,构建时渲染。

默认只展开最新一版,其余收起。

更新历史

版本号语义化:主.次.修订。每次改动在这里加一节。

2.5.1 · 2026-09-16

新增

  • 写作流程脚本化,三条命令:
    • npm run new —— 逐条问(标题 / 日期 / 分类 / 标签 / 封面样式 / 摘要), 直接回车用默认值;也支持 npm run new -- "标题" 技术 "前端, 笔记" 一条命令建好。 生成的草稿带 draft: true,构建时会跳过,先写草稿是安全的。
    • npm run posts —— 在资源管理器里打开文章目录。
    • npm run publish —— 自检 → 构建 → 提交 → 推送一条龙。 构建不过就什么都不提交(不会把错误推上去让 Cloudflare 报错); 有草稿会列出来提醒;提交说明写进临时文件再 git commit -F, 绕开 cmd.exe 下 git commit -m "中文" 乱码的问题。
  • README 补「写文章」完整章节:三种写法、改文章、本地预览、什么才算发布, 以及为什么必须 push 才会更新线上(线上是 Cloudflare 在构建 GitHub 仓库)。

修复

  • 主题切换的太阳 / 月亮图标没有居中。原来用的是 / 两个 Unicode 字符 —— 它们的墨迹在字体 em 框里的位置随系统字体变,靠 CSS 居中在有些机器上会偏上或偏下。 改成内联 SVG(viewBox 收紧到图形包围盒),居中由几何决定,不看字体脸色; 旋转切换动画保持不变。已用 Edge 无头截图逐个核对深色 / 浅色两种状态。

2.5.0 · 2026-09-16

新增

  • npm run smoketools/smoke-search.mjs):搜索的运行时冒烟测试。 verify / audit 只能证明「引擎没进首屏、chunk 切出来了」, 证明不了「用户聚焦之后它真能跑」。这个脚本用一个极小的 DOM 假件 把 dist 里真实的按需 chunk 跑一遍:init 幂等、补跑第一次输入、 渲染结果、↑↓ / Enter / Esc / Ctrl+K /「/」/ 清空、索引缺失时的诊断分支。 改搜索引擎之前先跑它。另加 npm run check = verify + smoke + audit。

性能

  • 搜索引擎改成按需加载src/scripts/search-engine.ts)。 SearchBox.astro 里只留一个引导:聚焦输入框 / Ctrl+K /「/」 时才 import() 引擎本体。首屏要下的 JS 从 16.37 KB 降到 9.99 KB(gzip 后 实际传输),第一次达标 PRD 的 10 KB 红线 —— 其中行内 7.88 KB、外链 gzip 2.11 KB。 引擎自己的 chunk 是 7.80 KB(gzip 3.33 KB),用户一动手才下载。
  • 引导分两段:快捷键与「正在准备搜索…」占位现在就装好, 保证 Ctrl+K /「/」第一次按下就有反应;引擎初始化要一点时间, 那之前敲进去的字由引擎 init() 里的 240ms 补跑接住。
  • 引擎 chunk 下载失败(离线 / 404)会在面板里明说,不会静默留个「正在准备搜索…」。

修复

  • 补跑第一次输入的逻辑原来写成 if (input.value.trim()),而 init() 执行时 输入框必然是空的 —— 这个分支从来没生效过。现在无条件挂 240ms 兜底, 触发时再判断(已经有结果或已清空就跳过)。冒烟测试专门盯这条。
  • tools/verify.mjs 增加「按需模块」检查:搜索引擎 / 设置面板只允许被 import() 引用,一旦有人改回静态 import 会立刻报错。
  • tools/audit-dist.mjs 增加产物层回归:首屏脚本里出现 excerptLength / search-hit / pagefind.js 等引擎特征串即判失败, 并核对引导里的 import() 确实指向那个按需 chunk。

2.4.0 · 2026-09-16

新增

  • 搜索查询语法。支持 in:title,tagtag:前端category:技术date:2024-01..2024-12words:500..2000min:1..5,以及 "精确短语"。 文章页的 sr-only 区块里补齐了 data-pagefind-filter / data-pagefind-meta, 筛选走 Pagefind 原生筛选器,区间比较在客户端做。搜索时面板顶部会显示生效的条件。

    注:需求里提到的 size:1024..4089 是文件管理器的语义,博客文章没有「文件大小」, 已改用语义等价的 words:(字数)与 min:(阅读分钟)。

  • 皮肤系统theme.css 改成「主色只存 RGB 分量 --a / --g,其余全部派生」, 皮肤只需覆盖这两行,线条 / 悬停 / 渐变 / 极光背景一起跟随。 三套皮肤:枫丹(水蓝)、歌剧院(玫瑰)、深海(幽紫),深浅各一份压暗版。 主题面板可同时切模式与皮肤。
  • --accent-solid / --gold-solid@property 注册成 <color>, 这样渐变里的色标也能平滑过渡,而不是硬切。

修复 / 调整

  • 搜索聚焦聚光:整页模糊变暗,搜索框高亮,导航淡出。 遮罩是 pointer-events: none(PRD 硬性要求,旧版漏了会导致全站点不动)。
  • 搜索结果只展示一次:点别处关掉后会连结果一起清空,再次聚焦不会又冒出来。
  • 首屏禁止选中.no-select),正文不受影响。
  • 顶部导航精简为 首页 / 关于 / 更新,归档与标签交给页脚(页脚本来就有)。
  • 搜索框光标与输入内容始终居中

2.3.1 · 2026-09-16

新增

  • 封面池src/lib/covers.ts)。文章 frontmatter 的 cover 现在支持三种写法:

    写法 含义
    cover: stand 用封面池里的(推荐)
    cover: /covers/my.jpg 用你自己的图(public 下的绝对路径)
    cover: https://… 外链

    不写则按 slug 从池子里稳定挑一张 —— 同一篇文章每次构建拿到的封面一致, 不会刷一次换一张。12 篇示例文章已全部改成池子 id。

调整

  • 主页首屏占满一屏calc(100svh - 68px)),默认看不到文章列表。
  • 首屏只留徽记 + FONTAINE · FURINA + yuuu + 一行统计,砍掉了原来的长句和大标题。
  • 徽记放大到 clamp(148px, 22vw, 244px),站名放大到 clamp(54px, 12vw, 124px)
  • 下滑时首屏整体缩小 20% 并淡出(只动 transform / opacity),文章版块顺势接上来。
  • 更新历史里内容本来就装得下的版本,不再显示「展开」按钮 —— 点了没新内容很迷惑。 改成按 scrollHeight 实测判断。

移除

  • 海浪背景。它原本对齐首屏底边,首屏改成满屏后会横在正文中间, 滚动时又赖着不走。已连同 Backgroundwaves 属性和 CSS 一起删除。

修复

  • 搜索框光标默认停在中央:placeholder-showntext-align: center), 一开始打字就回到左对齐,避免边打边跳。

2.3.0 · 2026-09-16

新增

  • 真的 favicon。用 tools/make-icons.mjs 处理参考图:从四条边泛洪填充抠背景 (不是「白色变透明」—— 角色头发也是白的,那样会打出窟窿),裁边, 输出 favicon.ico(16/32/48 三尺寸)、icon-192/512.pngapple-touch-icon.png 和一份 site.webmanifest
  • 7 张表情包处理成透明背景的 WebP,放在 public/mascot/,用作文章封面与空状态插画。
  • 主页重构成两屏:首屏只有徽记、站名、一句话和统计;文章列表整体下沉 + 模糊,滚进视口后一次性浮现。下滑提示带轻微浮动动画。
  • 搜索快捷键 /Ctrl/Cmd+K 保留)。↑↓ 在结果间移动,Enter 打开选中项。
  • 从搜索结果点进文章会定位:链接带上 ?q=,文章页找到正文第一处匹配, 包上 <mark>scrollIntoView({ block: 'center' }) 滚到屏幕中央, 配一个只动 opacity/transform 的脉冲圈。
  • 更新历史按版本折叠:默认只展开最新一版,其余收成 170px 并底部渐隐, 每段有「展开/收起」,顶部有「全部展开」。
  • tools/set-domain.mjs + pnpm run domain:一条命令改全站 6 处域名。

修复

  • 首页分类筛选点任何分类都是 0 篇index.astroel.dataset.category, 但 PostCard.astro 从来没输出过 data-category,永远是 undefined, 所有卡片都被 hidden。已补上属性。
  • 搜索框光标被 placeholder 遮住。快捷键提示原本写在 placeholder 里, 聚焦后文字紧贴光标。现在提示做成独立的 <kbd> 徽标,聚焦后淡出, placeholder 在聚焦时也变透明。
  • 卡片 hover 生硬。原来 300ms 线性位移 + 阴影重绘。现在统一用 cubic-bezier(0.22, 1, 0.36, 1) 长缓动,阴影改由伪元素淡入 (不逐帧重绘 box-shadow),封面缓慢放大,标题变色。
  • sharp 之前是幽灵依赖(和 zod 一样的坑),已显式声明。

与 PRD 的偏离

  • PRD 9.5 禁止用 filter: blur() 做动画,但需求明确要求「文章下沉模糊」。 采取折中:模糊只在进入视口时过渡一次,transitionend 后加 .is-donefilter 摘掉,不留长期合成层。 tools/verify.mjs 的对应规则也拆成两条:@keyframes 里动 blur 一律禁止; transition 里含 filter 则要求必须配 .is-done 摘除。

2.1.2 · 2026-09-16

修复(搜索质量)

  • 搜索结果被标签页污染。构建时 Pagefind 会提示 Did not find a data-pagefind-body element on the site. ↳ Indexing all <body> elements —— 意思是它把整页都索引了,包括导航栏、页脚和所有标签页。

    实测后果(用 pagefind.js 在 Node 里跑真实查询):

    查询 修复前 修复后
    芙宁娜 1 条,是标签页 /tags/芙宁娜/ 3 条,全是文章
    玻璃 6 条,第 1 条是 /tags/设计/ 1 条,正是那篇文章
    雨天 6 条(夹着无关标签页) 1 条
    Astro 34 条噪音 4 条,全是文章

    修法:给 PostLayout.astro<article>data-pagefind-body, 给底部按钮行加 data-pagefind-ignore,只索引正文。 索引页数从 43 降到 12(只剩文章),这才是博客搜索该有的样子。

  • 搜索结果能显示日期了。给日期元素加 data-pagefind-meta="date", SearchBox 里的 meta.dateundefined 变成了 2024 年 5 月 20 日

增强

  • npm run audit 新增两项检查:文章是否都标了 data-pagefind-body、 是否都带 data-pagefind-meta="date"。这类问题不看产物是发现不了的。

2.1.1 · 2026-09-16

修复

  • 幽灵依赖tools/verify.mjs 用了 zod@astrojs/compiler,但没在 package.json 里声明。 npm 的扁平化把它们提升到顶层所以能跑;pnpm 的隔离式 node_modules 会正确拒绝, 报 ERR_MODULE_NOT_FOUND。现已显式声明为 devDependencies, 并把 verify.mjs 的导入改成动态 import —— 缺依赖时给一句人话而不是甩堆栈。

新增

  • npm run audittools/audit-dist.mjs:对真实构建产物做验收, 而不是像 verify 那样只看源码。检查首屏 JS 实测字节、首页卡片数、 加载更多的静态 JSON、Pagefind 索引完整性、RSS/Sitemap、 以及 [hidden] 兜底和 pointer-events 保护有没有出现在产物 CSS 里。
  • 首屏内联 JS 的构成明细(会打印每段脚本的体积与用途),让性能预算可执行。

补充说明

  • buildastro build && pagefind --site distastro build 若以非 0 退出码结束, pagefind 不会执行,搜索索引会静默缺失。构建后请跑 npm run audit 确认。
  • ⚠️ Windows 的 cmd.exe 里不要把 # 注释写在命令同一行# 在 bash 是注释、 在 cmd 里不是,整行复制会让后面的命令收到多余参数 (例如 npm run build # 说明 会让 pagefind 报 unexpected argument '#' found)。 仓库里所有代码块都已去掉行内注释,可以整段复制。

实测数据(npm run audit,Astro 7.3.2 构建产物)

项目 结果
页面 44 个 HTML(12 篇正文 + 25 个标签页 + 归档/关于/更新/标签云/404)
首屏 JS 8.70 KB(行内 7.61 KB + 外部包 gzip 1.09 KB),红线 10 KB
第三方脚本 公开页面 0 个
首页首屏 正好 10 张卡片,追加走 api/posts/2.json
Pagefind 43 页 / 1694 词 / 57 文件 / 643 KB
RSS 12 篇
Sitemap 42 个 URL

2.1.0 · 2026-09-15

变更

  • Astro 5.18.2 → 7.3.2。这是与 PRD「锁死 Astro 5.x」的一处有意偏离npm audit 对 Astro ≤ 7.2.7 报出 1 critical / 1 high / 1 low, 逐条核对后确认相关代码路径本项目都没用到,但修复成本只有一行,且已实测兼容。 源码一行未改tools/verify.mjs 在 5 和 7 上都是全绿。
  • 包管理器配置补齐:pnpm-workspace.yaml 放行 esbuild / sharp 的构建脚本。 pnpm 10+ 默认拦截构建脚本并以 exit 1 结束,会导致 Cloudflare Pages 安装步骤失败。 注意 pnpm 11 已不再读取 package.json 里的 pnpm 字段,配置必须放这里。
  • 同时提供 package-lock.jsonpnpm-lock.yaml二选一保留

⚠️ 破坏性要求

项目
Node >= 18 >= 22.12.0
npm >= 9.6.5
pnpm >= 7.1.0

Cloudflare Pages 的 NODE_VERSION 必须从 20 改成 22,否则构建直接失败。


2.0.0 · 2026-09-15

用 Astro 从零重构。这是一次推倒重来,不是迭代。

技术栈(全部锁死)

选型
框架 Astro(静态输出,默认零 JS)
内容 Astro Content Collections(frontmatter 强校验)
样式 Tailwind CSS 4(主题变量走 CSS custom properties)
动画 View Transitions API + 原生 CSS
搜索 Pagefind(构建时生成静态索引)
RSS / Sitemap @astrojs/rss / @astrojs/sitemap
部署 Cloudflare Pages
写作 Sveltia CMS + GitHub OAuth Worker

新增

  • 组件化:Header / Footer / PostCard / TagCloud / SearchBox / ThemeToggle / Background / CoverStyle,改一处全站生效。
  • 内容层交给框架:不再手写 Markdown 解析器,表格、引用、代码块、任务列表全部由 Astro 处理,frontmatter 有 schema 校验。
  • 文件路由:首页、/posts/[slug]/archive/tags/[tag]/about/changelog/rss.xml/404
  • Pagefind 全文搜索:索引分片、按需加载,聚焦输入框才开始下载,不占首屏。
  • 原生 View Transitions:水波淡入,零 JavaScript。
  • 深色 / 浅色双调色板:460ms 整体联动过渡。
  • 9 种封面样式:潮汐 / 星云 / 王冠 / 歌剧院 / 极光 / 星海 / 气泡 / 方格 / 自定义图片,全部是 CSS 渐变,零图片请求。
  • 首页分页:首屏只渲染 10 篇,其余由构建时生成的静态 JSON 按需追加。
  • Sveltia CMS/admin 登录 GitHub 直接写文章,push 后 Cloudflare Pages 自动重建。
  • OAuth Workerworkers/oauth,处理 GitHub 授权的 /auth/callback

砍掉

  • ❌ 音乐播放器(与流畅度冲突)
  • ❌ 空闲提醒(鸡肋)
  • ❌ 6 种页面切换动画 → 只留 1 种「水波淡入」
  • ❌ 装饰性水母 SVG
  • ❌ 阅读次数 / 上次阅读时间(需要后端,第一版砍掉)
  • ❌ 拼音搜索(Pagefind 中文分词够用)
  • ❌ 评论系统(以后再说)

性能约定(硬红线)

  • 首屏 JS < 10KB —— 实测约 1KB(Astro 默认零 JS,交互脚本全部内联)
  • 只动 transformopacity,不碰 filter / box-shadow / width
  • 第三方脚本默认 0 个(统计脚本需手动填 token 才加载)
  • 任何功能如果让首屏 JS 超标,砍掉重做

从旧版踩坑里继承的禁令

  • 禁止用 display 覆盖 [hidden] 的默认行为(全局已加 [hidden] { display: none !important; }
  • 禁止给全屏固定层不加 pointer-events: none
  • 禁止手写 Markdown 解析器
  • 禁止全量加载所有文章到一个 JS 文件
  • 禁止用 filter: blur() 做动画
  • 禁止用 localStorage 存文章正文

1.4.1 · 2024-09-15(旧版)

  • 修复全站按钮点不动:空闲遮罩用 display 覆盖了 [hidden]

1.0.0 · 2024-09-12(旧版)

  • 手写静态站点首次上线。