我們如何在重建中達到 Lighthouse 100 分

說實話:我們的舊 WordPress 網站令人尷尬。不是因為它看起來很差 — 實際上看起來相當不錯。但引擎蓋下呢?3.2 秒的互動時間、Lighthouse 性能分數徘徊在 58 左右,以及一堆插件,讓每次部署都感覺像在拆解炸彈。我們是一家網頁開發機構。我們為客戶構建快速網站。而我們自己的網站是...不快。

所以我們拆掉它,用 Astro 重建。結果:在所有四個 Lighthouse 類別中獲得完美的 100 分 — 性能、無障礙、最佳實踐和 SEO。不是在單個頁面上。在每個頁面上。這是我們如何做到這一點、過程中發生了什麼故障,以及我們會做什麼不同的故事。

目錄

WordPress to Astro: How We Hit Lighthouse 100 on Our Rebuild

為什麼我們離開 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 — 不可怕,但不好。每次我們更新插件時,都有很小的概率某些東西會損壞。

真正的打擊?我們為一個每月只有大約 3,000 次訪問的網站支付 $80/月 的託管成本。那不是很多流量,而那對於本質上是一個有博客的宣傳冊網站來說是一筆巨大的錢。

關鍵時刻

最後的稻草出現在 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 週的兼職工作,同時進行客戶項目。

WordPress to Astro: How We Hit Lighthouse 100 on Our Rebuild - architecture

做出區別的架構決策

默認零 JavaScript

我們的整個網站總共只運送大約 2KB 的 JavaScript。那不是打字錯誤。兩千字節。其中大部分是移動導航切換和分析的小腳本。

以下是我們的移動導航 — 沒有框架,沒有依賴:

---
// MobileNav.astro
---
<button id="menu-toggle" aria-expanded="false" aria-controls="mobile-menu">
  <span class="sr-only">切換菜單</span>
  <svg><!-- hamburger icon --></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> 標籤會自動捆綁和去重。它很小,它是香草 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 殺手。以下是我們的方法:

  1. 自託管所有內容。 沒有 Google Fonts CDN。我們下載了 Inter 和 Cal Sans 並從我們自己的域名提供它們。這消除了對 fonts.googleapis.com 的 DNS 查詢、TCP 連接和 TLS 握手。

  2. 激進地縮減。 我們使用 glyphhanger 分析我們實際使用的字符,然後使用 pyftsubset 縮減我們的字體。我們的 Inter Regular WOFF2 從 96KB 縮小到 18KB。

  3. 使用 font-display: swap 與精心選擇的系統字體後備,緊密匹配指標,在交換期間最小化佈局偏移。

  4. 預載關鍵字體文件:

<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 Functions 進行伺服器端處理。沒有 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 的 schema 標記注射器和十四個插件樣式表時會發生的情況。

我們沿途做錯了什麼

並非一帆風順。是誠實的時候了。

錯誤 1:我們幾乎過度設計了內容管理

我們的第一直覺是為博客設置 Sanity 作為無頭 CMS。我們花了兩天時間配置架構並設置 Sanity Studio,然後退一步問,「誰實際上會使用這個?」答案是...我們。開發人員。誰對在 VS Code 中編寫 MDX 非常滿意。我們撕掉了 Sanity,改用 Astro 內容集合。節省了持續成本和複雜性。

錯誤 2:字體縮減打破了特殊字符

我們最初的字體子集過於激進。我們去掉了我們認為永遠不會使用的字符,然後發布了一篇包含 em 破折號和幾個彎引號的博客文章,這些字符被呈現為方框。課程:用真實內容測試您的子集,而不僅僅是「ABCDEFG」。

錯誤 3:我們忘記了 OpenGraph 圖像

我們啟動時沒有動態 OG 圖像。當有人在 Twitter/X 或 LinkedIn 上分享博客文章時,它顯示一個通用後備。我們必須回過頭去使用 @astrojs/og 構建 OG 圖像生成管道(在引擎蓋下使用 Satori)。應該已經在原始範圍內。

