使用 Scully 將 Angular 網站靜態化

前言

前端框架製成的網站,基本上在 html 裡只會有一個 div
剩下的一切都是由 JavaScript 渲染而成,也就是所謂的 Client Side Rendering(CSR)

為了利於 SEO 與方便搜尋引擎 bot 去爬取資料
於是框架們提供了解法:Server Side Rendering(SSR) ── 在 Server 時先將頁面渲染好再回傳回去,就會有完整的 html 結構,也就利於 SEO 了!

SSR 看似解決了一切問題,但對於系統的開發與管理來說
著實增加了負擔 ── 必須再有一台 Server 供 SSR 使用

若 Server 自架還好處理,流量不大的話,大不了一台 Server 跑 2 個服務
但現在幾乎都以雲端平台為主,多一台 Server 就是多一個營運成本!

而靜態頁面則是成本最低的雲端主機,甚至可說是免費!
甚至是丟在 GitHub page 就可以運作了
Server 還可以用 serverless function 來降低對後端的開發 loading

對於規模不大的 Project 或是作品集,靜態頁面的網站都是一個很好的作法

而能夠使用前端框架來產生靜態頁面,絕對是最棒的!
畢竟頁面若會日趨複雜,有框架當基底可以保證良好的擴展性

靜態頁面產生器 SSGs

相較於 React.Js 早已有的 NEXT.JS、Gastby.Js、Vue.Js 的 NUXT.JS
Angular則一直缺乏這類的靜態頁面產生器 SSGs(Static Site Generators)
終於約在 2020 年左右,社群迎來的專屬的 SSGs ── Scully !

也將 Angular JAMStack 舖好最後一哩路!

為免偏離主題太遠,關於 JAMStack 可以參考JAMStack 簡介

在現有 Angular 專案加入 Scully

非常簡單,只需要一行指令!

1
ng add @scullyio/init

約莫等待約3~5分鐘後,就完成了!
完全不必改一丁點程式碼!

然後執行

1
2
npm run build
npm run scully

其中 npm run scully 是 Scully 初始化時會自動加在package.json

Scully 產生靜態頁面原理

就是透過 puppeteer 逐一爬取頁面來產生
也可以透過一些參數調整爬取行為

小坑:靜態頁面爬取失敗

我在產生靜態頁面時,有幾個特定頁面一直無法順利取得

一開始以為是被 guard 阻檔
我的專案有 2 種 guard 。但另個 guard 的頁面卻可以順利取得!

還以為有 BUG,難道產生靜態頁面後,guard 會失效?
但測試時又確實有被保護住
Google 也一直查不到相關資訊,搞了好久

後來突然想到我在 guard 裡有加 alert 提示訊息!
果然一拿掉後就正常了…

因此要注意專案是否用到 browser API 卡住 puppeteer 爬取頁面

補充:自己 Side Project 實際經驗

我有個 Side Project 架構: Server 在 Heroku;Angular 做 SSR 放在 GCP

會搞這麼複雜也是因為規模太小
Heroku 綁自定域名則須付費,而 GCP 有提供免費綁定域名
盡管是個如此小的專案,我每個月都還得付 1 元給 GCP!

若前端網頁不使用 SSR 而單純當靜態頁面部署在 GitHub Page 之類的
會有下列問題:

  1. 所有頁面都得從首頁進入後再點擊各自路由才能到達
  2. 無 SEO 可言(盡管 Google 有說他們的 BOT 已支援)
  3. 若 User 將特定頁面加入書籤時,點擊會發現找不到網頁,使用者體驗很差

現透過 Scully 靜態化 Angular 後,就將頁面部署在 netlify
載入速度極快!幾乎是毫秒就將頁面跑完
剩下則是等待 API 回應的等待時間 (畢竟 Server 是採用免費方案,回應較慢)

原本架構採用 SSR,應該是 GCP 基本方案關係
一段時間無人使用會休眠。當觸發使用後,須等待 3~4 秒喚醒,之後速度才正常許多
雖不算太久,但就是沒那麼舒服

而靜態化後,連每個月的 1 元也省下來了!XD
雖然已經很便宜,但一直收到帳單也是頗煩的= =

當初有預留純 Angular 專案,GCP 上部署的是 fork 出來後再加上 Angular Universal
就是避免當用量起來,Heroku 確定要付費使用時,可以將 Angular 轉回 Heroku
統一雲端平台管理也比較單純
畢竟 GCP 的 DB 有點貴阿….(可參考之前踩坑心得:GCP VS HEROKU 小資使用心得)

我有保留原本的純 Angular 專案
因不想之後再花心力逐一拔除 Angular Universal 的東西
所以每當前端頁面要調整時,我就有 2 個專案要同步修改!

對於我日常維護造成極大的困擾!
靜態化後,終於讓前端專案回歸正常

參考資料

Scully 官方網站

妙的是,Google 搜此關鍵字,不是第一筆,排行卻在滿後面的XD

GCP VS HEROKU 小資使用心得
JAMStack 簡介