这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

开始使用

使用 Hugo Extended 构建中英双语 Oink 文档站。

Oink 是一款将完整浏览器运行时随主题提供的 Hugo 主题。消费站点只需 Hugo Extended 即可构建;默认流程不安装 Node.js 软件包、不运行 PostCSS、不依赖 CDN,也不会在构建期间远程下载主题资源。

选择起点

  • Hugo Module(推荐):在已有或新建 Hugo 站点中导入 github.com/pgsty/oink。参阅 Oink 快速开始
  • 项目站点:把独立的 pgsty/oink.pgsty.com 仓库作为完整双语配置与回归参考。
  • 现有 Docsy 站点:按照迁移指南删除公共覆盖和消费端 npm 资源管线,无需重写正文。

安装前提条件

安装 Git、Go 与 Hugo Extended 0.160.1 或更高版本。平台说明和验证命令请参阅开始之前

添加 Oink

在站点根目录运行:

hugo mod init github.com/example/product-docs
hugo mod get github.com/pgsty/oink@THEME_REF

然后在 hugo.yaml 中导入主题:

module:
  imports:
    - path: github.com/pgsty/oink

THEME_REF 固定为发布标签或不可变 commit,并提交 go.modgo.sum

构建契约

所有受支持的模块消费站点都使用相同的预览与构建命令:

hugo server --disableFastRender
hugo --gc --minify

后续步骤

  1. 完成基础配置
  2. 设置代码仓库、版权信息、Logo 和菜单。
  3. page.mdpage.zh.md 的形式并置译文。
  4. 添加并自定义内容
  5. 选择部署目标

1 - 使用 Oink 主题

导入 Oink Hugo Module,或查看独立项目站点。

Oink 将消费站点与持续维护的主题分开。站点负责自己的内容、品牌素材、配置和业务组件;主题负责公共外壳、样式、浏览器运行时与可复用短代码。

github.com/pgsty/oink 作为固定版本的 Hugo Module 导入。独立的 pgsty/oink.pgsty.com 仓库通过中英文内容、本地搜索、深色模式、图表、API 文档与组件示例,演示完整生产契约。

熟悉 Hugo 的用户可以从零开始。现有 Docsy 站点应使用迁移指南,不要手工重新创建外壳。

主题源码选项

推荐使用已发布的 github.com/pgsty/oink 模块标签。完整发布归档、固定版本的 Git submodule 或固定 commit 的 clone 也可以使用。选择之前请阅读其他安装方式;生产环境绝不能跟随未固定版本的分支。

构建契约

无论选择哪一种源码方式,都必须能够通过以下命令构建站点:

hugo --gc --minify

项目站点仓库中的 Node 命令只供维护者运行回归测试,不是消费站点的前提条件。

1.1 - 开始之前

构建 OINK 站点的前提条件。

消费端唯一必需的工具是 Hugo Extended。是否需要 Git 和 Go,取决于主题源码的获取方式。

安装 Hugo Extended

安装 0.160.1 或更高版本。当前验证基线为 0.164.0。如果发布版本调整了这些数值,应以对应版本的支持矩阵为准。

核对实际选中的二进制文件:

hugo version

输出必须包含 extended;标准版 Hugo 无法编译主题的 SCSS。请根据平台使用 Hugo 官方安装指南,并在本地开发与 CI 中固定同一版本。

按需安装 Git

克隆站点、使用 submodule、保留 .GitInfo 或获取主题 checkout 时需要 Git。运行以下命令验证:

git --version

从已经解压的离线归档构建站点时,Hugo 可以在没有网络的情况下运行;不过仍建议使用版本控制管理源码。

只有 Hugo 模块需要 Go

Hugo 模块命令会使用 Go。如果站点以 Hugo 模块形式导入主题,请安装 Go 并运行:

go version
hugo mod graph

使用固定版本归档、相邻主题目录或 Git submodule 时,站点构建不需要 Go。

不要安装前端工具链

OINK 将 Bootstrap、Font Awesome、LTR 与 RTL CSS、字体、搜索和浏览器运行时作为有版本的本地资源提供。消费站点不需要为主题安装 Node.js、npm、PostCSS、Autoprefixer 或 RTLCSS。

项目站点仓库中的 Node 命令只供维护者使用。消费端的生产命令是:

hugo --gc --minify

