Hugo 核心概念
本文介紹 Hugo 的核心概念,眾所皆知 Hugo 的文檔糟糕透頂,這些概念連他們自己的文檔都寫不好,有多爛看這張圖片就知道了:

照他們現在的維護節奏文檔問題永遠不可能改善。
Hugo 是什麼
Hugo 是一個網站構建工具,使用 Goldmark 將 markdown 轉 HTML,並且內建 JS/CSS/圖片處理工具,讓你可透過 Hugo 單一一個工具構建整個網站,因此特色是單一工具,單一執行檔,無 JS 等外部依賴,缺點同樣也同樣,開發工具使用基本完全仰賴 Hugo 有沒有整合,否則你就要用奇怪的方式完成,甚至無法使用。
目錄結構
- archetypes: 建立新 markdown 的模板
- assets: 可經由 Hugo 管道處理的資源 (圖片、pdf、影音資源、css、js 等),需要主題主動引用才會被 publish
- static: 不經由 Hugo 管道處理的資源,自動複製到 publish 輸出
- config: 設定檔目錄
- 一般用戶可直接放到根目錄的 hugo.toml 不需要 config 目錄
- config 目錄支援多個子目錄並使用不同環境變數
- 例如 config/development 是開發時專用設定
- 或是 config/foobar 可透過 hugo -e foobar 啟用此目錄的設定
- config 目錄還支援把 config 拆開,比如 params.toml 專門用於 params 底下的設定
- content: markdown 文章內容
- public: 構建結果輸出的目錄,多次構建不會清除前次內容,如果要測試東西是否存在,需要在多次構建之間手動刪除
一般用戶只需要知道這些,以下是主題開發者用的,也就是原始碼部分
- data: 全局載入的數據,通常是 yaml/toml
- i18n: 國際化,或者說翻譯文件 (internationalization 18 個字頭尾是 i 和 n 因此稱作 i18n)
- layouts: HTML 佈局文件
- resources: Hugo 處理自動生成的檔案,放著不管即可,刪除也不會怎樣
Unified File System
Hugo 和其他 SSG 最大的差別在於統一檔案系統 UFS,他會把多個主題/module "mount" 在他的虛擬檔案系統下,並且越靠近根目錄的會 override 越遠的,這帶來 Hugo 最大特色:主題有多種安裝方式。
因此 Git submodule 安裝其實只是把主題放到 Hugo 指定的目錄,然後 Hugo 把他放到 UFS 裡面,和手動安裝主題的差別只在於是否把主題原始碼也納入個人的 Git 追蹤。另一種 Hugo module 安裝方式則是透過 Go module,但一樣都接入到 UFS。
另一大特色就是 override,可以方便的覆蓋掉你想自定義的文件,但這也造成一堆人錯誤的覆蓋主題原始碼,比如主題內部有 assets/js/xxx.js,如果你也建立了同名檔案就會覆蓋掉主題的 xxx.js。
Module
Module 最常見的用法是 import 外部模組,也就是一般的主題安裝方式。
這裡要介紹的是用於進階設定 UFS,普通用戶用不到他,但是多語言、多版本、多角色就會碰到這個東西。
Hugo 的每個語言、版本對他來說都是建立一個獨立的 site,所以在中英多語言的網站對 Hugo 來說就是建立了兩個網站,如果兩個語言又都有兩個版本,那就會建立四個 site。這個 sites 對應的就是 module.mounts.sites 的設定。除了 mount sites,module 也允許 mount 其他目錄或文件,你也可以拿他來搭配 config environment 設定不同環境 mount 不同東西。
連結管理
連結管理是網站最重要的東西,連結掛了想必在任何時候都是最糟的情況,對於個人網站筆者唯一推薦 SECTION_NAME/ARTICLE_NAME 形式,也就是說
permalinks:
page:
posts: /articles/:slugorcontentbasename/
tutorials: /training/:slugorcontentbasename/
section:
posts: /articles/
tutorials: /training/
這樣的好處是網站結構清晰易懂,因為任何層級對用戶來說都是負擔。如果想按照日期編排也可以設定 /articles/:year:month:day-:slug/,或是乾脆將每個月份都建立獨立目錄。請避免只用 :year:month:day 作為 token,因為我一開始也覺得我不會一天寫兩篇文章直到我寫了。
v0.161.0 有更好的 permalink 設定方式,目前文檔尚未更新。