页面包与资源管理

概述

Hugo 的页面包(Page Bundles)是一种强大的内容组织方式,允许将相关的内容文件和资源(如图片、CSS、JS 等)组织在一起,形成自包含的内容单元。这种设计大大简化了资源管理和内容维护。

页面包类型

叶子包(Leaf Bundle)

叶子包是包含单个页面内容的目录,具有以下特征:

  • 包含一个 index.md 文件作为内容文件
  • 可以包含零个或多个资源文件
  • 不能包含其他子目录或子包
  • 适用于博客文章、产品页面等独立内容

叶子包结构示例

content/ └── blog/ └── my-awesome-post/ # 叶子包目录 ├── index.md # 内容文件 ├── hero-image.jpg # 页面资源 ├── diagram.png # 页面资源 └── data.json # 页面资源

叶子包的 index.md 示例

---
title: "我的精彩文章"
date: 2025-06-21
resources:
- src: "hero-image.jpg"
  title: "英雄图片"
  params:
    alt: "文章主图"
- src: "diagram.png"
  title: "示意图"
  params:
    alt: "流程图"
---

这是一篇关于 Hugo 页面包的文章。

### 分支包(Branch Bundle)

分支包是包含列表页面和子内容的目录,具有以下特征:

- 包含一个 `_index.md` 文件作为分支页面内容
- 可以包含零个或多个资源文件
- **可以包含其他子目录和子包**
- 适用于分类页面、章节页面等层级内容

#### 分支包结构示例

content/
└── tutorials/                    # 分支包目录
    ├── _index.md                 # 分支页面内容
    ├── banner.jpg                # 分支页面资源
    ├── introduction/             # 子叶子包
    │   ├── index.md
    │   └── intro-diagram.png
    └── advanced/                 # 子叶子包
        ├── index.md
        ├── screenshot1.png
        └── screenshot2.png

#### 分支包的 `_index.md` 示例

```markdown
---
title: "教程中心"
description: "全面的 Hugo 教程集合。"
resources:
- src: "banner.jpg"
  title: "教程横幅"
  params:
    alt: "教程中心横幅图片"
---

欢迎来到教程中心!这里包含了各种 Hugo 相关的教程。

资源处理

访问页面资源

在模板中可以通过多种方式访问页面资源:

{{/* 获取所有页面资源 */}}
{{ range .Resources }}
  <p>资源:{{ .Title }} - {{ .RelPermalink }}</p>
{{ end }}

{{/* 按类型获取资源 */}}
{{ $images := .Resources.ByType "image" }}
{{ range $images }}
  <img src="{{ .RelPermalink }}" alt="{{ .Params.alt }}">
{{ end }}

{{/* 获取特定资源 */}}
{{ $hero := .Resources.GetMatch "hero*" }}
{{ if $hero }}
  <img src="{{ $hero.RelPermalink }}" alt="{{ $hero.Params.alt }}">
{{ end }}

资源元数据配置

可以在 Front Matter 中为资源设置元数据:

---
title: "文章标题"
resources:
- src: "images/**.jpg"
  title: "图片 :counter"
  params:
    alt: "图片描述 :counter"
    caption: "图片说明"
- src: "documents/**.pdf"
  title: "文档 :counter"
  params:
    icon: "pdf"
---

全局资源配置

config.yaml 中可以设置全局资源处理规则:

params:
  images:
    # 图片质量设置
    quality: 85
    # 默认图片处理
    resize: "800x600"
    # WebP 转换
    webp: true

图像处理详解

基础图像操作

Hugo 提供了丰富的图像处理功能:

{{/* 获取图像资源 */}}
{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{/* 调整大小 */}}
  {{ $resized := $image.Resize "800x600" }}
  {{ $fitted := $image.Fit "800x600" }}
  {{ $filled := $image.Fill "800x600 Center" }}
  
  <div class="image-variants">
    <img src="{{ $resized.RelPermalink }}" alt="调整大小">
    <img src="{{ $fitted.RelPermalink }}" alt="适应大小">
    <img src="{{ $filled.RelPermalink }}" alt="填充裁剪">
  </div>
{{ end }}

响应式图像

创建响应式图像集合:

{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{ $sizes := slice "400" "600" "800" "1200" }}
  {{ $srcset := slice }}
  
  {{ range $sizes }}
    {{ $resized := $image.Resize (printf "%sx" .) }}
    {{ $srcset = $srcset | append (printf "%s %sw" $resized.RelPermalink .) }}
  {{ end }}
  
  <img 
    src="{{ ($image.Resize "800x").RelPermalink }}"
    srcset="{{ delimit $srcset ", " }}"
    sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
    alt="{{ .Title }}"
  >
{{ end }}

图像效果处理

{{ $image := .Resources.GetMatch "photo.jpg" }}
{{ if $image }}
  {{/* 颜色调整 */}}
  {{ $brightened := $image | images.Brightness 20 }}
  {{ $contrasted := $image | images.Contrast 1.3 }}
  {{ $saturated := $image | images.Saturation 1.2 }}
  
  {{/* 滤镜效果 */}}
  {{ $grayscale := $image | images.Grayscale }}
  {{ $sepia := $image | images.Sepia }}
  {{ $inverted := $image | images.Invert }}
  
  {{/* 模糊和锐化 */}}
  {{ $blurred := $image | images.GaussianBlur 5 }}
  {{ $sharpened := $image | images.UnsharpMask 1.0 1.0 0.05 }}
  
  <div class="image-effects">
    <img src="{{ $brightened.RelPermalink }}" alt="提亮">
    <img src="{{ $grayscale.RelPermalink }}" alt="灰度">
    <img src="{{ $blurred.RelPermalink }}" alt="模糊">
  </div>
{{ end }}

图像格式转换

{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{/* WebP 格式转换 */}}
  {{ $webp := $image.Resize "800x q85 webp" }}
  {{ $avif := $image.Resize "800x q85 avif" }}
  
  <picture>
    <source srcset="{{ $avif.RelPermalink }}" type="image/avif">
    <source srcset="{{ $webp.RelPermalink }}" type="image/webp">
    <img src="{{ $image.RelPermalink }}" alt="{{ .Title }}">
  </picture>
{{ end }}

图像水印和文字

{{ $image := .Resources.GetMatch "photo.jpg" }}
{{ if $image }}
  {{/* 添加文字水印 */}}
  {{ $watermarked := $image | images.Text (dict
    "text" "© 2025 MyWebsite"
    "x" 20
    "y" 20
    "size" 24
    "color" "#ffffff"
    "linespacing" 2
  ) }}
  
  {{/* 添加图片水印 */}}
  {{ $logo := resources.Get "images/logo.png" }}
  {{ if $logo }}
    {{ $logoed := $image | images.Overlay $logo 10 10 }}
    <img src="{{ $logoed.RelPermalink }}" alt="带标志的图片">
  {{ end }}
  
  <img src="{{ $watermarked.RelPermalink }}" alt="带水印的图片">
{{ end }}

高级图像处理

图像信息获取

{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{ $config := $image | images.Config }}
  
  <div class="image-info">
    <p>尺寸:{{ $config.Width }}×{{ $config.Height }}</p>
    <p>颜色模式:{{ $config.ColorModel }}</p>
    <p>文件大小:{{ $image.Params.byteSize | humanize.Bytes }}</p>
  </div>
  
  {{/* 根据图像比例调整处理 */}}
  {{ $ratio := div (float $config.Width) $config.Height }}
  {{ if gt $ratio 1.5 }}
    {{/* 宽图片处理 */}}
    {{ $processed := $image.Fill "1200x400 Smart" }}
    <img src="{{ $processed.RelPermalink }}" alt="宽屏图片">
  {{ else }}
    {{/* 方形或高图片处理 */}}
    {{ $processed := $image.Fill "600x600 Smart" }}
    <img src="{{ $processed.RelPermalink }}" alt="方形图片">
  {{ end }}
{{ end }}

智能裁剪

{{ $image := .Resources.GetMatch "portrait.jpg" }}
{{ if $image }}
  {{/* 智能裁剪选项 */}}
  {{ $smart := $image.Fill "400x400 Smart" }}
  {{ $center := $image.Fill "400x400 Center" }}
  {{ $top := $image.Fill "400x400 Top" }}
  {{ $bottom := $image.Fill "400x400 Bottom" }}
  {{ $left := $image.Fill "400x400 Left" }}
  {{ $right := $image.Fill "400x400 Right" }}
  
  <div class="crop-examples">
    <img src="{{ $smart.RelPermalink }}" alt="智能裁剪">
    <img src="{{ $center.RelPermalink }}" alt="居中裁剪">
    <img src="{{ $top.RelPermalink }}" alt="顶部裁剪">
  </div>
{{ end }}

图像懒加载

创建带有懒加载的图像:

{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{/* 创建低质量占位图 */}}
  {{ $placeholder := $image.Fill "40x40 q20" }}
  {{ $full := $image.Resize "1200x q85" }}
  
  <img 
    src="{{ $placeholder.RelPermalink }}"
    data-src="{{ $full.RelPermalink }}"
    class="lazy-load"
    alt="{{ .Title }}"
    loading="lazy"
  >
{{ end }}

最佳实践

页面包组织原则

  1. 内容相关性:将相关的内容和资源放在同一个包中

content/ └── projects/ └── awesome-project/ ├── index.md # 项目介绍 ├── screenshot.png # 项目截图 ├── architecture.svg # 架构图 └── demo-video.mp4 # 演示视频

  1. 资源命名规范:使用有意义的文件名
{{/* 好的命名 */}}
hero-image.jpg
product-screenshot-01.png
user-manual.pdf

{{/* 避免的命名 */}}
image1.jpg
screenshot.png
doc.pdf

性能优化策略

  1. 图像优化
{{/* 统一的图像处理管道 */}}
{{ $image := .Resources.GetMatch "hero.jpg" }}
{{ if $image }}
  {{ $optimized := $image.Resize "1200x q85" }}
  {{ if ge hugo.Version.Minor 89 }}
    {{ $optimized = $optimized.Process "webp q85" }}
  {{ end }}
  <img src="{{ $optimized.RelPermalink }}" alt="{{ .Title }}">
{{ end }}
  1. 资源缓存
{{/* 缓存复杂的图像处理 */}}
{{ $cacheKey := printf "%s-%s" .File.UniqueID "processed-images" }}
{{ $processed := partialCached "process-images.html" . $cacheKey }}

错误处理

{{/* 安全的资源访问 */}}
{{ $image := .Resources.GetMatch "hero.*" }}
{{ if $image }}
  {{ $resized := $image.Resize "800x600" }}
  <img src="{{ $resized.RelPermalink }}" alt="{{ .Title }}">
{{ else }}
  {{/* 回退方案 */}}
  {{ $fallback := resources.Get "images/default-hero.jpg" }}
  {{ if $fallback }}
    <img src="{{ $fallback.RelPermalink }}" alt="默认图片">
  {{ else }}
    <div class="image-placeholder">图片加载失败</div>
  {{ end }}
{{ end }}

国际化支持

{{/* 多语言资源处理 */}}
{{ $lang := .Language.Lang }}
{{ $imagePattern := printf "hero-%s.*" $lang }}
{{ $image := .Resources.GetMatch $imagePattern }}
{{ if not $image }}
  {{/* 回退到默认语言图片 */}}
  {{ $image = .Resources.GetMatch "hero.*" }}
{{ end }}

{{ if $image }}
  <img src="{{ $image.RelPermalink }}" alt="{{ .Title }}">
{{ end }}

实用模板片段

图片画廊组件

创建 layouts/_partials/image-gallery.html

{{ $images := .Resources.ByType "image" }}
{{ if $images }}
<div class="image-gallery">
  {{ range $images }}
    {{ $thumb := .Fill "300x200 Smart" }}
    {{ $full := .Resize "1200x q85" }}
    <div class="gallery-item">
      <a href="{{ $full.RelPermalink }}" data-lightbox="gallery">
        <img src="{{ $thumb.RelPermalink }}" alt="{{ .Title }}" loading="lazy">
      </a>
      {{ with .Params.caption }}
        <p class="caption">{{ . }}</p>
      {{ end }}
    </div>
  {{ end }}
</div>
{{ end }}

响应式图像组件

创建 layouts/_partials/responsive-image.html

{{ $image := .image }}
{{ $alt := .alt | default $image.Title }}
{{ $sizes := .sizes | default "(max-width: 768px) 100vw, 50vw" }}

{{ if $image }}
  {{ $small := $image.Resize "400x q85" }}
  {{ $medium := $image.Resize "800x q85" }}
  {{ $large := $image.Resize "1200x q85" }}
  
  <img 
    src="{{ $medium.RelPermalink }}"
    srcset="{{ $small.RelPermalink }} 400w, {{ $medium.RelPermalink }} 800w, {{ $large.RelPermalink }} 1200w"
    sizes="{{ $sizes }}"
    alt="{{ $alt }}"
    loading="lazy"
  >
{{ end }}

使用方式:

{{ $heroImage := .Resources.GetMatch "hero.*" }}
{{ partial "responsive-image.html" (dict "image" $heroImage "alt" "英雄图片") }}

小结

Hugo 的页面包和资源管理系统提供了:

  1. 灵活的内容组织:叶子包和分支包满足不同的内容组织需求
  2. 强大的图像处理:从基础调整到高级效果,满足现代网站的图像需求
  3. 性能优化:响应式图像、格式转换、懒加载等现代化特性
  4. 开发友好:清晰的 API、丰富的配置选项、完善的错误处理

通过合理使用页面包和资源管理功能,可以构建结构清晰、性能优秀的现代化网站。建议在实际项目中根据内容特点选择合适的组织方式,并利用 Hugo 的强大图像处理能力优化用户体验。

有关模块系统的内容,请参考 Hugo 模块系统 章节。有关更多模板功能,请参考 模板系统 章节。

文章导航

章节内容

这是章节的内容页面。

章节概览