最近对博客系统做了一轮集中更新。这篇文章不是“我怎么修复的”,而是根据 Git 里真实发生的改动,把它们整理成一份可读的更新说明:改了什么、为什么改、可能带来什么影响,以及你部署前需要确认哪些配置。
变更统计:22 个文件改动,约 +220 / -73。
1. 配置与隐私:Umami 统计从“硬编码”切换为“环境变量”
这次最大的方向之一,是把统计相关的敏感信息从仓库源码里移走。
发生了什么
src/config.tsumamiConfig.apiKey不再提供默认 key,改为只读环境变量:UMAMI_API_KEY。data-website-id改为从环境变量注入:UMAMI_WEBSITE_ID。
src/components/widget/Profile.astro- 不再从脚本字符串里用正则解析
data-website-id,改为直接读取UMAMI_WEBSITE_ID。
- 不再从脚本字符串里用正则解析
你需要做什么
如果你希望启用 Umami:
- 在部署平台环境变量中配置:
UMAMI_API_KEYUMAMI_WEBSITE_ID
否则统计功能会按“未配置”处理(这是预期行为)。
2. 构建性能:Rollup 手动拆包(manualChunks)
为了让首屏与缓存更稳定,本次在 astro.config.mjs 增加了 rollupOptions.output.manualChunks,将部分重依赖从 node_modules 中拆出来。
变化点
按依赖类型拆分为:
vendor-sveltevendor-vuevendor-math(KaTeX/rehype-katex/remark-math)vendor-mermaid
可能的影响
- 产物 chunk 命名与结构会变化。
- 如果你有 CDN 缓存策略或自定义资源预加载规则,需要确认是否仍匹配。
3. 页面体验:主题默认值更贴近系统偏好
在布局(src/layouts/Layout.astro)里,主题读取逻辑做了增强:
- 如果本地没有存储
theme,会读取系统prefers-color-scheme。 - 让首次访问的默认主题更符合用户系统设置。
4. 轮播稳定性:统一清理 interval,避免切页后残留
同样是在 src/layouts/Layout.astro,轮播逻辑引入了全局 interval 状态与 cleanupCarousel():
- 在初始化轮播前先清理可能存在的旧定时器。
- 在触摸暂停、鼠标悬停、以及页面跳转(swup)等时机主动清理。
这类改动的目标很明确:避免轮播重复启动、多个 interval 叠加、切页后仍在后台运行。
5. 订阅输出:Atom/RSS 生成更健壮(XML 转义)
在 src/pages/atom.xml.ts 新增了 escapeXml(),并对 title/subtitle/summary/author/category 等字段做 XML 转义。
为什么要做
当文章标题或摘要里包含 & < > ' " 这类字符时,未转义可能导致 feed 解析失败。现在对这些字段进行转义后,订阅兼容性会更稳。
6. 搜索组件:事件与定时器清理 + 样式隔离,减少“残留”和安全风险
src/components/Search.svelte 做了两类增强:
6.1 初始化更稳
- 对
pagefindready/pagefindloaderror使用具名 handler 注册,组件卸载时能正确 remove。 - 增加 fallback timeout(2 秒兜底),并在卸载时清理。
6.2 excerpt 样式隔离
搜索结果使用 {@html item.excerpt} 渲染摘要。本次新增了 .search-result-excerpt 包裹,并用 CSS 将其内部样式“收敛”,避免摘要内容通过样式影响页面其他区域。
7. 移动目录(MobileTOC):滚动节流 + 监听器可正确移除
src/components/MobileTOC.svelte 的改动重点是性能与可维护性:
- 新增
throttle()对滚动更新做节流(降低滚动时的计算频率)。 popstate监听使用可复用引用,卸载时能正确移除。scroll监听使用{ passive: true },更友好。
8. 加密文章:密钥派生从 bcrypt 子串切换为 SHA256(password)
这是一项“行为层面”的改动,涉及:
src/pages/posts/[...slug].astro(服务端加密)src/components/PasswordProtection.astro(前端解密)
现在加密/解密都使用:
CryptoJS.SHA256(password).toString()
你需要注意
- 如果你过去已经发布过使用旧派生逻辑加密的文章,旧内容可能需要重新加密,或提供兼容迁移方案。
9. 评论 Twikoo:重试加上上限,避免无限循环
src/components/comment/Twikoo.astro 增加了最大重试次数:
- 最多重试 20 次(约 10 秒)
- 超时后停止初始化并输出 warn
10. 图片加载:ImageWrapper 支持 loading/decoding
src/components/misc/ImageWrapper.astro 新增参数:
loading(默认lazy)decoding(默认async)
让你在需要“首屏必须立刻显示”的图片场景,可以显式切到 eager。
11. 外链安全:补齐 noopener/noreferrer
多个页面与组件对 target="_blank" 的外链补充或统一了 rel="noopener noreferrer",覆盖范围包括:
License、Profile、friends/projects/timeline等页面/组件
目的是避免 window.opener 带来的潜在安全风险。
12. 音乐播放器与樱花特效:统一解决“监听器移除失败”与资源清理
src/components/widget/MusicPlayer.svelte- 将匿名监听器改为可追踪 handler,并在销毁时统一移除。
src/utils/sakura-manager.ts- 缓存
resizehandler 引用,确保removeEventListener有效。
- 缓存
这类改动通常不“显眼”,但对长时间使用、频繁切页的站点非常关键。
部署前自检清单(建议)
- Umami
UMAMI_API_KEY是否已在环境变量配置?UMAMI_WEBSITE_ID是否已在环境变量配置?
- 加密文章
- 是否存在历史加密文章?如果有,确认是否需要重新加密/迁移。
- 构建与缓存
- 拆包后 chunk 名称变化,CDN 缓存/预加载策略是否仍然匹配?
- 订阅
- 用一个 RSS/Atom 阅读器(或在线校验工具)验证
atom.xml是否可解析。
- 用一个 RSS/Atom 阅读器(或在线校验工具)验证
如果你希望我把这篇文章的语气改得更“叙事化”(更像你 01/18 那种文风),或者需要我顺手加一张封面图字段 image: "./1.png" 并放入图片文件,我也可以继续帮你补齐。
部分信息可能已经过时




