页面资源管理:图片、附件、音频、代码块等
通过页面包(Page Bundle)方式将图片、音频等资源与内容放在同一目录,方便引用和迁移。利用 .Resources 访问这些文件,并结合 resources.Get 等函数进行按需处理,使资源管理更有条理。
阅读本节后,你将理解页面资源管理:图片、附件、音频、代码块等在构建流程中的角色,并掌握常见配置方式。
讲解如何借助 resources 管理器处理图片派生和指纹,使引用路径始终稳定。
还会分享调试和优化经验,帮助在复杂场景下保持文档与代码的可维护性。
页面包:内容与资源的结合
Hugo 的页面包(Page Bundle)是一种将内容文件(Markdown)与其相关资源(图片、PDF、附件等)组织在一起的方式。这种方式让内容和资源内聚,便于管理和迁移。
页面包主要分为两种类型:
叶子包 (Leaf Bundle)
叶子包是一个包含 index.md 文件的目录。该目录下的所有其他文件都被视为与这个页面关联的页面资源,它们只能通过这个页面进行访问。
content/
└── blog/
└── my-awesome-post/
├── index.md # 页面内容
├── cover.jpg # 页面资源
├── chart.png # 页面资源
└── data.json # 页面资源
- 适用场景:单个博客文章、产品介绍页等独立的、有自己专属资源的内容页面。
- URL:
my-awesome-post目录名决定了页面的 URL,例如/blog/my-awesome-post/。
分支包 (Branch Bundle)
分支包是一个包含 _index.md 文件的目录。它本身是一个列表页面,同时也可以有自己的页面资源。其下的子目录可以是叶子包或其他分支包。
content/
└── gallery/
├── _index.md # gallery 列表页内容
├── header.jpg # gallery 列表页的资源
├── nature/ # 子内容区(分支包)
│ ├── _index.md
│ └── featured.png
└── city/ # 子内容区(叶子包)
├── index.md
└── new-york.jpg
- 适用场景:内容区的概览页面,如博客列表页、相册主页。
- URL:
gallery目录名决定了其 URL,例如/gallery/。
访问页面资源
一旦你将资源组织在页面包中,就可以在模板中通过页面的 .Resources 变量来访问它们。.Resources 是一个包含了所有该页面资源的集合。
{{/* 在 single.html 模板中 */}}
<h1>{{ .Title }}</h1>
<div>{{ .Content }}</div>
<h2>本页资源列表:</h2>
<ul>
{{ range .Resources }}
<li><a href="{{ .RelPermalink }}">{{ .Name }}</a> ({{ .MediaType }})</li>
{{ end }}
</ul>
.Resources:一个可遍历的集合,包含页面包内除index.md或_index.md外的所有文件。.RelPermalink:资源的相对链接。.Name:资源的文件名。.MediaType:资源的媒体类型,如image/jpeg。
资源类型与筛选
通常我们不希望列出所有资源,而是需要筛选出特定类型或名称的资源。.Resources 提供了多种筛选方法。
按资源类型筛选
使用 .Resources.ByType 方法可以方便地获取特定类型的资源,如所有图片。
<h3>本页所有图片:</h3>
{{ range .Resources.ByType "image" }}
<img src="{{ .RelPermalink }}" alt="{{ .Name }}" />
{{ end }}
按文件名匹配
使用 .Resources.Match 方法可以通过 Glob 模式匹配文件名。
{{/* 获取所有 .jpg 文件 */}}
{{ range .Resources.Match "*.jpg" }}
<img src="{{ .RelPermalink }}" alt="{{ .Name }}">
{{ end }}
{{/* 获取所有以 "cover" 开头的文件 */}}
{{ $cover := .Resources.Match "cover.*" }}
图片处理
页面资源最强大的功能之一是图片处理。你可以对获取到的图片资源进行动态的裁剪、缩放、格式转换等操作。
假设 my-awesome-post 页面包中有一张 cover.jpg。
{{ $original := .Resources.GetMatch "cover.jpg" }}
{{ if $original }}
{{/* 缩放图片到 800px 宽,并保持宽高比 */}}
{{ $thumb := $original.Resize "800x" }}
<img src="{{ $thumb.RelPermalink }}" width="{{ $thumb.Width }}" height="{{ $thumb.Height }}">
{{/* 裁剪图片为 400x400 大小,并转换为 webp 格式 */}}
{{ $cropped := $original.Fill "400x400" }}
{{ $webp := $cropped.Process "webp" }}
<img src="{{ $webp.RelPermalink }}">
{{ end }}
.Resources.GetMatch:获取单个匹配的资源。.Resize、.Fill:图片处理函数。.Process:进行格式转换等处理。- 指纹保护:所有经过处理的资源,Hugo 都会为其生成带哈希指纹的文件名(如
cover_hu345f.jpg),以实现高效的浏览器缓存控制。你无需关心文件名,只需使用返回对象的.RelPermalink即可。
其他资源的处理
同样的方式也适用于非图片资源。例如,你可以列出所有 PDF 附件供用户下载。
<h3>附件下载:</h3>
<ul>
{{ range .Resources.Match "*.pdf" }}
<li>
<a href="{{ .RelPermalink }}" download>{{ .Title }}</a> ({{ .MediaType }})
</li>
{{ end }}
</ul>
.Title:你可以在资源的 Front Matter 中为其指定一个更友好的标题。只需在页面包中创建一个与资源同名的.md文件即可。my-awesome-post/ ├── my-document.pdf └── my-document.pdf.mdmy-document.pdf.md文件内容:--- title: "我的年度报告" ---
全局资源管理
对于需要在整个网站多处使用的资源(如 logo、全局 CSS/JS),应将它们放在 assets 目录下,并通过 resources.Get 进行调用和处理。
{{ $logo := resources.Get "images/logo.png" }}
{{ $resizedLogo := $logo.Resize "200x" }}
<img src="{{ $resizedLogo.RelPermalink }}">
最佳实践
- 优先使用页面包:对于与特定内容紧密相关的资源,应优先使用页面包进行管理。这使得内容更具可移植性。
- 利用图片处理:充分利用 Hugo Pipes 的图片处理能力,为不同设备和场景生成最优化的图片版本,提升网站性能。
- 为资源添加元数据:通过创建同名的
.md文件,为资源(特别是文档和附件)提供描述性的title和其他参数。 - 区分
assets和static:需要 Hugo 处理的资源(如 SCSS、需要优化的图片)放入assets;无需处理、直接复制的资源(如robots.txt、字体文件)放入static。
通过这套强大的资源管理系统,你可以构建出结构清晰、易于维护且性能卓越的 Hugo 网站。