Lyra 站点问题与修复笔记
这是一份从站点重构开始持续补写的排错笔记。它不是把每次提交简单罗列一遍,而是根据 Git 历史、当前代码和开发规范,记录那些真正影响过页面显示、交互、构建或内容维护的问题。
文章覆盖 2026 年 7 月 5 日完成 Astro 初版迁移,到 7 月 10 日这一轮整理结束之间的主要问题。以后遇到同类故障,也可以继续沿用“现象、原因、解决、复查”的格式往下补。
先记住:不要一上来就改代码
同一个“页面不对”可能来自完全不同的层级:
- Markdown 或组件没有生成正确内容;
- 构建后的资源路径、文件体积或缓存有问题;
- 客户端脚本在 Astro 页面切换后没有重新初始化;
- 音频、CDN 或图片等外部资源本身不可用;
- DNS、Cloudflare Pages 或浏览器缓存仍指向旧版本。
因此排查时要先确认故障在哪一层,再决定是否改代码。否则很容易修掉表面现象,却把真正原因留在原处。
2026-07-05:Banner 下滑后导航状态不正确
现象
首页 Banner 的向下按钮最初直接跳到某个内容区锚点。页面虽然滚下去了,但粘性导航有时会立刻进入吸顶状态,有时又会停在不自然的位置。期间先后尝试过切换 #home-content 和 #home-hero,都只能改变落点,不能稳定控制导航状态。
原因
导航是否吸顶并不是由目标区块的 id 决定,而是由 <main> 第一个子元素 .menu-sentinel 与视口的位置关系决定。锚点只知道“滚到目标元素”,并不知道站点还要保留顶部间距,也不会照顾 sentinel 的判断边界。
解决
现在由 home-banner-carousel.js 拦截按钮点击,读取 main.offsetTop,再按照设备宽度保留顶部呼吸感:
const topGap = window.matchMedia('(max-width: 767px)').matches ? 8 : 32;window.scrollTo({ top: Math.max(0, mainEl.offsetTop - topGap), behavior: 'smooth'});同时必须保证 .menu-sentinel 仍然是 <main> 的第一个子元素。以后如果调整布局,只改锚点或 CSS 偏移并不够,还要一起检查 sentinel 的实际位置。
复查
- 桌面端点击下滑按钮后,导航上方应保留约 32px 间距;
- 移动端保留约 8px,内容不能被导航遮住;
- 手动继续下滑时,导航才进入正常的粘性状态;
- 从其他页面返回首页后,按钮仍然只绑定一次。
2026-07-07:Cloudflare Pages 因单个图片过大而部署失败
现象
本地开发可以打开,Cloudflare Pages 构建也可能完成,但上传产物时失败。问题集中在 Banner 和画廊原图,其中一张静态 Banner 曾超过 25 MiB,画廊的响应式配置还会把超高分辨率原图尺寸加入输出列表。
原因
本地文件系统能保存大图,不代表部署平台会接受。更隐蔽的问题是 astro:assets 会按照传入的 widths 生成衍生图片;如果把 src.width 原样加入列表,一张 8064px 宽的照片就可能产生没有必要的超大构建产物。
解决
- 把画廊输出宽度限制为
[320, 640, 960]; - 批量压缩 Banner、Hero 和画廊照片;
- 首屏图片使用
loading=“eager”,非首屏图片使用loading=“lazy”; - 构建后检查
dist中最大的文件,而不只看源文件大小。
这一轮压缩中,部分十几到二十多 MiB 的照片被降到数百 KiB,Hero 图片也从十余 MiB 降到约 400 KiB。肉眼观感基本不变,但部署稳定性和首屏速度都明显改善。
复查
Get-ChildItem -Path dist -Recurse -File | Sort-Object Length -Descending | Select-Object -First 20 FullName, Length看到异常大的原图或衍生图时,应回到资源入口和 widths 配置修复,不要只在 dist 里手工删除。
2026-07-07:深色模式变量互相覆盖
现象
深色模式下部分卡片、边框和文字层级不一致:有些区域过亮,有些区域又失去对比度。单独改一个组件后,另一个组件还可能跟着变化。
原因
同一批颜色变量在多个位置重复覆盖,组件样式逐渐依赖“最后一条规则刚好生效”。当旧覆盖被删除或文件顺序变化时,视觉问题就会集中出现。
解决
先移除无效和重复的深色变量,让基础设计令牌恢复作用,再只为确实需要差异的组件补回少量覆盖。现在页面背景使用 –bg-color,卡片背景使用 –card-color,深色模式的改动集中在 base.css。
复查
- 切换系统深浅色后刷新首页、文章页、友链页和关于页;
- 检查正文、次要文字、边框、搜索面板和抽屉菜单的对比度;
- 搜索同一 CSS 变量是否在多个模块重复定义;
- 不要用组件里的硬编码颜色掩盖设计令牌问题。
2026-07-08:Astro 页面切换后脚本重复或页面消失
现象
启用 Astro View Transitions 后,传统的“页面载入一次、脚本执行一次”假设不再成立。曾出现过返回首页后轮播计时器重复、交互监听器叠加、音频离开文章后仍保留,以及命名槽中的内容在切换时显示异常等问题。
原因
Astro 客户端路由会替换页面 DOM,但不会像完整刷新那样自动重置所有全局状态。命名槽组件中的内联脚本还可能干扰 View Transition 快照。只监听 DOMContentLoaded 无法覆盖后续页面切换,只监听 astro:page-load 又可能造成重复初始化。
解决
客户端行为统一移到 public/js/ 下的外部脚本,并通过以下属性加载:
<script src="/js/example.js" defer data-astro-rerun data-cfasync="false"></script>每个交互模块还需要完成三件事:
- 在目标元素上保存初始化标记,避免重复绑定;
- 同时兼容首次载入与
astro:page-load; - 在
astro:before-swap中移除监听器、计时器、观察器和播放器实例。
只有必须导入 Astro 虚拟模块的代码可以放进极小型桥接组件,业务逻辑仍然留在外部脚本。
复查
不要只刷新当前页面。应当依次测试“首页 → 文章 → 首页 → 另一篇文章”,观察轮播速度、按钮响应次数、控制台报错和音频状态。
2026-07-08:文章时间轴遮罩和鼠标滚动不稳定
现象
时间轴边缘渐变有时会遮住一张完整卡片,即使当前位置已经对齐吸附点,仍然像是还有内容被裁切。部分鼠标的纵向滚轮也无法稳定转换成横向滚动。
原因
只根据 scrollLeft 判断左右边缘,不能知道卡片是否真的被裁切;而把鼠标滚轮的传统增量固定理解为 120,也会漏掉增量约为 109 或更低的设备。连续触发 scrollBy 还会堆积平滑动画。
解决
- 用卡片与容器的
getBoundingClientRect()判断真实裁切; - 对齐吸附点时隐藏渐变遮罩;
- 将
wheelDeltaY判定阈值设为 50; - 用
requestAnimationFrame合并同一帧内的滚动增量; - 初始化和尺寸变化后都把最新文章同步到最左侧。
复查
分别使用鼠标滚轮、触控板和移动端横向拖动。完整卡片边缘不应被遮罩覆盖,滚到两端时进度和遮罩也应同步消失。
2026-07-09:APlayer 演示区域空白
现象
音乐教程里写了播放器标签和 CDN 资源,但页面不能稳定显示演示。即使出现播放器,也难以判断“播放器初始化失败”和“网易云音频地址不可播”究竟是哪一种问题。
原因
原方案依赖 MetingJS 根据平台歌单自动解析数据,实际还需要额外的 Meting API。接口不可用、响应格式变化或请求被拦截时,页面可能只留下空白。文章 frontmatter 里的播放器开关当时也没有进入内容集合 schema,无法成为可靠的类型化数据。
解决
现在由 aplayer: true 控制文章专属脚本:
- 只有音乐教程会加载 APlayer;
- 演示直接向 APlayer 传入歌曲名、作者、封面和音频地址;
- 不再依赖 MetingJS 解析歌单;
- 资源加载失败时显示明确提示;
- 页面切换前暂停并销毁实例,防止出现两个播放器。
播放器界面能显示但音乐不能播放时,应单独打开音频 URL。版权、地区或外链策略导致的失败属于音频源问题,不应继续修改 APlayer 初始化代码。
2026-07-09:文章字段语义被误用
现象
文章的 tags 一度被当成主题标签展示,结果作者名字出现在不合适的位置,标题和“本文信息”的语义也变得混乱。
原因
这个仓库沿用了历史内容约定:tags 保存作者署名,不是普通博客常见的主题标签。只看字段名而没有检查旧文章数据,就会作出错误推断。
解决
title只负责文章标题;category负责技术、音乐等内容分类;tags作为作者数组,在文章信息和 JSON-LD 作者字段中使用;README.md、AGENTS.md和 schema 注释同步写明这个历史约定。
复查
修改内容模型前,先抽查旧文章 frontmatter,再检查列表页、详情页、RSS、搜索和 JSON-LD 是否使用了同一语义。
2026-07-09:文章图片占位符和正文内容不一致
现象
重构记录中留有指向不存在文件的图片占位符,而且部分叙述仍停留在旧实现。Markdown 注释让这些坏路径暂时不显示,却也让“以后补图”长期留在正文里。
原因
文章从旧站迁移时,正文和资源没有作为一个整体检查;注释中的资源路径也不会被日常页面浏览发现。
解决
删除不存在的占位符,按当前站点实现重写相关段落。文章需要图片时,先把资源放进 src/assets/img/blog/,再使用相对路径引用,并通过生产构建确认资源会被 Astro 正确处理。
复查
rg -n "TODO|待补|assets/img|!\[" src/content/blogcorepack pnpm build2026-07-10:图片优化后仍需处理交互争用
现象
Banner 同时支持自动轮播、鼠标悬停暂停、页面可见性暂停和移动端滑动时,状态容易互相打架。例如触摸滚动页面时误判为切换壁纸,或恢复后出现计时偏差。
原因
这些功能共享同一组计时器、动画播放状态和触摸坐标。只关闭事件绑定而不对应调整清理逻辑,也会在页面切换时留下不一致状态。
解决
当前脚本保留完整能力,但通过明确的功能开关关闭桌面悬停暂停和移动端左右滑动。事件注册与移除都使用同一开关条件,页面隐藏时仍会暂停计时,恢复后按剩余时间继续。
这种做法便于以后重新启用功能,但启用前必须重新完成鼠标、触控和 View Transition 的组合测试。
构建环境把 telemetry 权限问题误报成源码错误
现象
在受限沙箱里运行生产构建时,Astro 可能报 EPERM: operation not permitted, mkdir …。错误路径位于工作区之外的用户配置目录,源码甚至还没有开始编译。
原因
Astro 首次运行时会初始化 telemetry 配置。沙箱允许写项目目录,却不一定允许写系统用户目录,因此在编译前就被权限策略阻止。
解决
先确认报错目标确实是 Astro 的用户级配置目录,再按工具权限规则提升权限,重跑同一条 corepack pnpm build。不要因为这条 EPERM 去修改依赖、Astro 配置或页面源码。
中文文件显示乱码或被错误转码
现象
PowerShell 终端有时把 UTF-8 中文显示成乱码;更危险的是用系统默认编码批量写回文件,导致原本正常的 Markdown、Astro 或 JavaScript 真正损坏。
原因
“终端显示编码”和“文件实际编码”是两件事。只凭终端肉眼判断,再用 Set-Content 或重定向覆盖文件,会把显示问题变成文件问题。
解决
- 手工修改优先使用
apply_patch; - 读取中文文件时明确使用 UTF-8;
- 用 Node 按 UTF-8 读取关键行和码点确认文件内容;
- 批量替换后扫描 Unicode 替换字符和常见乱码痕迹;
- 已经损坏时,从 Git 中最近确认正常的版本恢复,再重新应用小范围改动。
favicon、OG 字体和浏览器缓存
favicon 仍显示旧图标
浏览器通常会长期缓存根路径 /favicon.ico。站点现在同时维护根路径和 public/img/ 中的副本,页面统一引用根路径;更新时需要同步替换,并在必要时修改版本参数或清理浏览器缓存。
OG 图片构建依赖外部字体
OG 图片需要在构建阶段渲染文字。如果字体来自 CDN,网络波动就可能让构建结果缺字或直接失败。现在中文字体放在 src/assets/fonts/ 本地维护,构建不再依赖远端字体服务。
教程截图泄露个人信息
现象
部署教程使用真实控制台截图时,图片里可能包含项目名称、域名、账号、DNS 记录或其他只属于站点维护者的信息。即使正文已经替换,图片仍可能保留原始内容。
原因
图片无法像文本一样被普通关键词搜索完整覆盖,裁剪也可能留下角落信息。真实界面还会随平台更新,很快变成过时教程。
解决
删除真实控制台截图,改用只保留操作关系的通用 SVG 示意图;示例统一使用占位域名和虚构名称。提交前还要同时检查文件名、图片文字、alt 文本和 Git diff。
一套可以重复使用的排查顺序
1. 内容层
检查 frontmatter、资源相对路径、字段语义和 Markdown 生成结果。先确认问题是否只出现在某一篇文章。
2. 构建层
运行生产构建,区分源码错误、telemetry 权限错误和外部资源错误。构建成功后检查最大产物与生成路由。
3. 运行时
从完整刷新和 Astro 客户端切换两条路径测试。检查控制台、Network、重复事件、计时器、播放器和观察器清理。
4. 部署与缓存
确认远端提交、Cloudflare Pages 部署版本、静态资源响应头、DNS 解析和浏览器缓存。不要在远端仍运行旧提交时继续改本地页面。
提交前检查清单
-
git status -sb中只有本轮预期文件; - 文章图片全部存在,alt 文本能说明图片内容;
- 没有真实域名、账号、邮箱、DNS 值等个人信息;
- 修改过的客户端脚本全部通过
node –check; -
corepack pnpm build构建成功; -
dist中没有超过平台限制的意外大文件; - 已扫描中文乱码和 Unicode 替换字符;
- 已清理
.astro、dist等构建产物; - 从完整刷新和站内页面切换两种入口都测试过关键交互。
小结
这段时间遇到的问题看起来分散,实际上反复落在几个共同点上:状态边界没有说清、构建环境与本地环境不同、资源预算被忽略,以及内容字段或图片没有和代码一起维护。
真正稳定的修复不只是“让页面现在能显示”,还要把原因写进代码结构、开发规范和复查步骤。这样下次出现相似现象时,可以先定位层级,再复用已经验证过的方法,而不是重新从猜测开始。