錯誤 4:301 重定向映射有空隙

儘管使用 Screaming Frog 映射舊 URL,我們錯過了一些外部網站正在熱鏈接的圖像 URL。我們在啟動後大約一週在 Cloudflare 的分析中發現了這些,並添加了缺失的重定向。始終在遷移後檢查您的伺服器日誌 — Google Search Console 不會捕獲所有內容。

您自己遷移的課程

如果您正在考慮從 WordPress 遷移到靜態優先框架,以下是我要告訴您的:

  1. 遷移前審計。 殺死表現不好的內容。遷移是修剪的好機會。

  2. 將工具與工作相匹配。 Astro 對我們來說是完美的,因為我們主要是內容。如果您需要大量交互,Next.js 或類似框架可能是更好的選擇。

  3. 不要複製粘貼您的舊架構。 我們沒有嘗試在 Astro 中複製我們的 WordPress 設置。我們從頭開始重新思考一切。我們實際上需要表單插件嗎?不,<form> 元素帶有無伺服器函數就很好。

  4. 測量前、測量後、持續測量。 我們在 GitHub Actions 中設置了一個 Lighthouse CI 作業,在每個拉取請求上運行。如果 PR 將任何分數降低到 95 以下,它將失敗檢查。

  5. 為「最後 5%」預算時間。 從 Lighthouse 85 到 95 很簡單。從 95 到 100 需要字體縮減、關鍵 CSS 分析、圖像格式優化和第三方腳本審計。為此預留時間。

  6. 您的託管成本應該令您的舊設置感到尷尬。 如果您提供靜態文件,仍然支付大量託管費用,出了問題。靜態託管現在是一種商品。

如果您有興趣了解這樣的遷移對您的項目會是什麼樣子,請查看我們的 定價頁面與我們聯繫。我們已經為幾個客戶進行過這個遷移路徑,性能增益始終很戲劇化。

常見問題

將 WordPress 網站遷移到 Astro 需要多長時間? 對於我們的網站(約 50 個頁面,包括博客文章),大約花了 6 週的兼職工作。擁有數百篇文章和複雜自訂帖子類型的較大網站可能需要 8-12 週。實際開發通常比內容審計和重定向映射要快。

您可以使用 Next.js 而不是 Astro 達到 Lighthouse 100 嗎? 這是可能的,但難度明顯更高。Next.js 即使對於靜態頁面也向瀏覽器發送 JavaScript 運行時(React 水合層)。您可以接近 — 95-99 的分數通過仔細優化是可以實現的。但 Astro 的零 JS 默認方法使內容網站的完美分數更容易達到。

WordPress 功能如聯繫表單和搜索呢? 聯繫表單適用於普通 HTML 表單和無伺服器函數後端(Cloudflare Pages Functions、Netlify Functions 等)。對於搜索,我們使用帶有 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 年底發布)是成熟和穩定的。保時捷、Google、Microsoft 和 Netlify 等公司在生產中使用它。構建性能也能很好地擴展 — 具有數千頁的網站在使用正確配置的情況下在一分鐘內構建。

與 WordPress 相比,持續維護是怎樣的? 戲劇性的少。沒有插件更新,沒有數據庫維護,沒有 PHP 的安全補丁。我們通過 Dependabot PR 大約每月更新一次 Astro 及其依賴項。每次更新大約需要 5 分鐘來審查和合併。與 WordPress 更新跑步機相比。

非技術團隊成員是否仍然可以在 Astro 網站上編輯內容? 使用我們的設置(Git 中的 MDX 文件),您需要習慣 Markdown 和基本 Git 工作流。對於擁有非技術編輯的團隊,我們建議將 Astro 與 Sanity、Contentful 或 Storyblok 等無頭 CMS 配對。編輯獲得視覺界面,您仍然獲得靜態生成的所有性能優勢。