跳至內容
Bluebean 的筆記
Go back

從 Hexo 遷移到 Astro

大概有一年沒更新 Blog 了吧……

這一年來也是很多事情……

總之,最近又想到這個 Blog 了,就回來了 :)

一開 VSCode 我就在思考,這個 Blog 還適不適合繼續用 Hexo。過往我寫文章都是在 VSCode 上編輯,但是圖片貼上都要花時間處理路徑,其實挺累的。所以我就用 Google 的 AI Mode 問了一些現代化的靜態網頁方案,最後選擇了 Astro 這條不歸路。

為什麼選 Astro?

其實只是剛好看到這個方案,腦門一拍就定案了。

真要說原因的話,就是 Astro 的架構可以讓我把文章用資料夾分層,並且不論在圖片連結上或是重導向都很契合我的需求,一方面我可以透過重導向保留過往的連結,還可以重新調整 URL 結構。

痛苦的遷移

遷移的痛苦程度完全取決於以往的文章內容跟配置是否綁死在 Hexo 生態。

當我用 AI Mode 列出遷移指南的時候,看起來非常簡單,只要把 post 內的 .md 給搬過去就好了,聽起來真棒!然後,我就折騰了一整天 🙃

雖然我的文章很少,但也是需要動不少東西。

由於 Astro 本質上更像是一個前端專案,因此所有主題都跟主 Repo 綁死。再加上 Astro 的自由度高,每個專案的 schema 跟功用都不一樣。

一開始,我選擇了 Minrock 主題,這是一個可以整合 obsidian 並且支援語音閱讀的部落格主題。功能挺多樣的,但是有很多內容我不需要,而且,他的 Tag 沒有跳脫,使得 # 之類的特殊字元會使標籤壞掉,折騰了半天,最後放棄……

後來選擇了 AstroPaper ,簡約的風格搭配 Tag 跟搜尋功能符合我的需求,只需要經過小幅度的修改就可以拿來用了,算是不錯的選擇。

主題影響遷移

前面有說到,Astro 本身比較像前端專案。每個主題各有各的偏好,markdown 文章的 yaml 配置各有不同。因此,在嘗試主題的過程中,我必須不斷調整 yaml 測試主題。

以 Hexo 常用的發布日期 date來當例子:

除此之外,有些主題對 schema 比較要求,需要補上必填的 schema,否則會遇上渲染失敗的問題。

Plugin

其實我用到的 Plugin 不多,嚴格來說就只有 KaTeX 而已,但我現在的主題可不支援,因此需要額外找 Plugin 來處理。

剛好,Astro 的 Markdown 渲染引擎正經過一波大更新。於是,我就在如何安裝 katex 上又折騰了一陣子。

Astro 原本的渲染引擎是 Unified ,後來有一個新世代的引擎是 Sätteri。這兩個引擎的 Plugin 無法共用。

最一開始,我選擇了 KaTeX ,裝了之後沒反應 (因為當時用的是 Sätteri,而我下載的是 Unified 用的)。後來經過一番努力,終於是搞定了,但是我卻發現整個數學式被重寫了 2 次……

因為 KaTeX 渲染會產出 HTML + 較新的 MathML 規範。因為不明原因,生成的頁面並沒有隱藏其中一個,就造成重複渲染了。最後就改用純 MathML 渲染。

Info

其實我只在一個頁面用到 KaTeX,但也就為了這個頁面,又花了一些時間處理 🙃

圖片連結調整

過往,因為 Hexo 的性質,圖片的 URL 處理其實有些混亂。

我的 Blog 就有集中管理的 Assets 跟文章資料夾的專屬空間,這部份也花了一點時間做處理。

Astro 本身直接連接檔案,因此 markdown 上的路徑只要可以找到圖片,最後生成的網頁就可以正確的連接,算是蠻不錯的設計。

Hexo 主題語法遷移

以前的文章大量使用像是 {% note info %} 之類的區塊標記,轉到 Astro 之後,就需要轉成標準 markdown,或是整篇文章寫成 astro 格式。

最後選擇了 Github 常見的 Alert 寫法:

> [!INFO]
> INTO 區塊

靜態 CMS 管理

這個算是我額外處理的部份,因為過往用 VSCode 編輯還要自己處理圖片,而最初的 HexoAdmin 外掛很難用,所以我也在尋找一個開箱即用的方案。

最後找到了 Keystatic ,一款簡單好用的靜態內容 CMS 管理。

Keystatic 本身只接受兩種 markdown 擴充:mdx 跟 markdoc。

因為過去的內容有 html 跟 hexo 語法混雜,所以部份語法到 mdx 會直接壞掉。最後,我選擇了 markdoc 方案,既可以在 CMS 管理中使用,又不會被 <>{%} 這些符號搞到壞掉。

Keystatic 也要求絕對的 schema 定義,以及資料夾與圖片空間的結構要求,因此在上面花了不少時間。

但目前使用下來,體驗還算不錯,這篇文章正是在 Keystatic 上撰寫的 :)

Giscus 留言

有鑑於 Gitalk 的權限要求造成的部屬問題,我後來查詢並挑選了 Giscus 方案。

主要 Giscus 本身是透過註冊官方 Github App,並以 Github OAuth 的方式在 Discussion 上留言。比起 Gitalk 直接使用 PAT Token 建立 Issue 還來得安全一點。

重導向

因為路由規則的變動,為了保留原有的網址,需要做重導向。

另外意外的是,Astro 已經有現成的方案可以處理了,而且還可以支援多路由重導向,挺不錯的。

我選擇 astro-redirect-from,這樣就可以在每個文章的 schema 底下紀錄曾經的 URL 並做重導向

主題細節調整

處理完這堆東西之後,總算是完成本體遷移的部份了,剩下的就是一些主題的調整。

即使 AstroPaper 已經足夠簡潔了,但仍然有不足的部份,比如使用 Astro 的 ClientRouter 做的 SPA 頁面切換。

不知道為什麼,SPA 的轉場動畫有很嚴重的衝突,最後我只能把整個 ClientRouter 跟 transition 屬性給拔掉。

部屬

基本上這個流程並不困難了,主要還是因為我不熟悉 Github Action ,所以只能找範例來用。

我沒辦法使用官方的 Action 範例,因為官方的 Action 只能在同 Repo 上執行,但我需要保護聞長原始碼,這在免費方案下是行不通的,所以只能夠繼續採用 private repo 版控 + 推到 public repo 部屬。

這次使用 github-pages-deploy-action 的 SSL Auth 搭配 Deploy Key 做部署。

大功告成

費了一大功夫,最終呈現的就是現在的 Blog 了 🎉

雖然 Blog 內容少,評論也少,甚至有沒有人收藏我也不知道。但保險起見,還是小心的做了遷移。

如果一開始有先進版控,我想這種涉及大量雜項但重複程度高的作業,還是交給 AI Agent 來處理會更好一些,不過我一直都使用免費方案,所以沒辦法進行這麼大量的操作 😥

雖然遷移後 Blog 少了一些東西,比如文章分類 (跟 Tag 很像的東西) 跟側邊 markdown TOC,但也多了一些意想不到的,比如 RSS Feed 跟頁面搜尋。

Astro 看起來更容易做到頁面搜尋跟 RSS Feed 之類的事情,基於內容生成的 .js/.xml 只需要 檔名.ts 搭配程式輸出,就可以動態生成內容,這種方法相當便利。

不過,本來只是想要來寫個文章而已,卻花了不少時間在框架本體上,摩擦還是不小。以開箱即用來說, Astro 似乎不算是個好選擇。


分享文章:

Previous
[雜談] 2025-09-21 - 閒聊近況