WordPress 迁移到 Astro:我们如何在重建中达到 Lighthouse 100
我得老实跟你说:我们的旧 WordPress 网站很尴尬。不是因为它看起来很糟糕——实际上看起来还不错。但是在幕后?3.2 秒的交互时间,Lighthouse 性能评分徘徊在 58 左右,还有一堆插件让每次部署都感觉像在拆除炸弹。我们是一家网络开发机构。我们为客户构建快速网站。而我们自己的网站……并不快。
所以我们拆掉它,用 Astro 重建了。结果:四个 Lighthouse 类别中的完美 100 分——性能、可访问性、最佳实践和 SEO。不是在某个页面。是在每一个页面。这是我们如何做到这一点、过程中出了什么问题,以及我们会做什么不同的故事。
目录
- 为什么我们离开 WordPress
- 为什么我们选择 Astro
- 迁移策略
- 做出差异的架构决策
- 性能优化深度分析
- Lighthouse 100 成绩单
- 前后对比:数字
- 我们一路上搞错的地方
- 您自己迁移的经验
- 常见问题

为什么我们离开 WordPress
看,WordPress 驱动了大约 43% 的网络。这不是个坏平台。我们为客户构建了大量 WordPress 网站,如果合适的话会继续这样做。但对于我们自己的机构网站——一个主要是静态的营销网站加博客——WordPress 的方式太过了。
这是我们的 WordPress 设置:
- 主题:基于 Sage (Roots.io) 的自定义主题
- 插件:14 个活跃插件,包括 Yoast SEO、WP Rocket、Advanced Custom Fields Pro、Gravity Forms 和其他几个
- 托管:WP Engine Professional 计划,每月 $60
- CDN:Cloudflare Pro,每月 $20
- 构建复杂性:PHP 模板、Webpack 资源、MySQL 数据库
即使有 WP Rocket 进行积极缓存,我们的 Core Web Vitals 也很平庸。移动设备上的最大内容绘制 (LCP) 是 2.4 秒。累积布局偏移 (CLS) 是 0.12——不算糟糕,但也不好。而且每次更新插件时,都有可能会出问题。
真正的问题是什么?我们每月支付 $80 的托管费用来维护一个仅获得大约 3,000 次访问的网站。这流量不多,对于一个本质上是展示网站加博客的东西来说,这是一笔很大的费用。
临界点
最后一根稻草出现在 2025 年 1 月。WordPress 核心更新破坏了我们的自定义 Gutenberg 块。修复它需要更新 ACF Pro,这需要更新我们主题的 PHP 版本兼容性,这需要更新托管环境。本应是一个例行更新的事情变成了一整天的工作。
我看着我的团队说:"我们告诉客户要去无头架构。我们为什么不吃自己的狗粮呢?"
为什么我们选择 Astro
我们评估了四个重建选项:
| 框架 | 优点 | 缺点 | 我们的评估 |
|---|---|---|---|
| Next.js | 我们很熟悉,生态系统很好 | 对于内容网站来说太重了,需要服务器或边缘运行时 | 太重了 |
| Astro | 以内容为中心,默认不发送 JS,岛屿架构 | 生态系统较小,较新 | 完美契合 |
| Eleventy | 简单,快速构建,成熟 | 有限的组件模型,DX 不够现代 | 次选 |
| Hugo | 构建速度快如闪电,单一二进制文件 | Go 模板令人痛苦,灵活性有限 | 不适合我们 |
我们为客户构建大量 Next.js 项目,这是我们对任何具有动态功能的东西的首选。但对于内容密集的营销网站?Next.js 无论如何都会发送 JavaScript 运行时。即使使用静态导出,您也在向浏览器发送 React。
Astro 的理念引起了我们的共鸣:发送 HTML,仅在需要时添加 JavaScript。他们的岛屿架构意味着您可以拥有一个完全交互式的 React 组件,坐在完全静态的 HTML 旁边,而静态部分则不发送任何 JavaScript。这正是我们需要的。
我们在整个 2024 年也在为客户做更多 Astro 开发工作,所以团队对框架很熟悉。这不是学习练习——这是一个我们已经信任的工具。
内容层问题
我们早期做出的一个决定:我们不会为自己的网站使用无头 CMS。对于客户项目,我们经常推荐 无头 CMS 设置,使用 Contentful、Sanity 或 Storyblok。但对于我们的博客,每个作者都是开发人员,对 Markdown 和 Git 很熟悉?Astro 中的内容集合与提交到仓库的 MDX 文件更简单、更快。
构建时没有 API 调用。没有内容交付网络。没有额外的服务来管理或付费。只是文件夹中的文件。
迁移策略
我们没有进行大爆炸式迁移。这是我们的分阶段方法:
第 1 阶段:内容审计(1 周)
我们使用 wp-cli 导出所有 WordPress 内容,并使用用 turndown(HTML 转 Markdown 转换器)加上一些正则表达式清理构建的自定义脚本将帖子转换为 MDX。当时我们有 47 篇博客文章。其中大约 12 篇已过时或表现不佳,所以我们将这些重定向到相关的较新内容,没有迁移它们。
第 2 阶段:Astro 中的设计系统(2 周)
我们将组件库重建为 Astro 组件。按钮、卡片、部分布局、导航——全部作为 .astro 文件。不需要任何框架。纯 HTML 和带有作用域样式的 CSS。
第 3 阶段:页面构建(2 周) 首页、能力页面、关于、联系、博客列表、个人博客文章、404。我们都用我们的组件库将它们构建为 Astro 页面。
第 4 阶段:性能调优(1 周) 这是 Lighthouse 100 工作真正发生的地方。下面有更多内容。
第 5 阶段:启动和重定向(2 天) 我们为每个旧 URL 设置了适当的 301 重定向,用 Screaming Frog 验证没有任何问题,向 Google Search Console 提交了新站点地图,并进行了 DNS 切换。
总时间表:大约 6 周的兼职工作,同时进行客户项目。

