
前两篇都在讲“别碰源码”。这一篇讲的正好相反:有四件事,配置层确实做不到,只能改。
既然要改,就先立规矩。
改源码之前先问三个问题
config/*.yaml里是不是真的没有对应开关?先去代码仓的src/config/README.md翻一遍- 如果只差“一点点”,能不能用自定义 CSS 覆盖,而不是改原文件?
- 改完之后,主题升级冲突了,我打算怎么合并?
第三个问题如果答不上来,先别改。这也是我把每次改动都记下来的原因。
一个必须知道的规矩:两处要同步
代码仓里有两个地方都定义了集成配置:
astro.config.mjs:构建时实际生效的那份src/integration/index.ts:npm 包shirones的镜像
主题同时以“源码项目”和“npm 包”两种形态发布,所以改了其中一处,另一处也要同步。只改一处的话,dev 看着是好的,发布成包之后就丢配置了。
我就因为这个多花了一轮排查。
开场动画
这是整个改造里投入最大的一块,前后两天。
起因很简单:看到一个参考站的开屏效果不错,想让自己的站也有。拆解之后发现实现不复杂,就是纯 CSS @keyframes 加一个 class 状态机,没有 Canvas、没有 WebGL,也不用引入 GSAP 那种动画库。
效果拆成四段
| 段 | 做什么 |
|---|---|
| 1 | 灰阶起手,左上角一个圆形扩散上色 |
| 2 | 站点名逐字掉落 |
| 3 | 按时段问候语打字机输出 |
| 4 | 整层上移,露出首页 |
全程 4.12 秒,后来调到大约 4.9 秒。
实现上是四个新文件,加上已有的 Layout.astro 里两行插入:
src/types/openingAnimationConfig.ts # 类型src/config/openingAnimationConfig.ts # 配置,默认 enable: falsesrc/utils/opening-animation.ts # 会话标记等纯逻辑src/components/organisms/OpeningCinema.astro # 组件本体src/layouts/Layout.astro # 插两行配置默认关着,所以不开这个功能的人项目里零 DOM、零请求。这是主题一贯的“零额外负担”原则,加新功能时也照这个来。
素材
两张图,桌面和手机分开,不共用:
| 桌面 | 手机 | |
|---|---|---|
| 规格 | WebP q82 · 1920×1080 | WebP q82 · 1170×2066 |
| 体积 | 190 KB | 136 KB |
| 留白 | 不需要(16:9 正好满幅) | 上下留白,用同一张图模糊放大填底 |
手机那块的留白别用纯色填,会露出接缝。用同一张图放大虚化(inset: -10% 加 blur)就看不出来了。
选图有个反直觉的地方:我一开始选的图被 banner 否掉过,理由是“一裁切就切到脸”。但开场遮罩是全屏展示、不裁切的,同一个容器换了,同一张图就从“不可用”变成了最优解。所以挑开场图的时候,别用横幅的裁切逻辑去判断。
三个坑,都挺值钱
坑一:会话标记写在哪儿,决定动画播不播。
“一个标签页只播一次”这件事,是靠一个会话标记实现的。我第一版把标记写在启动那一刻,结果 dev 冷启动时 Vite 会强制整页刷新两三次,标记先落地了,动画被重载打断,看起来就是永远不播。改成在动画结束时落标记就好了。
顺带说,这个标记在 sessionStorage 里,不是 localStorage。我在写验证脚本时设错过一次,白排查半天。
坑二:动效降级只认站点自己的开关。
主题原本同时看系统的 prefers-reduced-motion。问题是,Windows 用户在“辅助功能”里关掉动画效果之后,这个偏好就成立了,开场动画会被静默跳过。访客根本不知道是自己系统设置的问题,只会觉得“你这站坏了”。
后来我把全站的降级判断收敛成一个开关:只认站点显示设置里的“减少动态效果”,不看系统偏好。改动面不小,src/ 里有 26 个文件、28 处 @media (prefers-reduced-motion),测试里还有 18 个文件 24 处,一起清了。
坑三:起播时机比动画本身更影响流畅度。
我一直以为卡顿在动画里,换了几种测量方式之后才发现反了:动画期间其实已经满帧,卡顿集中在加载期的头两秒,因为圆扩散那一动画刚好撞上了首屏的长任务。
解法是给动画加一个起播门槛:等首屏安静下来(最近 200ms 内没有长任务)再开始。改完之后圆扩散那段的帧时间中位数从 33ms 降到 17ms。
这部分我有个 AI 助手陪着一起跑,从查源码到写测量脚本都是。说句公道话,它最大的用处不是写得快,是肯把“我以为”变成“我测了”。上面那个卡顿结论的翻转,就是它坚持换测量方式换出来的。
角色装饰带
参考站流行在页面底部摆一排角色立绘。我在两个地方各摆了一排:页脚和首页横幅底部。
页脚那排可以纯配置搞定:页脚支持注入一段 HTML,把 8 张图贴进去就行,不碰组件源码。
首页横幅那排不行。横幅是纯源码组件,没有页脚那种注入槽,也没有“往横幅塞装饰”的配置项,只能改 src/components/organisms/BannerStage.astro,加一个新图层。
尺寸这两个坑,我第一次全踩了
--strip-h 必须写 px,不能写 rem。
主题在窄屏会把根字号降到 14px。我写 2.875rem 以为等于 46px,实际只有 40.25px,差了 12%。
别用 vw 或 clamp 去算容器宽。
这是更隐蔽的一个。页脚的可用宽度不是跟着视口线性变的,它随栅格列数非单调跳变:1600 的视口给页脚 912px,1280 的视口反而只有 656px。
我第一版用 clamp(74px, 7.4vw, 112px) 算高度,结果 390px 宽的手机上整排溢出 57px。
改法是把高度当上限用,让容器自己缩:
.banner-stage__characters img { height: var(--strip-h); flex: 0 1 auto; min-width: 0; object-fit: contain; object-position: 50% 100%;}这样宽度不够时整排等比缩小,永不溢出、永不裁切,8 只画出来的高度自动相等。18 个屏幕档位测下来,溢出全部归零。
素材怎么来
我拿到的 8 张是纯白底、没有透明通道的 JPEG,直接放上去就是白方块,得先抠。
做法是从四边和四角洪泛填充挖掉白底,阈值给 30 左右。这样不会误伤角色内部的白色衣服(这几张图里近白像素占了四到七成,用整体去白的方式肯定出事)。贴边的 2px 过渡带按接近白的程度给半透明 alpha,最后预乘 alpha 再缩放。
最后一步不能省。不预乘的话,透明边缘的白色会渗进轮廓,缩完一圈黑晕。
友链申请页
需求是:友链页标题右边加一个按钮,点进去是一个独立的申请页,告诉别人怎么加我。
这一页有个让人意外的好消息:主题给每个代码块内置了复制按钮。所以整页只需要一份 Markdown,照样有“点一下复制”的体验,一行组件代码都不用写。
代价是纯 Markdown 只能单列流式排,做不出参考站那种左右两栏。我的判断是阅读顺序反而更顺,就接受了。
实现上照着主题已有的占位页写一个 src/pages/friends/apply.astro:从内容仓读一份 md、渲染进卡片里,标题取正文的一级标题,页面代码里零硬编码文案。
三个细节:
- 对外公示的头像要另存一份到
public/。assets/下的图走图像管线,产物 URL 带 hash,换头像 URL 就变,别人早就复制走的链接会失效。public/下文件名固定,换头像覆盖同名文件即可。 - 加国际化文案必须 10 个语言全加。那张表是穷尽类型,缺一个就编译报错。
- 标题栏没有预留按钮位,而且被十几个组件共用。我没去改它,而是把标题和按钮包进一个 flex 容器,样式上用
:global()穿透 Svelte 的作用域。
图标系统:一条最值钱的坑
这条如果不知道,能白排查一整天。
主题的图标是离线内联的,构建时从一个本地图标集合里取,运行时不联网。负责生成这个集合的脚本只扫 src/ 下六种扩展名:.astro、.md、.mdx、.svelte、.ts、.tsx。
.yaml 不在里面。
所以你在 config/*.yaml 里写一个从没用过的图标名,结果是:图标空白,零报错,零警告。构建成功,页面正常,就是那块地方什么都没有。
解法是在内容仓建一个 data/custom-icons.ts,把要用的图标按 "图标集:图标名" 的格式带前缀登记进去。这个文件在 src/ 下,会被扫到。
顺序也别错:
# 改 YAML → 同步 → 重新生成图标pnpm content:syncpnpm icons:generate这一轮改完,记得登记
我维护了一张改动登记表,每改一处填一行:日期、文件、改了什么、为什么配置做不到、升级冲突风险。
看着麻烦,但主题更新的时候它就是救命的东西,你不用去 diff 整个 src/,照着表把这几处重新打一遍即可。
小结
这一篇的四件事,按“要不要动”排序的话:
| 想要的效果 | 动源码吗 |
|---|---|
| 页脚放装饰带、改页脚内容 | 不用,有注入槽 |
| 友链申请页 | 要,但只是新增一个页面文件 |
| 首页横幅装饰带 | 要,横幅没有注入槽 |
| 开场动画 | 要,而且是新增一整套 |
下一篇是最后一篇,把这堆东西从本地推到线上:构建链路、GitHub Actions、服务器和域名。
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 18 天
部分内容可能已过时