Hugo:一款靜態網站產生器
靜態網站產生器會將以標記式語言撰寫的頁面內容,轉譯為完整的 HTML,讓開發者能輕鬆上傳成果,並簡單且安全地架設網站。本文將介紹Hugo,這是一款以 Go 撰寫、針對速度最佳化的靜態網站產生器。它是一個彈性的工具,可依各種使用情境進行設定:從簡單的部落格、專案文件,到大型的資訊網站,甚至政府服務網站皆適用。
背景
靜態網站產生器大概從 HTML 發明之初就已存在:大多數網站都有共同的頁首與頁尾,網站擁有者不會想在每個頁面手動複製貼上這些內容。當時開發者比較可能會寫個幾十行的 Perl 或 Bash 自訂腳本,把 HTML 串起來。這種做法確實可行,但如今的靜態網站產生器比簡單的自訂腳本更快、也更強大。
很多網站是透過每次瀏覽頁面時動態算繪內容來處理共通的頁首(以及類似的元素);例如使用連接資料庫的 PHP。到了 2020 年,開發者可能更傾向使用連接提供內容之 HTTP API 的React 前端。然而,當網站只需要提供大多為靜態的內容時,這兩種架構都有點殺雞用牛刀。
許多個人網站與部落格,以及專案與公司的文件網站,都可以採用靜態方式產生。提供預先算繪好的 HTML,比提供動態算繪的內容更快、也更可靠。維基百科列出了靜態網站所具備的一些優點:
- 相較於動態網站,安全性更高(動態網站在存在漏洞時,有遭受 Web Shell 攻擊的風險)
- 相較於動態網站,能為終端使用者提供更佳的效能
- 對資料庫或其他應用程式伺服器等系統的依賴更少,甚至完全不需要
當然,有些網站(特別是網頁應用程式)永遠都需要動態內容。即使是像 LWN 這樣文章內容本身是靜態的網站,也需要能為已登入的訂戶與未登入的訪客提供不同的內容。因此,動態伺服器與 API 永遠有其必要。但當網站內容是靜態且公開的,或是任何動態內容都能在客戶端處理時,靜態網站產生器就能大幅簡化整個系統。
由於靜態網站產生器相對容易打造,因此有許多開源選項可供選擇。所有主流的程式語言都有頗受歡迎的相關工具,例如:Ruby 的Jekyll、Python 的Pelican、Java 的JBake、PHP 的Sculpin、JavaScript 的Hexo,以及其他數百種工具。本文將聚焦於 Hugo,這是一個活躍且維護良好的開源專案。
Hugo 由 Steve Francia(現為 Go 核心團隊成員)於 2013 年創建,但在 2015 年由 Bjørn Erik Pedersen 接手擔任主要開發者。該專案託管於 GitHub;目前包含約 43,000 行 Go 原始碼(不含註解),採用寬鬆的 Apache License 2.0 授權。其說明文件網站內容詳盡,當然也是用 Hugo 本身打造的。該專案也有相當多的社群參與,擁有流量不低的討論區以及大量由使用者提交的主題。Pedersen 在 2017 年表示,Hugo 的基礎設施(而非開發本身)獲得了一些企業贊助:「Netlify 免費幫我們代管網站,Discourse 維持論壇運作,Travis、Appveyor 和 CircleCI 負責建置。除此之外,沒有其他贊助商。
」
網站產生器是用什麼程式語言寫的,其實不是那麼重要(我個人使用 Jekyll,但從未需要寫 Ruby),不過開發者往往還是會傾向選擇以自己熟悉的語言撰寫的工具。即使開發者使用 Hugo,也大概永遠不需要寫 Go,不過若要打造或自訂主題,就可能需要接觸 Go 的HTML 樣板語法。
根據 BuiltWith 的統計,Hugo 在過去三年中的使用量急遽成長。它已被數個知名專案採用,包括重新設計的 Smashing Magazine 網站、1Password 支援網站與部落格、Let's Encrypt 網站,以及美國政府的 Digital.gov 網站。
運作方式
若不加任何參數執行,hugo 會遍歷 content 子目錄中的Markdown 檔案,並將算繪後的 HTML 輸出至名為 public 的子目錄。這一切皆可設定——預設的設定檔是專案根目錄下的 config.toml。輸出內容會依據主題來算繪,主題由數個 Go HTML 樣板組成,精確定義了會產生什麼樣的 HTML。主題還包含了 CSS 樣式,以及主題所需的任何圖片或 JavaScript 檔案。
在撰寫本文之前,我架設了一個包含三篇文章與一個「About」頁面的簡單測試網站——就像個人網站或部落格會用到的那種。從挑選主題、設定 Hugo 到加入一些假內容,大約花了 30 分鐘。Hugo可透過常見作業系統的套件管理器、GitHub 上針對 Linux、各種 BSD、macOS 與 Windows 預先建置好的執行檔,或從原始碼自行建置來安裝。對 Hugo 而言,從原始碼建置非常簡單,只要安裝 Go(若尚未安裝)、複製專案後輸入 go build 即可。在我的電腦上,從複製專案到執行「hugo version」大約只花了 20 秒。
在開發過程中,輸入「hugo server」即可啟動本地網頁伺服器,從記憶體中提供算繪後的內容。在此模式下,Hugo 會自動監看檔案並視需要重新建置 HTML。算繪後的頁面中甚至還包含一些 JavaScript,能在內容一有變動時就自動在瀏覽器中重新載入(透過 WebSocket 使用LiveReload)。Hugo 內建的伺服器是以可用於正式環境的net/http 伺服器為基礎,但部署時通常更簡單的做法是預先建置好算繪後的檔案,再上傳至 Amazon S3 這類靜態網站代管服務,或是放在NGINX 等一般網頁伺服器後方來提供服務。
如同其他靜態網站產生器,Hugo 為頁面使用一種簡單的檔案格式,由 YAML 格式的「front matter」組成,並以「---」行與 Markdown 內容分隔。以下是我的範例網站中第一篇文章的內容:
--- title: "First Post" date: 2020-07-06T09:33:48+12:00 categories: - Development --- The quick brown fox jumps over the lazy dog. Ee equals em cee squared. Let's try a [link](https://benhoyt.com/) and **some bold text**. Another paragraph. Hugo seems to be working. Writing Markdown is nice.
為了讓大家了解 Hugo 的主題樣板長什麼樣子,以下是我在測試中使用的Soho 主題中的 single.html 樣板(它用來算繪單篇部落格文章):
{{ define "main" -}}
<div class="post">
<h1>{{ .Title }}</h1>
{{ if ne .Type "page" -}}
<div class="post-date">
<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z0700" }}">
{{ .Date.Format "Jan 2, 2006" }}
</time>
· {{ .ReadingTime }} min read
</div>
{{- end }}
{{ .Content }}
</div>
{{- end }}Hugo 支援「taxonomies」(分類方式),也就是對頁面進行分類的不同方式,並會為每一種分類建立一個頁面,列出所有套用該分類的文章。預設會建立「tags」與「categories」兩種分類,例如我測試網站上的「Development」分類。說明文件中展示了對分類進行排序或為其加入中繼資料的各種方式。
該工具支援多種方式來控制算繪後內容中的頁面網址(「permalinks」),預設值 /:section/:filename/ 會產生如 /posts/third-article/ 的網址。:section 名稱來自 content 中的子目錄名稱(例如 posts),而 :filename 則是內容來源檔案不含副檔名的檔名。這些「目錄網址」是透過在目錄中建立帶有索引檔的算繪後 HTML 檔案來實現的:/posts/third-article/index.html。
Hugo 較進階的功能之一是它所稱的「shortcodes」,也就是帶有參數的一小段 HTML 片段,可用來補強 Markdown 有限的功能,而無需直接退回使用 HTML。內建的 shortcode 有很多,例如 gist(嵌入 GitHub Gist)、highlight(語法突顯的程式碼)以及 youtube(嵌入式 YouTube 影片)。例如,下列 shortcode:
{{< youtube w7Ft2ymGmfc >}}將會產生如下的 HTML 輸出:
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
<iframe src="https://www.youtube.com/embed/w7Ft2ymGmfc?autoplay=1"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen title="YouTube Video"></iframe>
</div>Hugo 還包含更多進階功能,例如從文章內的標題產生目錄、支援其他標記格式(預設為 Markdown)、用於預處理 CSS 與 JavaScript 的管線,以及用來縮放與裁切圖片的影像處理指令。
Hugo 主打速度快,其首頁寫道:「每頁不到 1 毫秒,平均網站可在不到一秒內建置完成
」。Smashing Magazine 擁有 7500 個頁面的網站據稱在約 13 秒內就建置完成。這種速度部分歸功於它以 Go 撰寫——Go 會編譯為原生執行檔(而非像 Python 那樣是直譯位元組碼的語言),但也部分歸功於貢獻者多年來在基準測試與效能方面所做的各種努力;例如,可參考 2020 年 1 月發布的 0.63 版版本說明。
一般來說,使用靜態網站產生器時,內容作者需要是開發者,或至少要熟悉文字編輯器、Markdown 與 Git。不過,網站代管商 Netlify 有一款名為Netlify CMS 的開源工具,讓非開發者也能透過所見即所得(WYSIWYG)編輯器來貢獻內容——該工具會在背後自動提交至 Git 儲存庫。Hugo 的說明文件中有列出其他類似工具的清單。
代管選項
採用靜態網站產生時,開發者可以選擇將算繪後的成果代管在任何主機或網頁伺服器上。常見的選項有 GitHub Pages、Amazon S3、Netlify,或是使用Caddy 或 NGINX 網頁伺服器自行架設。Hugo 有一個說明文件頁面,針對各種選項提供詳細的設定資訊。
我的測試網站決定使用 Amazon S3(前端搭配 AWS 的 CloudFront CDN)。這相當容易設定,每月只需幾美元就能處理數百萬次的頁面瀏覽。當然,你也可以完全不使用雲端,改用手邊現有的任何伺服器來代管——即使是便宜的伺服器,每秒也能處理數千個靜態檔案請求。
要使用持續整合(例如 GitHub Actions)在每次提交至網站的 Git 儲存庫時執行 Hugo 建置,確保算繪後的版本隨時保持最新,也是相當簡單的事。
總結
Hugo 似乎沒有公開的路線圖或固定的發布時程;在過去幾年中,大約每月會發布一次,中間還穿插錯誤修正版本。Pedersen 在 2018 年 7 月曾談到「邁向 1.0 之路」,但目前維護者似乎相當滿足於 0.x 的版號。版本名稱往往帶有輕鬆幽默的風格,例如「Christmas Edition」與「40K GitHub Stars Edition」。
靜態網站產生器是建置與部署以靜態內容為主的網站相對簡單的方式。Hugo 的速度、寬鬆的授權條款以及豐富的功能,使其成為開發者極具吸引力的選擇,無論是用於小型的個人網站,還是大型的內容密集型網站皆然。總體而言,Hugo 是一個值得持續關注的活躍專案。
[感謝建議此主題的 Jim Garrison。]
隨機一篇部落格
留言
登入後參與討論