實務上會想將每個 Template 或 Partial 有自己的 CSS 檔,在開發階段亦保持獨立,直到編譯階段再將所有 CSS 檔合併成單一 CSS 檔。
Version
Hugo 0.148.2
Hugo Config
hugo.toml
name = 'starter theme'
[params.css]
files = [
"css/vars.css",
"css/reset.css",
"css/baseof.css",
"css/home.css",
"css/single.css",
"css/list.css",
"css/_partials/header.css",
"css/_partials/footer.css",
"css/page/about.css"
]
- 在
hugo.toml的[params.css]的fiiles設定所有 CSS 檔案路徑,將來若有新的 CSS 檔加入,只要修改hugo.toml即可,不必修改 CSS Partial
CSS Partial
layouts/_partials/css.html
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ .Site.Title }}</title>
<link rel="icon" href="/favicon.ico" />
{{ $isDev := hugo.IsServer }}
{{ $files := .Site.Params.css.files }}
{{ if $isDev }}
{{ range $files }}
{{ with resources.Get . }}
<link rel="stylesheet" href="{{ .RelPermalink }}" />
{{ else }}
{{ warnf "CSS file not found: %q" . }}
{{ end }}
{{ end }}
{{ else }}
{{ $res := slice }}
{{ range $files }}
{{ with resources.Get . }}
{{ $res = $res | append . }}
{{ else }}
{{ warnf "CSS file not found: %q" . }}
{{ end }}
{{ end }}
{{ $bundle := $res
| resources.Concat "css/main.css"
| resources.Minify
| resources.Fingerprint
}}
<link
rel="stylesheet"
href="{{ $bundle.RelPermalink }}"
integrity="{{ $bundle.Data.Integrity }}"
crossorigin="anonymous" />
{{ end }}
- CSS Partial 負責將多個 CSS 檔合併成單一 CSS 檔,並加以壓縮與加上 fingerprint
Line 6
{{ $isDev := hugo.IsServer }}
hugo.IsServer:判斷是否正在執行開發中的 Web Server,可藉由此判斷是否正在開發模式,否則則為編譯模式
Line 7
{{ $files := .Site.Params.css.files }}
- 由
.Site.Params.css讀取filesslice
Line 9
{{ if $isDev }}
{{ range $files }}
{{ with resources.Get . }}
<link rel="stylesheet" href="{{ .RelPermalink }}" />
{{ else }}
{{ warnf "CSS file not found: %q" . }}
{{ end }}
{{ end }}
{{ else }}
- 若為
開發模式則多個 CSS 檔不必合併與壓縮,保持原本多個獨立 CSS 檔方便 debug range():使用迴圈走訪filesslice 內每個 CSS 檔路徑with():確保resources.Get()非nil,若為nil則使用warnf()印出錯誤訊息幫助 debug
Line 17
{{ else }}
{{ $res := slice }}
{{ range $files }}
{{ with resources.Get . }}
{{ $res = $res | append . }}
{{ else }}
{{ warnf "CSS file not found: %q" . }}
{{ end }}
{{ end }}
{{ $bundle := $res
| resources.Concat "css/main.css"
| resources.Minify
| resources.Fingerprint
}}
<link
rel="stylesheet"
href="{{ $bundle.RelPermalink }}"
integrity="{{ $bundle.Data.Integrity }}"
crossorigin="anonymous" />
{{ end }}
- 若為
編譯模式則將多個 CSS 檔合併與壓縮,並加上 fingerprint
Line 18
{{ $res := slice }}
slice():建立 empty slice
Line 19
{{ range $files }}
{{ with resources.Get . }}
{{ $res = $res | append . }}
{{ else }}
{{ warnf "CSS file not found: %q" . }}
{{ end }}
{{ end }}
range():使用迴圈走訪filesslice 內每個 CSS 檔路徑with():確保resources.Get()非nil,若為nil則使用warnf()印出錯誤訊息幫助 debugappend():將 element 加入到filesslice 內
Line 26
{{ $bundle := $res
| resources.Concat "css/main.css"
| resources.Minify
| resources.Fingerprint
}}
resources.Concat():將多個 CSS 檔合併成main.cssresources.Minify():將 CSS 檔壓縮resources.Fingerprint():將 CSS 檔名加上 fingerprint
Line 31
<link
rel="stylesheet"
href="{{ $bundle.RelPermalink }}"
integrity="{{ $bundle.Data.Integrity }}"
crossorigin="anonymous" />
RelPermalink:取得main.css的相對路徑Data.Integrity:提供 SRI,用來讓瀏覽器驗證資源內容是否被竄改,需搭配crossorigin="anonymous"
Baseof Template
layouts/baseof.html
<!doctype html>
<html lang="en">
<head>
{{ partial "css.html" . }}
</head>
<body>
{{ block "main" . }}{{ end }}
{{ partial "js.html" . }}
</body>
</html>
- 所有 template 基礎的
baseof.html
Line 3
<head>
{{ partial "css.html" . }}
</head>
- 在
<head>內引用csspartial
Conclusion
- 藉由將 CSS 檔案路徑統一寫在
hugo.toml內,將來若有新的 CSS 檔案加入,不必去修改 CSS Partial,統一修改hugo.toml即可 - CSS 雖然沒有如 Sass 提供
@import將多個 SCSS 檔案合併成單一 CSS 檔功能,但透過 Hugo pipe 反而能達成開發模式CSS 多檔,而編譯模式CSS 單檔的效果