资源管道
使用 Hugo Pipes 处理 Sass、CSS、JavaScript、图片、指纹哈希和响应式资源
资源管道
Hugo Pipes 是 Hugo 内置的资源处理系统。它可以在构建时处理 CSS、Sass、JavaScript、图片、指纹哈希、压缩和缓存,让静态站也拥有接近前端工程化的资源管理能力。
简单判断:
- 需要处理、压缩、打包、加指纹的资源放
assets/ - 不需要处理、只想原样复制的资源放
static/ - 只属于某篇文章的图片和附件放 Page Bundle
assets 与 static 的区别
| 目录 | 处理方式 | 引用方式 | 适合 |
|---|---|---|---|
assets/ | 经过 Hugo Pipes 处理 | resources.Get | Sass、JS、可处理图片 |
static/ | 原样复制到 public/ | 直接写 URL | favicon、PDF、验证文件 |
| Page Bundle | 作为页面资源处理 | .Resources.GetMatch | 文章封面、附件、图集 |
CSS 处理
目录示例:
assets/
└── css/
└── main.css
模板中引用:
{{ with resources.Get "css/main.css" }}
{{ $css := . | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous">
{{ end }}
fingerprint 会给文件名加内容哈希,适合长期缓存:
/css/main.min.abc123.css
Sass/SCSS 处理
目录示例:
assets/
└── scss/
├── main.scss
├── _variables.scss
└── _layout.scss
main.scss:
@use "variables";
@use "layout";
body {
color: variables.$text-color;
}
模板中编译:
{{ $opts := dict "targetPath" "css/main.css" "outputStyle" "compressed" }}
{{ with resources.Get "scss/main.scss" }}
{{ $css := . | css.Sass $opts | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous">
{{ end }}
注意:
- Hugo Extended 和 Extended/deploy 内置 LibSass
- Sass 官方已弃用 LibSass,新语法建议使用 Dart Sass
- Dart Sass 需要在本地和 CI/CD 环境中安装
- 如果主题文档要求 Dart Sass,不要只安装 Hugo Extended
PostCSS
如果主题使用 Tailwind CSS、Autoprefixer 或其他 PostCSS 插件,需要 Node.js 环境。
安装依赖:
npm init -y
npm install -D postcss postcss-cli autoprefixer
postcss.config.js:
module.exports = {
plugins: {
autoprefixer: {}
}
}
模板中处理:
{{ $css := resources.Get "css/main.css" | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous">
CI 构建时要记得:
npm ci
hugo --minify
JavaScript 打包
Hugo 的 js.Build 基于 esbuild,可用于打包、转译、tree shaking、minify 和 source map。
目录示例:
assets/
└── js/
├── main.js
└── search.js
模板中引用:
{{ $opts := dict "targetPath" "js/main.js" "minify" hugo.IsProduction }}
{{ with resources.Get "js/main.js" }}
{{ $js := . | js.Build $opts | fingerprint }}
<script src="{{ $js.RelPermalink }}" integrity="{{ $js.Data.Integrity }}" crossorigin="anonymous" defer></script>
{{ end }}
开发环境保留 source map:
{{ $opts := dict
"targetPath" "js/main.js"
"minify" hugo.IsProduction
"sourceMap" (cond hugo.IsProduction "" "inline")
}}
TypeScript 入口也可以处理:
assets/js/main.ts
{{ $js := resources.Get "js/main.ts" | js.Build (dict "targetPath" "js/main.js") }}
图片处理
Hugo 可以处理 Page Bundle、assets/ 和远程资源中的图片。常见方法:
| 方法 | 作用 | 示例 |
|---|---|---|
.Resize | 按宽高缩放 | Resize "800x" |
.Fit | 等比缩放到指定框内 | Fit "800x600" |
.Fill | 裁剪填充指定尺寸 | Fill "1200x630" |
.Crop | 裁剪 | Crop "600x400" |
.Filter | 应用滤镜 | images.GaussianBlur 6 |
文章 Page Bundle:
content/posts/hugo-images/
├── index.md
└── cover.jpg
模板:
{{ with .Resources.GetMatch "cover.*" }}
{{ $cover := .Fill "1200x630 webp q80" }}
<img src="{{ $cover.RelPermalink }}" width="{{ $cover.Width }}" height="{{ $cover.Height }}" alt="{{ $.Title }}">
{{ end }}
webp q80 表示输出 WebP,质量 80。
响应式图片
可以生成 srcset:
{{ with .Resources.GetMatch "cover.*" }}
{{ $small := .Resize "480x webp q75" }}
{{ $medium := .Resize "800x webp q75" }}
{{ $large := .Resize "1200x webp q75" }}
<img
src="{{ $medium.RelPermalink }}"
srcset="{{ $small.RelPermalink }} 480w, {{ $medium.RelPermalink }} 800w, {{ $large.RelPermalink }} 1200w"
sizes="(max-width: 768px) 100vw, 800px"
width="{{ $medium.Width }}"
height="{{ $medium.Height }}"
alt="{{ $.Title }}"
loading="lazy">
{{ end }}
建议写入 width 和 height,减少页面布局抖动。
远程资源
可以读取远程图片或数据:
{{ with resources.GetRemote "https://example.org/image.jpg" }}
{{ $img := .Resize "800x webp" }}
<img src="{{ $img.RelPermalink }}" alt="">
{{ end }}
远程资源会增加构建时对网络的依赖。生产环境更建议把关键资源放在仓库或稳定 CDN 中。
资源合并
多个 CSS 合并:
{{ $base := resources.Get "css/base.css" }}
{{ $syntax := resources.Get "css/syntax.css" }}
{{ $css := slice $base $syntax | resources.Concat "css/bundle.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous">
多个 JS 合并:
{{ $a := resources.Get "js/a.js" }}
{{ $b := resources.Get "js/b.js" }}
{{ $js := slice $a $b | resources.Concat "js/bundle.js" | minify | fingerprint }}
<script src="{{ $js.RelPermalink }}" integrity="{{ $js.Data.Integrity }}" crossorigin="anonymous" defer></script>
如果 JS 之间有模块依赖,优先使用 js.Build。
缓存与 fingerprint
生产环境推荐:
{{ $css := resources.Get "css/main.css" | minify | fingerprint "sha384" }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous">
这样浏览器可以长期缓存文件;内容变化后文件名也会变化。
服务器或 CDN 可设置:
Cache-Control: public, max-age=31536000, immutable
没有 fingerprint 的 HTML 不要设置过长缓存。
构建模式判断
模板中可以用:
{{ if hugo.IsProduction }}
{{/* 生产环境 */}}
{{ else }}
{{/* 开发环境 */}}
{{ end }}
常见用法:
{{ $opts := dict "minify" hugo.IsProduction }}
生产构建:
HUGO_ENVIRONMENT=production hugo --minify
Windows PowerShell:
$env:HUGO_ENVIRONMENT = "production"
hugo --minify
资源缓存目录
图片处理和资源构建结果通常缓存到 resources/。缓存能提升二次构建速度。
常见 .gitignore:
/public/
/resources/
/.hugo_build.lock
如果 CI 每次重新构建,可使用平台缓存能力缓存 resources/,但不是必须。
常见问题
Q: resources.Get 返回空
A: 检查路径是否相对于 assets/。例如文件是 assets/css/main.css,模板里写 resources.Get "css/main.css"。
Q: Sass 构建失败
A: 检查是否安装 Hugo Extended。如果主题使用 Sass 新语法,再检查是否安装 Dart Sass。
Q: PostCSS 本地正常,线上失败
A: 线上没有执行 npm ci,或 Node 版本不一致。部署平台需要配置 Node.js 与安装命令。
Q: 图片没有被处理
A: 确认图片是 Page Resource 或放在 assets/ 中。static/ 中的图片不会被 Hugo Pipes 处理。
下一步
继续阅读 Hugo Modules,学习如何用模块管理主题、资源和大型站点结构。
评论