快轉到主要內容

Hugo Modules


本文專門介紹 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:

go.mod
require example.com/othermodule v0.1.0

replace example.com/othermodule => example.com/myfork/othermodule v0.1.0

或是指向本地目錄:

go.mod
replace github.com/user/theme => /home/user/projects/theme

replace 寫在 go.mod 裡並隨專案一起發布,因此對所有建置這個專案的人都會生效,包含 CI。

Workspace

Workspace 用於設定本地開發時的 module 配置,可以將他理解為暫時版的 replace 功能。舉例來說,開發本地 module 時直接套用本機檔案:

hugo.work
go 1.20

use .
use ../theme

以環境變數暫時啟用:

HUGO_MODULE_WORKSPACE=hugo.work hugo server

或是在 hugo.yaml 設定長期啟用 workspace 模式:

hugo.yaml
workspace: 'hugo.work'

Workspace 和 replace 最大的差異是允許暫時啟用且不會寫進 go.mod,當模組被外部依賴,不會有 replace 設定影響外部用戶的問題。

實際應用範例

多語言網站

如同多語言網站說的一樣,可以將指定目錄 mount 到指定位置的指定 site 上,以完成多語言設定。

共用元件庫

最基礎的應用,多個網站共用同一組 shortcode、partial 或 CSS,抽成獨立 module 讓所有網站引用:

module:
  imports:
    - path: github.com/your-org/shared-components

exampleSite

開發主題時常見的做法是在主題 repo 裡放一個 exampleSite/ 目錄,作為主題的範例網站使用,但 exampleSite/ 這個網站依賴的主題是專案根目錄的主題本身。

Workspace 可以輕鬆解決這個問題,設定方式為

hugo.work
go 1.20

use .
use ../
hugo.yaml
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 依環境切換引用:

config/staging/hugo.yaml
module:
  imports:
    - path: config-staging
config/production/hugo.yaml
module:
  imports:
    - path: config-production

其中 config/stagingconfig/production 目錄會根據 environment variable 自動切換,或是以 hugo -e staging 手動指定,也可搭配 CI/CD 依部署環境切換要引用的設定 module。

無障礙設定

字體大小