我一直想把我的個人網站升級到Astro 6。發布說明在我的瀏覽器標籤頁裡躺了好幾個星期,每次想起來升級的時候,總能找到藉口去做別的事。這週,我終於沒藉口了。我抽出一個下午,執行了npx @astrojs/upgrade ,祈禱一切順利,期待著升級成功。

開發伺服器立即崩潰,並出現一個關於缺少tailwindcss套件的神秘錯誤。

我盯著錯誤看了一分鐘。然後,我做了任何一個理智的開發者在2026年都會做的事——我引入了一個人工智慧編碼代理,讓它幫我修復所有問題。

這篇文章正是我夢寐以求的實戰指南,同時也提醒我們,人工智慧代理雖然非常有用,但卻過於自信,存在安全隱患。你仍然需要清楚自己在做什麼。

我最初的想法

  • Astro 5.x(各種補丁版本)

  • @astrojs/cloudflare v12.x

  • @astrojs/tailwind v5.x

  • 舊版內容集合( src/content/config.tstype: 'content' / 'data'

  • astro-expressive-code v0.38.x

  • astro-icon v1.1.5

我最終得到的

  • Astro 6.2

  • @astrojs/cloudflare v13

  • Tailwind CSS v4 ( @tailwindcss/vite )

  • astro-expressive-code v0.41.7

  • 自訂內聯 SVG 圖示元件(替換astro-icon

錯誤 1: Cannot find package 'tailwindcss'

Cannot find package 'tailwindcss' imported from
.../node_modules/@astrojs/tailwind/dist/index.js

發生了什麼事

透過升級指令安裝了@astrojs/tailwind v6,但它的package.json中只將tailwindcss列為對等依賴項,並沒有將其打包。由於tailwindcss不在我的dependencies中,Node 無法解析它。

代理人的診斷

我把錯誤訊息貼到代理程式中,詢問發生了什麼事。它立即診斷出是依賴項問題,並自信地轉向了 PostCSS。它新增了postcss.config.mjsautoprefixed@tailwind指令。網站恢復了功能,但方法完全錯誤。

我不得不要求代理人繼續使用 TailwindCSS 並遷移到 PostCSS。我要求代理人查閱 Astro 的文件,而不是憑空猜測。代理人隨後使用相關工具,提出了兩種方案:

方案A:繼續使用Tailwind 3(最簡單)

安裝tailwindcss@3並同時進行集成,保持所有設定不變:

npm install tailwindcss@3

您的astro.config.mjs保持不變:

import tailwind from '@astrojs/tailwind';
// ...
integrations: [tailwind()]

這是 Astro 文件推薦用於舊版 Tailwind 3 專案的路徑。

方案 B:升級到 Tailwind 4

Astro 5.2+ 包含一個astro add tailwind指令,用於安裝官方的 Vite 外掛程式 ( @tailwindcss/vite ),這是在 Astro 中使用 Tailwind 4 的新建議方法。

npx astro add tailwind

這就建立了以下關係:

  1. 在您的 Vite 外掛程式中設定@tailwindcss/vite (透過astro.config.mjs

  2. src/styles/global.css中使用@import "tailwindcss";

  3. v4 版本不再需要tailwind.config.mjs文件,而是使用基於 CSS 的配置。

如果採用這種方法,您可以完全移除@astrojs/tailwind ,並按照Tailwind 的 v4 升級指南將您的自訂主題遷移到 CSS 變數。

接下來發生的事情:正確的方法

我指示代理人執行方案 B ,執行npx astro add tailwind來設定正確的 Vite 插件,然後將自訂主題遷移到global.css中的新@theme區塊中:

@import "tailwindcss";

@theme {
  --color-primary: #f97316;
  --color-hover: #ea580c;
  --color-light: rgba(249, 115, 22, 0.15);
  --color-secondary: #fdba74;
}

@variant dark (&:where(.dark, .dark *));

如果你想保留 Tailwind 3:使用上面的選項 A,讓@astrojs/tailwind來完成工作。

如果你想使用 Tailwind 4:請使用選項 B 和官方的 Vite 插件。不要手動設定 PostCSS。

錯誤 2: LegacyContentConfigError

搞定 Tailwind 之後,我滿懷希望地重啟了開發伺服器。結果下一個錯誤又出現了。

[LegacyContentConfigError] Found legacy content config file in
"src/content/config.ts". Please move this file to
"src/content.config.ts" and ensure each collection has a loader defined.

發生了什麼事

Astro 5 引入了內容層 API ,但保留了對舊集合的自動向後相容性。 Astro 6 完全取消了此安全機制。我的src/content/config.ts檔案中包含type: 'content'type: 'data'配置不再有效。

修復

代理程式出色地完成了此次遷移。它移動了文件,重寫了導入語句,並配置了載入器:

前:

import { defineCollection, z } from 'astro:content';

const writings = defineCollection({
  type: 'content',
  schema: z.object({ ... })
});

const projects = defineCollection({
  type: 'data',
  schema: z.array(z.object({ ... }))
});

export const collections = { writings, projects };

後:

import { defineCollection } from 'astro:content';
import { glob, file } from 'astro/loaders';
import { z } from 'astro/zod';

const writings = defineCollection({
  loader: glob({ pattern: '**/[^_]*.mdx', base: './src/content/writings' }),
  schema: z.object({ ... })
});

const projects = defineCollection({
  loader: file('src/content/projects/projects.json'),
  schema: z.object({ ... })  // not z.array(...)
});

export const collections = { writings, projects };

主要變化:

  • 檔案位置: src/content/config.tssrc/content.config.tssrc/目錄下的專案根目錄)。

  • z導入: astro:contentastro/zod

  • type已移除:不再允許type: 'content'type: 'data' 。您需要明確聲明一個loader

  • 資料集合:如果您使用type: 'data'並傳入 JSON 文件,則新的file()載入器會為每個頂層物件傳回一個條目。模式應該是z.object(...) (單一條目),而不是z.array(...) (整個檔案)。

  • slugid在舊版 API 中, entry.slug是自動產生的。在新版 API 中, entry.id是辨識碼。我的 URL 需要更新:

// Before
href={`/writings/${post.slug}`}
// After
href={`/writings/${post.id}`}

這裡是代理程式越權的地方。它告訴我,由於我的貼文都儲存在folder/index.mdx結構中, glob()會根據檔案路徑產生 ID,產生類似migrating-astro-5-to-astro-6/index的檔案。它建議我去掉後綴:

href={`/writings/${post.id.replace(/\/index$/, '')}`}

總覺得哪裡不對勁。我writings庫裡的每篇文章在 frontmatter 裡都有slug字段,我預感 Astro 會用它作為文章id 。於是我提出異議,要求客服人員對照 Astro 的文件核實。

查閱文件後,無法確認當 frontmatter 中存在slug時, /index是否會被附加。實際上, post.id始終是migrating-astro-5-to-astro-6 ,而不是migrating-astro-5-to-astro-6/index 。對於我的配置來說, .replace()是不必要的,簡單的post.id就能正常運作。

注意:務必將代理程式的輸出與您自己的程式碼和建置輸出進行比對。代理程式執行速度很快,但最終發布它的責任在於您。

一切都還不錯。經紀人幫我節省了好幾個小時。但後來他變得自大起來。

錯誤 3: Property 'runtime' does not exist on type 'Locals'

內容集合已修復。我準備查看網站渲染效果。但 Cloudflare 適配器卻另有打算。

ts(2339): Property 'runtime' does not exist on type 'Locals'.

發生了什麼事

@astrojs/cloudflare v13 完全移除了Astro.locals.runtime 。新的文件說明如下:

import { env } from 'cloudflare:workers';
const kv = env.MY_KV;

我已將 API 路由遷移到這種模式。但是,我在開發環境中遇到了執行時錯誤:

module is not defined

源自 Cloudflare Vite 插件的工作進程。

客服人員花了不少時間嘗試各種隨機的修復方法——清除快取、重新排序導入、檢查 Vite 配置——但這些都沒用。最後我自己找到了問題所在: @astrojs/cloudflare v13 的開發伺服器執行在workerd內部,它與astro-icon整合有相容性問題。當astro-icon<Icon>元件首次渲染時,workerd 模組執行器會崩潰,並出現module is not defined神秘錯誤,導致網站上的所有路由都無法正常運作。

此時,它感到很沮喪。它已經在這件事上花費了比預期更多的時間。為了讓某些功能正常執行,它不得不降級回@astrojs/cloudflare v12 版本。

但我們並沒有就此止步。代理人建議用一個小型自訂元件完全取代astro-icon該元件會內聯來自@iconify-json/mdi的 SVG 路徑。只需三十行程式碼,無需虛擬模組,也不存在workerd相容性問題。我們嘗試了一下,然後切換回 v13 版本,問題就解決了。

解決方法:正確完成 v13 遷移。

首先,更新wrangler.toml以使用 v13 入口點:

main = "@astrojs/cloudflare/entrypoints/server"

然後將所有程式碼從Astro.locals.runtime.env遷移到import { env } from 'cloudflare:workers' :

前:

const { env } = Astro.locals.runtime;
const kv = env.VOTES;

後:

import { env } from 'cloudflare:workers';
const kv = env.VOTES;

對於 TypeScript,我還必須在src/env.d.ts中擴充Cloudflare.Env ,新增wrangler.toml中未宣告的金鑰(例如YOUTUBE_API_KEYGITHUB_TOKEN ):

declare namespace Cloudflare {
  interface Env {
    YOUTUBE_API_KEY: string;
    PLAYLIST_ID: string;
    GITHUB_TOKEN: string;
  }
}

注意:代理程式不知道wrangler types命令。此命令會產生類型,從而避免手動新增類型。

這是必要的,因為import { env } from 'cloudflare:workers'是針對全域Cloudflare.Env介面進行類型定義的,而不是針對wrangler types產生的專案級Env進行類型定義。

最後,從package.jsonastro.config.mjs中移除astro-icon ,並將所有<Icon name="mdi:github" />的用法替換為自訂元件。問題解決。

錯誤 4: astro-expressive-code對等依賴項不匹配

那是最大的挑戰。我以為已經萬事大吉了。結果npm run build提醒我,整合也有自己的時間表。

peer astro@"^4.0.0-beta || ^5.0.0-beta || ^3.3.0" from [email protected]

發生了什麼事

升級指令沒有更新astro-expressive-code ,因此它的對等依賴範圍仍然排除了 Astro 6。

修復

npm install [email protected]

v0.41.7 正式支持 Astro 6。

這位經紀人第一次就猜對了。能贏就贏,我都欣然接受。

錯誤 5: Buffer<ArrayBufferLike>' is not assignable to parameter of type 'BodyInit'

正當我以為依賴之爭已經結束時,TypeScript 又給了我一個驚喜。

在我的原始影像生成端點中,我有:

const screenshot = await page.screenshot({ ... });
return new Response(screenshot, { ... });

升級後,TypeScript 開始拒絕將Buffer當作Response體。這不是執行時問題——Puppeteer仍然返回Bufferastro check (以及npm run build )會標記出這個問題。

修復

在傳遞給Response之前,已轉換為Uint8Array

return new Response(new Uint8Array(screenshot), { ... });

這既符合 Workers 執行時期類型要求,也符合 TypeScript 的嚴格檢查要求。

最終檢查清單

| 指令 | 狀態 |

|---|---|

| npm install | ✅ (無--legacy-peer-deps ) |

| npm run dev | ✅ 所有路由都在workerd中渲染 |

| npm run build | ✅ |

| npm run preview | ✅ |

我學到的

  • npx @astrojs/upgrade會處理 Astro 核心的版本升級,但整合元件通常有自己的升級時間表。升級後務必檢查npm ls是否有依賴項警告。

  • 在 v6 版本中,內容集合遷移是不可避免的。 Astro 5 提供了一個過渡期,而 Astro 6 則沒有。新的loader API 實際上更清晰易懂,一旦你習慣了它。

  • 適配器升級是最有風險的部分。 @astrojs/cloudflare v13 對環境綁定機制進行了重大更改,並將開發伺服器遷移到了workerd 。好處是你的開發環境現在幾乎與生產環境完全相同。缺點是某些整合(例如astro-icon )目前仍不相容於workerd的模組載入機制。

  • 建構環境和開發環境不一樣。我的網站在開發伺服器執行之前很久就成功建置了。 v13 Cloudflare 適配器只在開發環境( astro dev )中出現問題,這是因為它在workerd內部執行程式碼的方式不同。務必同時測試建置環境和開發環境。

  • 當整合出現問題時,請先查閱官方文件,然後再嘗試尋找變通方案。我之前已經拉取了@astrojs/tailwind並直接安裝了tailwindcss ,但客服人員建議我使用@tailwindcss/vite這是 Tailwind CSS v4 的正確 Vite 插件。 Astro 的npx astro add tailwind指令會自動為 v4 版本進行配置,而 v4 正是支援的版本。

  • import { env } from 'cloudflare:workers'是新的標準。它完全取代了Astro.locals.runtime.env 。如果您使用的是 v13 版本,請立即採用新標準——只需記住, wrangler types會生成Env接口,但cloudflare:workers讀取的是Cloudflare.Env ,因此您可能需要擴展命名空間以存儲密鑰。

  • AI代理是優秀的隊友,但卻不是好的團隊領導者。它們會自信地提出錯誤方案,忽略根本原因,甚至臆想出遷移細節。你需要掌握足夠的知識來反駁它們,核實它們的說法,並指導策略的發展。

概括

從 Astro 5 升級到 6 並非只需一條指令即可完成。核心升級過程很順利,但圍繞著它整合的 Tailwind、Cloudflare 和 expressive-code 等元件,各自都存在一些重大變更。如果讓我重新來過,我會:

  1. 首先進行內容集合遷移( src/content/config.tssrc/content.config.ts )。

  2. 升級前請確定要使用 Tailwind 3 還是 4。對於 v4 版本,請使用npx astro add tailwind對於舊版 v3 版本,請使用 installtailwindcss@3` 。

  3. 直接升級到@astrojs/cloudflare v13。 Astro.locals.runtime → import { env } from 'cloudflare:workers' Astro.locals.runtime是機械式的。

  4. 測試時workerd npm run dev ,而不僅僅是npm run build比 Node 更嚴格。

v13 中的workerd開發伺服器整體來說是件好事——我的本地環境現在幾乎和生產環境一模一樣——但它容錯率很低。如果你遇到module is not defined或類似的底層錯誤,請追蹤是哪個整合觸發了這些錯誤。對我來說,用一個自訂的 30 行 SVG 元件取代astro-icon ,就解決了一整類相容性問題。

延伸閱讀


如果您正在計劃自行遷移,我很想知道進展如何。如果您遇到我未提及的問題,或找到了更簡潔的解決方案,歡迎隨時在X/Twitter上與我聯絡。敬請期待更多類似文章。


原文出處:https://dev.to/harshil1712/migrating-from-astro-5-to-astro-6-a-real-world-breakdown-2d0c


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝14   💬8  
297
🥈
我愛JS
💬1  
4
🥉
Gigi
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登