做出差异的架构决策
默认零 JavaScript
我们的整个网站总共发送大约 2KB 的 JavaScript。这不是打字错误。两千字节。其中大部分是用于移动导航切换和分析的小脚本。
这是我们的移动导航——没有框架,没有依赖:
---
// MobileNav.astro
---
<button id="menu-toggle" aria-expanded="false" aria-controls="mobile-menu">
<span class="sr-only">切换菜单</span>
<svg><!-- 汉堡菜单图标 --></svg>
</button>
<nav id="mobile-menu" hidden>
<slot />
</nav>
<script>
const toggle = document.getElementById('menu-toggle');
const menu = document.getElementById('mobile-menu');
toggle?.addEventListener('click', () => {
const expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!expanded));
menu?.toggleAttribute('hidden');
});
</script>
Astro 组件中的 <script> 标签会自动打包和去重。它很小,它是 vanilla JS,它在任何地方都有效。
CSS 策略:作用域样式 + 最小全局层
我们对组件级样式使用了 Astro 的内置作用域 CSS,以及一个单一的全局样式表(约 8KB 压缩)用于排版、重置、自定义属性和实用类。没有 Tailwind。我知道这是个有争议的看法。
我们喜欢在较大的应用程序和客户项目中使用 Tailwind。但对于这么小的网站,它增加了我们不需要的构建复杂性和文件大小。我们手写的 CSS 比 Tailwind 的输出要小,即使有清除也是如此。
/* 全局自定义属性 */
:root {
--color-text: #1a1a2e;
--color-bg: #ffffff;
--color-accent: #e94560;
--color-accent-dark: #c81e45;
--font-body: 'Inter', system-ui, sans-serif;
--font-heading: 'Cal Sans', var(--font-body);
--max-width: 72rem;
--space-unit: 0.25rem;
}
具有智能预加载的静态生成
每个页面都在构建时静态生成。我们使用 Astro 的内置 prefetch 集成在悬停时预加载链接,使导航感觉瞬间完成:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://socialanimal.dev',
integrations: [mdx(), sitemap()],
prefetch: {
prefetchAll: false,
defaultStrategy: 'hover',
},
build: {
inlineStylesheets: 'auto',
},
});
性能优化深度分析
达到 Lighthouse 100 不仅仅是选择正确的框架。Astro 给了你一个领先的开始,但最后 10-15 分需要深思熟虑的努力。这是我们所做的。
图像优化
Astro 的内置 <Image /> 组件处理响应式图像,自动格式转换(WebP/AVIF)、延迟加载以及适当的 width/height 属性以防止 CLS。
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<Image
src={heroImage}
alt="Social Animal 开发团队正在处理无头架构"
widths={[400, 800, 1200]}
sizes="(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px"
format="avif"
fallbackFormat="webp"
quality={80}
loading="eager"
/>
对于英雄图像特别是,我们使用 loading="eager",因为它在视口上方。其他所有内容默认获得 loading="lazy"。
我们还查看了网站上的每个图像并问:这个真的需要是图像吗?几个装饰元素变成了 CSS 渐变或 SVG。例如,我们的英雄部分背景是一个 CSS 渐变,应用了通过一个微小的内联 SVG 应用的细微噪声纹理。
字体加载策略
字体是 Lighthouse 的杀手。这是我们的方法:
自己托管一切。 没有 Google Fonts CDN。我们下载了 Inter 和 Cal Sans,从我们自己的域提供。这消除了对 fonts.googleapis.com 的 DNS 查询、TCP 连接和 TLS 握手。
积极子集。 我们使用
glyphhanger分析我们实际使用的字符,然后用pyftsubset对字体进行子集处理。我们的 Inter Regular WOFF2 从 96KB 降到了 18KB。使用
font-display: swap加上仔细选择的系统字体回退,该字体与指标紧密匹配,最大限度地减少交换期间的布局偏移。预加载关键字体文件:
<link rel="preload" href="/fonts/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/cal-sans-latin-600.woff2" as="font" type="font/woff2" crossorigin />
托管:Cloudflare Pages
我们从 WP Engine($60/月)迁移到 Cloudflare Pages(免费层)。是的,免费。我们的网站完全在 Cloudflare 免费计划的限制范围内——每月 500 次构建、无限带宽、无限请求。
Cloudflare Pages 从 Git 推送部署,从他们的全球边缘网络提供,并自动处理缓存头。对于我们的整个网站,构建时间平均 22 秒。相比之下,我们的 WordPress 设置中缓存清除本身可能花费更长时间。
每月托管成本从 $80 降到了 $0。
关键 CSS 内联
当您设置 build.inlineStylesheets: 'auto' 时,Astro 会自动内联小样式表。对于我们的页面,每个关键样式都内联在 <head> 中,这意味着没有渲染阻止的 CSS 请求。浏览器可以立即开始绘制。
第三方脚本纪律
这是大多数网站丢失完美分数的地方。每个第三方脚本都是一个潜在的性能灾难。我们无情地限制了我们的脚本:
- 分析:从 Google Analytics(70KB+ JavaScript)切换到 Plausible Analytics(< 1KB 脚本,异步加载)。我们为 Plausible 支付 $9/月,数据质量对我们的需求来说真的更好。
- 表格:我们位于 /contact 的联系表使用一个简单的 HTML 表,通过 Cloudflare Pages 函数进行服务器端处理。没有 JavaScript 表库。
- 没有聊天小部件。 没有社交媒体嵌入。没有 cookie 同意横幅(我们不使用需要同意的 cookie)。
Lighthouse 100 成绩单
以下是我们截至 2025 年 5 月的实际 Lighthouse 分数,使用 Chrome DevTools 在受限连接(Lighthouse 默认移动模拟)上测量:
| 指标 | 分数 |
|---|---|
| 性能 | 100 |
| 可访问性 | 100 |
| 最佳实践 | 100 |
| SEO | 100 |
| 首次内容绘制 | 0.6s |
| 最大内容绘制 | 0.8s |
| 总阻止时间 | 0ms |
| 累积布局偏移 | 0 |
| 速度指标 | 0.8s |
0ms 的总阻止时间是我最喜欢的统计数据。零。基本上没有 JavaScript 阻止主线程。曾经。
前后对比:数字
| 指标 | WordPress(之前) | Astro(之后) | 改进 |
|---|---|---|---|
| Lighthouse 性能 | 58 | 100 | +72% |
| LCP(移动) | 2.4s | 0.8s | 快 3 倍 |
| CLS | 0.12 | 0 | 消除 |
| TBT | 380ms | 0ms | 消除 |
| 页面权重(首页) | 1.8MB | 142KB | 小 92% |
| HTTP 请求 | 47 | 6 | 减少 87% |
| 发送的 JavaScript | 340KB | 2KB | 减少 99.4% |
| 每月托管成本 | $80 | $9(仅 Plausible) | 便宜 89% |
| 构建/部署时间 | 3-5 分钟 | 22 秒 | 快 ~10 倍 |
| 首字节时间 | 420ms | 18ms | 快 23 倍 |
页面权重的减少甚至令我们感到震惊。从 1.8MB 到 142KB。这就是停止发送 jQuery、React、WP Rocket 的脚本加载器、Yoast 的架构标记注入器以及十四个插件样式表的结果。
我们一路上搞错的地方
这不是一帆风顺的。坦诚时刻。
错误 1:我们几乎过度工程化了内容管理
我们最初的本能是为博客设置 Sanity 作为无头 CMS。我们花了两天时间配置架构并设置 Sanity Studio,然后退一步问:"谁实际上会使用这个?"答案是……我们。开发人员。他们完全乐意在 VS Code 中编写 MDX。我们拆掉 Sanity,转向 Astro 内容集合。节省了持续的成本和复杂性。
错误 2:字体子集破坏了特殊字符
我们最初的字体子集太激进了。我们删除了我们认为永远不会使用的字符,然后发布了一篇包含 em dash 和几个花引号的博客文章,它们显示为方块。课程:用实际内容测试你的子集,而不仅仅是"ABCDEFG"。
错误 3:我们忘记了 OpenGraph 图像
我们推出时没有动态 OG 图像。当有人在 Twitter/X 或 LinkedIn 上分享博客文章时,它显示了一个通用的回退。我们必须回过头来使用 @astrojs/og(它在幕后使用 Satori)构建一个 OG 图像生成管道。应该在原始范围内。
错误 4:301 重定向映射有漏洞
尽管使用 Screaming Frog 映射旧 URL,我们仍然错过了一些外部网站被热链接的图像 URL。我们在启动约一周后在 Cloudflare 的分析中发现了这些,并添加了缺失的重定向。始终在迁移后检查您的服务器日志——Google Search Console 不会捕获所有内容。
您自己迁移的经验
如果您考虑从 WordPress 迁移到静态优先框架,这是我要告诉你的:
迁移前进行审计。 删除表现不佳的内容。迁移是修剪的绝好机会。
将工具与工作相匹配。 Astro 对我们来说很完美,因为我们主要是内容。如果您需要大量交互,Next.js 或类似框架可能更好。
不要复制粘贴你的旧架构。 我们没有尝试在 Astro 中复制我们的 WordPress 设置。我们从头开始重新考虑一切。我们是否真的需要表单插件?不,一个
<form>元素加上一个无服务器函数就可以了。事前测量,事后测量,持续测量。 我们在 GitHub Actions 中设置了一个 Lighthouse CI 作业,在每个拉取请求上运行。如果 PR 将任何分数降低到 95 以下,它会失败检查。
为"最后 5%"预算。 从 Lighthouse 85 到 95 很简单。从 95 到 100 需要字体子集、关键 CSS 分析、图像格式优化和第三方脚本审计。为此计划时间。
您的托管成本应该让您的旧设置感到尴尬。 如果您正在提供静态文件但仍在支付大量托管费用,那么出了问题。静态托管现在是一个商品。
如果您对像这样的迁移对您的项目会是什么样子感兴趣,请查看我们的 定价页面 或 与我们联系。我们现在为多个客户完成了这个迁移路径,性能收益始终很显著。
常见问题
将 WordPress 网站迁移到 Astro 需要多长时间? 对于我们的网站(包括博客文章大约 50 页),大约花费了 6 周的兼职工作。有数百篇文章和复杂自定义文章类型的较大网站可能需要 8-12 周。实际开发通常比内容审计和重定向映射要快。
您可以用 Next.js 代替 Astro 获得 Lighthouse 100 吗? 这是可能的,但要困难得多。Next.js 即使对静态页面也会向浏览器发送 JavaScript 运行时(React 水合层)。您可以接近——95-99 的分数对于内容网站来说是可以通过仔细优化实现的。但 Astro 的零 JS 默认方法使内容网站的完美分数更容易实现。
WordPress 功能呢,比如联系表单和搜索? 联系表单可以使用普通 HTML 表单和无服务器函数后端(Cloudflare Pages 函数、Netlify 函数等)正常工作。对于搜索,我们使用带有 Pagefind 的客户端搜索,它在构建时生成搜索索引,仅发送 5KB 的 JavaScript。它快速且可以离线工作。
从 WordPress 迁移到 Astro 会伤害 SEO 吗? 如果处理正确,则不会。我们为每个 URL 设置了 301 重定向,尽可能保持了我们的 URL 结构,提交了新站点地图,并保留了所有结构化数据。我们的有机流量实际上在迁移后的三个月内增长了 23%,可能是由于 Core Web Vitals 的改进。
如何在 Astro 网站上处理动态内容,如博客评论? 我们的博客上没有评论——它们在 WordPress 上基本上都是垃圾邮件。如果您需要评论,Giscus(基于 GitHub Discussions)或 Hyvor Talk 等服务作为嵌入式组件可以很好地工作。它们作为 Astro 岛屿加载,因此不会影响初始页面加载。
Astro 对大型网站生产就绪吗? 绝对是。Astro 5.x(于 2024 年末发布)成熟且稳定。Porsche、Google、Microsoft 和 Netlify 等公司在生产中使用它。构建性能也能很好地扩展——具有数千页的网站在正确配置下在一分钟内构建。
与 WordPress 相比,持续维护是什么样的? 戏剧性地更少。没有插件更新、没有数据库维护、没有 PHP 安全补丁。我们每月通过 Dependabot PRs 更新 Astro 及其依赖关系大约一次。每次更新花费大约 5 分钟来审查和合并。相比之下,WordPress 更新跑步机。
非技术团队成员仍然可以在 Astro 网站上编辑内容吗? 使用我们的设置(Git 中的 MDX 文件),您需要熟悉 Markdown 和基本的 Git 工作流。对于拥有非技术编辑的团队,我们建议将 Astro 与无头 CMS(如 Sanity、Contentful 或 Storyblok)配对。编辑获得可视界面,您仍然获得静态生成的所有性能优势。