检查完整发行物

用于离线或网络隔离环境时,请确认主题归档包含 go.modhugo.yamlassets/layouts/static/i18n/LICENSENOTICEVENDOR.json。进入隔离环境前安装 Hugo Extended,然后在禁用网络的情况下运行同一个构建命令。

后续步骤

1.2 - 查看双语项目站点

把独立 Oink 项目站点作为完整参考。

独立的 pgsty/oink.pgsty.com 仓库是完整的双语示例与回归站点。它有意比 starter 更全面:应把它作为参考,然后只保留产品真正需要的内容与配置。

克隆项目站点

Oink 主题公开发布后,可以直接克隆并构建站点:

git clone https://github.com/pgsty/oink.pgsty.com.git product-docs
cd product-docs
hugo --gc --minify

已提交的 go.mod 会固定 github.com/pgsty/oink。本地开发主题时,请把主题克隆为同级目录,并使用 Oink 快速开始记录的 workspace 命令。

运行站点检查

Hugo 本身即可构建站点。Node.js 只用于项目站点的格式、链接、翻译与回归检查:

npm install
npm test

打开生成的站点,分别检查中英文页面。请从具有译文的详情页使用语言切换器,不要只在首页测试。

替换示例身份

编辑 hugo.yamlconfig/ 下的文件,并替换:

  • 站点标题,以及各语言的标题与描述;
  • baseURL
  • 代码仓库与分支 URL;
  • 版权所有者与起始年份;
  • Logo 与品牌素材;
  • 中英文菜单标签。

不要创建 oink.* 参数命名空间。请使用 Hugo 的语言、菜单、模块、输出和 markup 设置,以及主题已经记录的参数。

替换示例内容

把每组译文放在一起:

content/docs/getting-started.md
content/docs/getting-started.zh.md

删除产品不需要的历史与回归内容。只有在页面不再引用后,才删除对应示例资源。

中文标题应显式使用英文页面实际渲染出的 ID:

## Configure search
## 配置搜索 {#configure-search}

将新站点纳入版本控制

发布派生站点前,请修改模块路径、仓库元数据与 remote。继续在 go.mod 中固定 Oink 版本。除非托管工作流有明确要求,否则不要提交生成的 public/ 产物。

后续步骤

1.3 - 新建站点:从零开始

在没有前端工具链的情况下创建最小双语 OINK 站点。

独立的双语项目站点是完整参考。需要更小、拥有自身内容结构的站点时,可以采用本流程。

创建站点骨架

运行:

hugo new site --format yaml my-new-site
cd my-new-site

初始化站点模块并固定 Oink:

hugo mod init github.com/example/my-new-site
hugo mod get github.com/pgsty/oink@THEME_REF

添加最低配置

将以下内容保存为 hugo.yaml

title: Product Docs
baseURL: https://docs.example.com/
defaultContentLanguage: en

languages:
  en:
    label: English
    locale: en-US
    weight: 1
    menus:
      main:
        - { name: Docs, pageRef: /docs, weight: 10 }
        - { name: Blog, pageRef: /blog, weight: 20 }
  zh:
    label: 简体中文
    locale: zh-CN
    weight: 2
    menus:
      main:
        - { name: 文档, pageRef: /docs, weight: 10 }
        - { name: 博客, pageRef: /blog, weight: 20 }

markup:
  goldmark:
    renderer:
      unsafe: true
  highlight:
    noClasses: false

params:
  offlineSearch: true
  ui:
    showLightDarkModeMenu: true
    sidebar_menu_foldable: true

module:
  imports:
    - path: github.com/pgsty/oink
  hugoVersion:
    extended: true
    min: 0.160.1

提交 go.modgo.sum。不要添加 npm 挂载项或 PostCSS 管线。

添加双语内容

创建以下文件:

content/
├── _index.md
├── _index.zh.md
├── docs/
│   ├── _index.md
│   ├── _index.zh.md
│   ├── getting-started.md
│   └── getting-started.zh.md
└── blog/
    ├── _index.md
    └── _index.zh.md

每个页面都需要 front matter。例如,content/docs/getting-started.md 可以写成:

---
title: Getting started
weight: 10
---

## Install {#install}

Install the product.

它的 getting-started.zh.md 译文保留显式标题 ID:

---
title: 开始使用
weight: 10
---

## 安装 {#install}

安装产品。

在两个示例中使用相同的显式 ID 不会产生问题,还能直观展示跨语言合同。翻译现有页面时,应从英文渲染 HTML 中复制 ID。

预览与构建

启动开发服务器:

hugo server --disableFastRender

随后单独验证生产构建:

hugo --gc --minify

添加自定义布局前,请检查 /docs//zh/docs/、语言选择器、本地搜索索引和浏览器控制台。

逐步添加功能

先复制 Logo 和品牌素材,再添加代码仓库链接与菜单。只在确实需要的页面中加入图表、API 文档和内容组件;OINK 会按需发布对应的本地运行时。

如果站点需要带业务语义的短代码,请将其保留在站点自己的 layouts/_shortcodes/ 下。只有接口已经摆脱站点假设,并且能被多个站点复用后,才应移入主题。

后续步骤

2 - 其他安装方式

使用 OINK 归档、Git checkout 或 Hugo Module。

推荐安装方式是使用 github.com/pgsty/oink Hugo Module。以下选项只改变 Hugo 获取同一份主题源码的方式,不会改变内容,也不会改变 Hugo-only 构建命令。

前提条件

所有方式都需要 Hugo Extended 0.160.1 或更高版本。Git 方式需要 Git,Hugo 模块需要 Go。消费站点采用任何一种方式都不需要 Node.js、npm、PostCSS 或 Autoprefixer。

选项 1:完整发布归档

完整离线归档包含主题、本地浏览器运行时、字体、许可证、NOTICE、vendor 清单和 checksum。它是网络隔离构建的首选输入,也是保留准确发行物最简单的方式。

把主题解压到站点的 themes/ 目录:

site/
├── hugo.yaml
└── themes/
    └── oink/

配置如下:

theme: oink

解压前先校验归档 checksum。只能使用明确发布版本附带的归档,不要把本地组装文件表述为已经发布的发行物。

选项 2:Git submodule

submodule 会在站点仓库中记录准确的 OINK 仓库 commit:

git submodule add https://github.com/pgsty/oink.git themes/oink
git -C themes/oink fetch --tags
git -C themes/oink checkout THEME_REF
git add .gitmodules themes/oink
git commit -m "Add OINK theme at THEME_REF"

配置嵌套主题路径:

theme: oink

CI 必须在运行 Hugo 前初始化 submodule。请将 THEME_REF 固定为发布标签或不可变的 commit,不要让生产环境跟随 main

选项 3:固定版本的 Git 克隆

如果托管平台要求构建输入包含完整主题树,或者站点需要随仓库提供已经评审的副本,可以使用克隆:

git clone https://github.com/pgsty/oink.git themes/oink
git -C themes/oink checkout THEME_REF

同样设置 theme: oink。请记录最终解析出的 commit,以及恢复克隆的流程。如果把这些文件提交到站点仓库,必须保留 OINK 的 LICENSENOTICEVENDOR.json

OINK 不以 npm 包形式发行。现有 Docsy npm 用户应遵循 npm 迁移指南

选项 4:Hugo Module

把公开模块固定到发布标签或不可变 commit:

hugo mod get github.com/pgsty/oink@THEME_REF
hugo mod tidy

hugo.yaml 中导入:

module:
  imports:
    - path: github.com/pgsty/oink

本地开发主题时,请使用被忽略的 Go workspace,把站点模块与同级 OINK checkout 一起加入。

预览与验证

所有源码方式都使用相同命令:

hugo server --disableFastRender
hugo --gc --minify

请验证:全新生产构建能够在没有 node_modules 目录的情况下完成;本地资源能在配置的 baseURL 下正确解析;中英文页面与搜索索引都已经生成。

版本变更和覆盖审查请参阅更新 OINK

3 - 在容器中运行 OINK

使用 Hugo Extended 容器构建和预览 OINK 站点。

容器并非必需:OINK 本身只需要 Hugo Extended。如果团队希望固定工具镜像,或不想在开发者工作站上安装 Hugo,可以选择容器方式。

创建 Hugo 镜像

下面的 Dockerfile 从发布包安装当前验证过的 Hugo Extended 版本。请让该版本始终与主题支持矩阵保持一致。

FROM debian:bookworm-slim

ARG HUGO_VERSION=0.164.0
ARG TARGETARCH

RUN apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates curl git \
    && curl -L -o /tmp/hugo.deb \
      "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.deb" \
    && apt-get install -y /tmp/hugo.deb \
    && rm -rf /var/lib/apt/lists/* /tmp/hugo.deb

WORKDIR /src
EXPOSE 1313
ENTRYPOINT ["hugo"]
CMD ["server", "--bind", "0.0.0.0", "--disableFastRender"]

在站点根目录构建镜像:

docker build -t oink-hugo .

镜像构建过程会下载 Hugo。在网络隔离环境中,请预先镜像基础镜像和 Hugo 软件包,或者将 OINK 完整离线发行包与获准使用的内部镜像组合使用。

预览站点

挂载完整站点源码,包括相邻存放或随站点提供的主题:

docker run --rm -it \
  -p 1313:1313 \
  -v "$PWD:/src" \
  oink-hugo

打开 http://localhost:1313/。宿主机上的变更会被容器中的 Hugo 实时重载进程检测到。

执行生产构建

覆盖默认的 server 命令:

docker run --rm \
  -v "$PWD:/src" \
  oink-hugo --gc --minify

生成的站点会写入挂载源码目录中的 public/。请确保容器用户对该目录具有写权限;在共享环境中,应按本地策略映射用户 ID 或修正文件所有权。

这个镜像不需要 Node.js、npm、PostCSS,也不应包含远程浏览器资源步骤。

4 - 站点基础配置

配置 OINK 站点、语言、导航与本地功能。

Hugo 从 hugo.yamlhugo.tomlhugo.json 读取站点级设置。Oink 项目站点使用 YAML,因为多语言菜单和主题选项更便于浏览与评审。

最低配置

下面的节选展示了 Hugo Module 的关键结构。

title: Product Documentation
baseURL: https://docs.example.com/
defaultContentLanguage: en

languages:
  en:
    label: English
    locale: en-US
    weight: 1
    title: Product Documentation
    menus:
      main:
        - name: Docs
          pageRef: /docs
          weight: 10
        - name: Blog
          pageRef: /blog
          weight: 20
  zh:
    label: 简体中文
    locale: zh-CN
    weight: 2
    title: 产品文档
    menus:
      main:
        - name: 文档
          pageRef: /docs
          weight: 10
        - name: 博客
          pageRef: /blog
          weight: 20

markup:
  goldmark:
    renderer:
      unsafe: true
  highlight:
    noClasses: false

params:
  offlineSearch: true
  github_repo: https://github.com/example/product-docs
  github_branch: main
  copyright:
    authors: Example Authors
    from_year: 2026
  ui:
    showLightDarkModeMenu: true
    sidebar_menu_foldable: true
    breadcrumb_disable: false

module:
  imports:
    - path: github.com/pgsty/oink
  hugoVersion:
    extended: true
    min: 0.160.1

英文权重为 1,也是默认语言;简体中文权重为 2;其他语言依次排列。直接点击语言按钮时会按此顺序切换,完整的悬停菜单也采用相同顺序。

内容译文

将译文并置存放:

content/
├── _index.md
├── _index.zh.md
├── docs/
│   ├── _index.md
│   ├── _index.zh.md
│   ├── install.md
│   └── install.zh.md
└── blog/
    ├── release.md
    └── release.zh.md

会影响路由的元数据应保持一致。标题、描述、菜单标签、摘要、标签、图片替代文字和短代码中的可见字符串都需要翻译。每个中文标题都应显式使用英文页面实际渲染出的标题 ID,确保不同语言中的 URL 片段保持稳定。

本地搜索与浏览器资源

offlineSearch: true 会启用主题的同源 Lunr 索引和 CJK 回退。索引按语言分别生成。除非站点明确接受相应的网络依赖,否则不要配置公共搜索服务。

Mermaid、KaTeX、Markmap、Swagger UI、Redoc、Asciinema、ECharts 和 Infographic 都由主题本地提供,并按页面加载。PlantUML 和 Draw.io 属于依赖服务的例外:请显式配置获准使用的端点,否则保持禁用。

在站点层设置 title、各语言标题、params.logo、代码仓库 URL、版权和菜单。OINK 不新增 oink.* 配置树,而是沿用 Hugo 与兼容 Docsy 参数的位置。

代码仓库元数据用于在内容页提供编辑、查看、提交问题和内容年龄信息。请确保 github_repogithub_project_repogithub_branchgithub_subdir 同源码布局一致。

生产默认值

  • 使用真实的生产 baseURL,包括可能存在的子路径。
  • 除非属于明确的产品决策,否则关闭在线分析、评论、Google CSE、Algolia 和远程嵌入。
  • 在 CI 中固定 Hugo Extended 和主题版本。
  • 使用 hugo --gc --minify 作为生产构建命令。
  • 重新分发归档时保留 LICENSENOTICE 和 vendor 清单。

可构建的完整参考配置请查看项目站点的 hugo.yaml

5 - 故障排查与已知问题

诊断 OINK 安装、构建、语言、搜索与平台问题。

请从一次干净的生产构建开始诊断:

hugo --gc --minify --logLevel info

消费端命令不应调用 npm、PostCSS、Autoprefixer,也不应下载主题浏览器资源。

构建问题

Hugo 不是 Extended 版本或版本过旧

运行 hugo version。输出必须包含 extended,版本也不得低于 0.160.1。如果 shell、编辑器、CI runner 或容器仍然选中了旧二进制文件,请检查它的 PATH 和固定工具配置,不要盲目再安装一份。

找不到主题

module "github.com/pgsty/oink" not found 一类错误表示 Hugo 无法解析配置中的主题。请按所选安装方式检查:

  • 对于 Git checkout,主题名称必须与目录路径一致;
  • 对于 Hugo 模块,运行 hugo mod graph,并检查 go.modgo.sum,以及所有 Hugo workspace 或 replacement;
  • 对于 CI checkout,请在运行 Hugo 前初始化固定版本的 submodule,或恢复完整发布归档。

缺少本地浏览器资源

如果缺少 Bootstrap、Font Awesome、Lunr、Mermaid 或其他 OINK 资源,不要通过添加 CDN URL 来掩盖问题。请确认发行物完整,并包含 assets/third_party/assets/js/third_party/static/webfonts/VENDOR.json。如果确有文件缺失,请重新解压或获取同一个固定版本。

译文页面没有出现

逐项检查以下四个条件:

  1. hugo.yaml 中存在 languages.zh,并且设置了权重。
  2. 文件名是 page.zh.md,其中 zh 必须小写。
  3. 译文 front matter 没有设置 draft: true,日期也不在未来。
  4. 除非有意采用不同路由,否则会影响路由的元数据应与源文件一致。

当 Hugo 能找到页面译文时,语言选择器会直接链接过去;否则会按设计回退到目标语言首页。

翻译后的标题文字通常会生成不同的自动 ID。请在译文标题中显式加入英文渲染 ID:

## 安装 {#installation}

不要推测包含短代码或内联 HTML 的标题 ID。请检查英文渲染结果,再比较中英文标题 ID 列表。

搜索问题

启用 offlineSearch: true 后,每种语言都会生成自己的搜索索引。请确认输出中存在 offline-search-index.en.jsonoffline-search-index.zh.json,并检查浏览器是否从站点 base URL 请求这些文件。子路径部署中,错误的 baseURL 是索引缺失的常见原因。

中文分词使用主题的 CJK 回退。如果搜索结果为空,应先确认中文页面内容确实进入中文索引,而不是立即修改分词器。

平台问题

macOS 报告打开文件过多

大型实时预览内容树可能超过 shell 的打开文件数限制。通过 ulimit -n 查看当前限制;如果本地策略允许,可以为当前 shell 临时提高限制。在修改整台机器的限制之前,应优先从监视树中排除生成目录和无关目录。

Windows Subsystem for Linux 速度慢或遗漏变更

请让 Hugo 处理 Linux 文件系统中的路径,而不是 Windows 挂载路径。跨文件系统的通知与权限行为可能让实时重载变慢或不可靠。

诊断清单

  • 使用固定的准确 Hugo Extended 版本复现问题。
  • 通过项目规定的清理命令删除陈旧的 public/resources/ 产物,再重新构建。
  • 比较开发环境与生产环境的配置层。
  • 关注第一条构建错误,而不只是最后出现的级联报错。
  • 使用最小页面区分主题行为与站点覆盖。
  • 分小组逐步重新启用站点覆盖和内容组件。
  • 检查故障页面的浏览器控制台和网络日志。