升級 Lumos 網站
完成時有兩件事必須成立,且彼此相互制約:
- 使用者撰寫的內容不會遺失。 他們的覆寫、頁面、令牌及元件。
- 不會遺留任何舊慣例。 重新命名的 props 已重新命名,移動的元件已移動,已淘汰的模式也已移除。
僅保留他們的工作而不更動,會違反第二點。僅透過覆寫來現代化則會違反第一點。解決方式是採用三向合併——比較他們起始的版本、他們目前的版本以及當前釋出的版本——並在三者不一致時秉持詢問而非猜測的原則。
網站的起始點
升級的好壞取決於對起始點的掌握程度。
node -p "JSON.parse(require('fs').readFileSync('package.json')).lumos ?? 'unstamped'"
- 有戳記 —
create-lumos寫入的{ version, commit, scaffolded }。其中的 version 是網站源自的釋出版本,僅供閱讀;commit 則是要合併的目標,這才是關鍵。兩者並非重複:在兩個釋出之間建立的網站,等於該版本加上後續新增的內容,只有 commit 能說明確切幅度。在 version 加入前已戳記的網站僅帶有 commit,這已足夠。該 commit 即為合併基準。取得它後,你就能確切知道哪些行屬於框架,哪些屬於使用者。 - 無戳記 — 網站早於戳記功能。將
v0.0.1視為基準。在報告中清楚說明:基準僅是推測,因此合併時會有更多衝突,需要更多人工審視。
網站自身的 package.json 版本不具參考價值——create-lumos 會將每個新網站設為 0.0.1。請勿將其視為框架版本。
步驟
1. 提交現有內容
拒絕在髒亂的工作樹上開始——若與前一天的工作混雜,升級過程中的 diff 將難以閱讀。
git status --porcelain # 必須為空
git commit --allow-empty -m "Before Lumos upgrade"
刻意建立空提交:這是整個升級過程的錨點,git diff <該提交> 將成為審查依據。
2. 拍攝網站快照
在進行任何變更前,先啟動開發伺服器:
astro dev --background
node .agents/skills/lumos-upgrade-version/visual-check.mjs capture before
捕捉所有靜態路由在桌面與行動版下的畫面。這是步驟 8 的比對依據,且無法事後補拍。
3. 取得兩個參考副本
npm create lumos@latest .lumos-upgrade/latest # 當前釋出的版本
以及合併基準——網站當初建置時所用的 commit:
curl -sL https://codeload.github.com/lumosframework/lumos-for-astro/tar.gz/<commit> \
| tar -xz -C .lumos-upgrade --one-top-level=base --strip-components=1
現在有三個目錄樹:base(使用者起始處)、網站(使用者目前所在處)、latest(使用者即將遷往的目標)。
4. 將每個檔案歸入四個類別之一
針對框架表面中的每個檔案——元件、佈局、樣式、工具類:
| base vs site | base vs latest | 含義 | 處理方式 |
|---|---|---|---|
| 相同 | 相同 | 雙方皆未觸碰 | 保留 |
| 相同 | 已變更 | 框架已移動,使用者從未修改 | 直接採用最新版本 |
| 已變更 | 相同 | 使用者覆寫,框架未變動 | 保留使用者版本 |
| 已變更 | 已變更 | 雙方皆有變動 | 三向合併,衝突列入報告 |
src/pages、src/content 與 src/assets 依定義屬於使用者——絕不替換。它們仍需在步驟 6 中進行遷移。
.agents/skills 整體升級,但有一例外。 技能的說明文字屬於框架,應更新至最新版本,但技能中可能包含專案寫入的段落——例如 /lumos-import-webflow 的 此專案 就是一個例子,其中記錄了路徑、提供者及 CMS 篩選器,這些資訊不存在於其他地方。在採用新檔案前,完整保留此類段落,並在報告中說明已執行此操作。直接採用最新版本會銷毀無其他來源的記錄。
5. 合併 base.css 而非直接取代
全域 CSS 是最可能屬於第四個類別的檔案:框架新增令牌,使用者修改品牌顏色與字型。以三向合併方式逐令牌處理,並遵守兩項規則:
- 使用者已修改的令牌保留其數值,即使框架已變更預設值。他們的品牌顏色並非過時的預設值。
- 框架新增的令牌採用框架的數值,並放置在其專屬段落中——而非附加在檔案結尾。
所有雙方皆有變動的令牌,須將其兩個數值都列入報告。不代為挑選。
6. 遷移網站自有程式碼
比對 base 與 latest 以了解哪些內容已移動,然後套用至 src/pages 及使用者撰寫的任何內容:
- 重新命名或移動的元件 — 更新所有 import 與標籤。同時移動資料夾並失去前綴的元件(如
FormInput→Form/Input.astro)包含兩項變更,需一併處理。 - 重新命名的 props — 在每個呼叫點重新命名。
- 已移除的 props — 暫停並詢問。 針對每個移除的 prop,提供三個可行的選項:保留該 prop 作為本機覆寫、移除它、或改用取代它的功能。切勿在未告知的情況下自行決定;被移除的 prop 通常代表某種意義。
- 已刪除的元件 — 保留使用者的副本。 將
base中的元件複製到網站自身的元件資料夾中,讓網站仍能正常建置且外觀不變,並標記它:此元件不再由框架維護,並說明取代它的內容(如果有的話)。
7. 確認建置成功
npx astro check && npx astro build
在檢查螢幕截圖前,兩者都必須乾淨通過。在此階段發現型別錯誤,代表遺漏了某項遷移。
趁機檢查 Astro 配對版本。 Astro 是網站自身的依賴項,而非框架的——Lumos 是以腳手架方式引入,而非安裝——因此升級是檢查的自然時機,但並非強制更新的理由。比對網站的 astro 版本與正在合併的釋出版本;若網站落後一個主要版本,請在報告中說明,由網站擁有者決定。
使用 npx @astrojs/upgrade 而非手動升級。它會同時更新 Astro 與 @astrojs/* 整合套件,而 @astrojs/sitemap 並未宣告對 astro 的 peer 依賴——因此不匹配的配對會在無任何提示下安裝,最終以建置失敗或網站地圖默默停止產出的形式顯現。
8. 確認無任何變動
node .agents/skills/lumos-upgrade-version/visual-check.mjs capture after
node .agents/skills/lumos-upgrade-version/visual-check.mjs compare
對步驟 2 的每個路由進行像素差異比對,容許反鋸齒誤差,並針對像素差異超過 0.1% 的畫面產生標示差異的圖片。當有任何變動時,結束碼不為零。
改變設計的升級代表某處出了問題——可能是令牌合併方向錯誤、prop 遺失、或元件被替換為不完全相同的版本。從差異圖片往回追溯,直到每個差異都獲得解釋。有些差異是合理的:上游的真實錯誤修正會移動像素。原則是「沒有無法解釋的差異」,而非「完全沒有差異」。
9. 提交結果
git add -A && git commit -m "Upgrade Lumos to <commit>"
將 package.json 中的戳記更新為剛合併的 commit,以便下次升級有精確的基準。然後刪除 .lumos-upgrade/。
報告
- 採用最新版本 — 因未經修改而整體取代的檔案。
- 保留為自有 — 保留的使用者覆寫,框架變更未被採納。
- 已合併 — 雙方皆有變動的檔案,說明各部分來自何處。
- 已遷移 — 套用至使用者自有程式碼的重新命名與移動,附計數。
- 保留運作 — 上游已刪除但複製到網站中的元件,並說明取代它的內容。
- 已處理 — 已移除的 props 及使用者選擇的解決方式。
- 視覺差異 — 每個有變動的畫面及其原因。
- 仍待處理 — 任何未解決的事項。升級完成時此列表可能不為空,但必須明確說明。
版本
- 技能版本 — 1.0.0。
- 框架 — 目前尚無正式釋出版本:
create-lumos是從main分支的最新 commit 建立腳手架,因此「最新」代表最新的 commit,合併基準是一個 commit 而非標籤。若未來有標籤化的釋出版本,則在戳記中優先使用標籤,並在步驟 4 中讀取變更日誌,而非盲目比對。
在沒有 Claude Code 的情況下使用此技能
各步驟皆為純粹的 git 與 node 指令。visual-check.mjs 需要 headless Chrome 與 sharp,這兩者在 Mac 上的 Astro 專案中通常已具備。只有自動觸發與 /lumos-upgrade 功能是 Claude Code 的專屬特性。