如果只是想知道我的驗證結果,先說結論:可以。後續只是我的驗證過程和成果,如果沒興趣就可以關閉此文並到 Astro 官網看看了🤣🤣🤣
大家好,這篇文我想來試用一下這陣子滿多話題的 Astro。說來有趣,我最早知道 Astro 時並不是在某個社群或聽同事提及,而是某一次我下班後去上跳舞課時,就剛好瞄到有位上同堂課的學員正在用 Mac 寫前端,並發現他的專案是基於 Astro,用手機稍微 Google 一下才知道這個框架。
我們學習一個新的框架或庫通常是為了去嘗試解決某些問題。閱讀了 Astro 的介紹頁後,我就想到我自己作品集頁面的一個痛點。
想要解決的問題
我的作品集是採用 Express.js 作為伺服器掛載靜態頁放在機器上的,掛載的就是一個很單純的靜態 html 檔案。會這樣做是因為當初在開發時就希望它除了以單純為主外,所有效能指標都必須要是滿分,而當初也很順利地做到:
不過因為我當初在製作時就是很單純地用 html 去編寫,因此作品的部分就不免要剪剪貼貼,如果樣式需要調整就會很麻煩。但畢竟我的頁面最多也就只需要去 for loop 我的作品區塊,不需要寫什麼邏輯。曾想過使用簡單的模板系統如 Mustache.js 去解決這個問題,不過礙於這個庫偏冷門加上自己懶惰就作罷,React, Vue 這類的庫或框架我則沒有什麼信心它能維持一樣的效能分數。不過,再看到 Astro 文件中的敘述:
需要兼顧網站載入速度與 SEO 嗎?Astro 非常適合你。
就引起我想要嘗試的興趣了。我的目標非常簡單:
- 改用 Astro 來寫我的作品集頁面
- 效能分數不能有任何一項指標低於滿分
進行開發
雖然說是進行開發,不過 Astro 的學習門檻是真的很低,從建構 Astro 專案、把作品集頁面搬移到 Astro 專案中、邊閱讀文件、邊將作品寫成組件前後耗費也就一小時左右。而語法部分,例如代表作品的組件語法就長這樣:
---
interface Props {
title: string;
description: string;
tags: string[];
image: string;
link: string;
ariaLabel: string;
}
const { title, description, tags, image, link, ariaLabel } = Astro.props;
---
<div class="grid-item">
<a href={link} aria-label={ariaLabel} target="_blank" rel="noopener">
<div class="hoverbox ef-move-right light">
<img src={image} alt="" loading="lazy" />
<div class="hb_back">
<h2 class="work__title">{title}</h2>
<p class="work__text">{description}</p>
</div>
<ul class="work__tags">
{tags.map((tag) => <li>{tag}</li>)}
</ul>
</div>
</a>
</div>
不論是習慣使用 Vue 還是 React 的開發者,應該都不難看出這段語法代表的意思吧?如果需要在組件內寫樣式,也就只要在最後一個 </div>
下方增加 <style>
即可編寫樣式。
再來最重要的來了:基於 Astro 框架 Build 出來的靜態頁面,可以和原本的靜態頁面一樣維持所有指標均為 100 分嗎?我用了非常土法煉鋼的方式:
- 用
npm run build
產出靜態資料 - 將靜態資料包含圖片、CSS、JavaScript 及 HTML 覆蓋到原本的專案
- 在本地啟動原本專案的伺服器確認無問題
- 將專案推送至機器上並在站上重跑一次 Lighthouse 效能檢測
跑出來的結果如下:
前後效能分數並無太大差異,甚至在我順手修了一個 LCP 的小問題後還提升了一點點。換句話說,Astro 的確可以替代我目前直接寫靜態頁面導致維護較為困難的問題。
最後一個要解決的問題就是:將專案直接遷移到 Astro 下,由原本自建的超陽春 Express.js 專案改由 Astro 來一站式處理。
開始遷移
翻了一下 Astro SSR 一些解決方案的說明後,發現它可以使用 hybrid
的方式,也就是像我原本的作法直接產出靜態頁面,而非收到請求時才進行渲染,這樣應該可以確保效能分數不會受到任何影響:
// astro.config.mjs
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
// https://astro.build/config
export default defineConfig({
output: "hybrid",
adapter: node({
mode: "standalone",
}),
});
機器部分,我用的是 fly.io
,它本身部署需要的設定就非常少,費用也不會很貴,針對 Astro 也有說明使用方式,這邊就不贅述。
最後分享完成調整後站上出現 Astro 的喜悅感:
至於為什麼當初會用 Express.js 而非直接放在如 Github Page 之類的地方,是因為原本是要做 MPA,也是有需要在部分頁面處理請求、也的確有實作出來只是沒有實際運用,而目前依然是打算保留這個彈性,所以才會沿用伺服器的方式。
結論
從開始接觸 Astro 到撰寫完這篇文,前後也就花了大約四小時。Astro 真的是一個很好入門,在效能上確實也跟自己寫靜態頁面相去不遠,目前已經想好未來能應用的場景,也期待能很快再使用它去處理其他不同的問題。這篇文就到這,若內文有任何錯誤,也歡迎指出,謝謝。
References: