旧站是用 Hexo 搭的,前后加了七个插件:音乐播放器、看板娘、字数统计、访问量、动态背景、图片灯箱、还有一个我到现在都说不清干什么的加载动画。它们单独看都挺好,加在一起的结果是——首屏要等十二秒。
十二秒是什么概念?足够一个人从点开链接,到判断这个站不值得等,然后关掉。我自己的博客,我自己都懒得打开。
先搞清楚慢在哪
我用 Chrome 的性能面板跑了一遍,结论有点意外:不是图片太大,也不是服务器太慢,而是 JavaScript 太多。七个插件加起来引入了 1.4 MB 的脚本,其中大部分在首屏根本用不上。
更糟的是渲染阻塞。那些脚本全塞在 <head> 里同步加载,浏览器必须先下载、解析、执行完,才肯画第一个像素。
性能问题很少是「某个东西太慢」,多数时候是「不该在这一刻做的事,被安排在了这一刻」。
为什么选 Astro
换框架之前我对比了几个选项:
- Hugo —— 构建最快,但模板语法我始终不顺手,改一个卡片要翻半天文档。
- Next.js —— 生态最全,但为一个纯静态博客引入整个 React 运行时,太重了。
- Astro —— 默认输出零 JavaScript,组件写法接近 JSX,想加交互时还能局部「水合」。
最后一条是决定性的。它允许我只在需要的地方加载 JS,而不是整站背着一个框架跑。
改造过程
1. 把插件换成纯 CSS
动态背景、卡片悬浮、加载动画——这些原本都是 JS 驱动的,其实用 CSS 的 transition 和 @keyframes 就能做到,而且不阻塞渲染。
/* 原本 40 行 JS 的悬浮效果 */
.card {
transition: transform .28s cubic-bezier(.22, .61, .36, 1);
}
.card:hover {
transform: translateY(-3px);
}
2. 图片按需加载
封面图全部加上 loading="lazy",并且用 Astro 的 <Image> 组件自动生成 webp 和多种尺寸。这一项把首屏传输量从 3.2 MB 压到了 180 KB。
3. 字体本地化
原来用的是 Google Fonts,国内访问经常卡住,而且会阻塞渲染。换成系统字体栈之后,这一项直接归零——中文本来就不该依赖网络字体。
结果
首屏从 12.4 秒降到 0.4 秒,Lighthouse 四项全绿。但比数字更有意思的是:我开始愿意点开自己的博客了。
这件事让我重新想清楚一个问题:博客到底该为谁而快?不是为 Lighthouse,是为那个在手机上、在地铁里、只有三十秒耐心的人。
如果一篇文章需要读者等十二秒才能开始读,那它写得多好都已经输了一半。