本文專門介紹 Hugo Modules 以及對應的 hugo mod 指令。
什麼是 Module
Module 是 Hugo 組織內容的基本單位。一個 module 可以是完整的 Hugo 專案,也可以只是提供某一種元件(content、layouts、assets、data、i18n、static、archetypes)的小型可重用套件。你安裝的主題,本質上就是一個 module。
Module 可以任意組合、巢狀引用,也可以掛載外部目錄,甚至是非 Hugo 專案的目錄,全部併入同一個 UFS。
初始化與引用
專案本身要先變成一個 module 才能引用其他 module:
hugo mod init github.com/user/theme這會產生 go.mod。如果你不打算讓其他人導入你的模組,那麼具體的名稱並不重要,取個合理的名稱即可。
在 hugo.yaml 宣告要引用的 module:
module:
imports:
- path: github.com/user/theme執行 hugo 構建時,會自動下載 module、寫入快取,並產生 go.sum 記錄版本與校驗碼。
同時引用多個 module 時,同名檔案的合併規則按照 UFS 規則合併。
常用指令
以下整理常用的 hugo mod 指令:
更新單一 module:
hugo mod get -u github.com/user/theme指定版本:
hugo mod get -u github.com/user/theme@v0.42.0更新全部 module:
hugo mod get -u遞迴更新 module:
hugo mod get -u ./...清理
go.mod/go.sum中未使用的項目:hugo mod tidy清除 module 快取:
hugo mod clean
Vendor
hugo mod vendor 用於本地檢視與臨時修改除錯。
此指令會將所有引用的 module 複製到優先權更高的 _vendor 目錄,可以直接在 _vendor 目錄中對 module 修改測試。直接修改 _vendor 內的檔案僅用於快速除錯,再次 vendor 就會被覆蓋,正式的客製化方式仍然是透過 UFS 在專案根目錄用相同路徑覆蓋。
Replace
Replace 功能用於永久替換依賴,比如改為自己的 fork:
require example.com/othermodule v0.1.0
replace example.com/othermodule => example.com/myfork/othermodule v0.1.0或是指向本地目錄:
replace github.com/user/theme => /home/user/projects/themereplace 寫在 go.mod 裡並隨專案一起發布,因此對所有建置這個專案的人都會生效,包含 CI。
Workspace
Workspace 用於設定本地開發時的 module 配置,可以將他理解為暫時版的 replace 功能。舉例來說,開發本地 module 時直接套用本機檔案:
go 1.20
use .
use ../theme以環境變數暫時啟用:
HUGO_MODULE_WORKSPACE=hugo.work hugo server或是在 hugo.yaml 設定長期啟用 workspace 模式:
workspace: 'hugo.work'Workspace 和 replace 最大的差異是允許暫時啟用且不會寫進 go.mod,當模組被外部依賴,不會有 replace 設定影響外部用戶的問題。
實際應用範例
多語言網站
如同多語言網站說的一樣,可以將指定目錄 mount 到指定位置的指定 site 上,以完成多語言設定。
共用元件庫
最基礎的應用,多個網站共用同一組 shortcode、partial 或 CSS,抽成獨立 module 讓所有網站引用:
module:
imports:
- path: github.com/your-org/shared-componentsexampleSite
開發主題時常見的做法是在主題 repo 裡放一個 exampleSite/ 目錄,作為主題的範例網站使用,但 exampleSite/ 這個網站依賴的主題是專案根目錄的主題本身。
Workspace 可以輕鬆解決這個問題,設定方式為
go 1.20
use .
use ../workspace = 'hugo.work'node_modules
Mounts 功能也可用於 node_modules,讓你直接將 node_modules 內容 mount 到指定目錄,不需手動 vendor 套件。設定方式為:
module:
mounts:
- source: assets
target: assets
- source: node_modules/@awmottaz/prettier-plugin-void-html/
target: assets/prettier-plugin-void-html在 JS 和模板中就能直接使用該目錄的內容。
內容與源碼分離
把 content/ assets/ 獨立成一個 module(獨立的 git repo),讓寫手完全不需要碰觸主題原始碼:
module:
imports:
- path: github.com/your-org/site-content寫手只需要對 site-content 這個獨立 repo 有存取權限,不會誤動到 layouts 等程式碼部分。工程師只需要設定 CI 構建時下載這個 module 即可簡單達成權責分離。
本地開發需要即時看到內容變更效果時,可以搭配前面提到的 replace 指向本地路徑或用 workspace 掛載。
多環境設定分離
把正式站與預覽站需要的不同 data/ 或 params 依環境切換引用:
module:
imports:
- path: config-stagingmodule:
imports:
- path: config-production其中 config/staging 和 config/production 目錄會根據 environment variable 自動切換,或是以 hugo -e staging 手動指定,也可搭配 CI/CD 依部署環境切換要引用的設定 module。