CONTENT MANAGEMENT

URL management

概覽

預設情況下,當 Hugo 渲染頁面時,生成的 URL 會與 content 目錄中的檔案路徑相符。例如:

content/posts/post-1.md → https://example.org/posts/post-1/

您可以通過前端資料的值和網站配置選項來改變 URL 的結構和顯示方式。

前端資料

slug

在前端資料中設定 slug,以覆蓋路徑的最後一個段落。slug 值不會影響區塊頁面。

content/posts/post-1.md
     
---
slug: my-first-post
title: My First Post
---
+++
slug = 'my-first-post'
title = 'My First Post'
+++
{
   "slug": "my-first-post",
   "title": "My First Post"
}

生成的 URL 會是:

https://example.org/posts/my-first-post/

url

在前端資料中設定 url,以覆蓋整個路徑。可以與常規頁面或區塊頁面一起使用。

如果在前端資料中同時設定了 slugurl,則以 url 的值為主。

包含冒號

New in v0.136.0

如果需要在 url 前端資料欄位中包含冒號,請使用反斜線字符轉義。如果字符串使用單引號包裹,請使用一個反斜線;如果使用雙引號包裹,請使用兩個反斜線。在 YAML 前端資料中,如果省略引號,請使用單個反斜線。

例如,使用以下前端資料:

content/example.md
     
---
title: Example
url: my\:example
---
+++
title = 'Example'
url = 'my\:example'
+++
{
   "title": "Example",
   "url": "my\\:example"
}

生成的 URL 會是:

https://example.org/my:example/

如上所述,這會在 Windows 上失敗,因為冒號(:)是保留字符。

檔案擴展名

使用此前端資料:

content/posts/post-1.md
     
---
title: My First Article
url: articles/my-first-article
---
+++
title = 'My First Article'
url = 'articles/my-first-article'
+++
{
   "title": "My First Article",
   "url": "articles/my-first-article"
}

生成的 URL 會是:

https://example.org/articles/my-first-article/

如果包含檔案擴展名:

content/posts/post-1.md
     
---
title: My First Article
url: articles/my-first-article.html
---
+++
title = 'My First Article'
url = 'articles/my-first-article.html'
+++
{
   "title": "My First Article",
   "url": "articles/my-first-article.html"
}

生成的 URL 會是:

https://example.org/articles/my-first-article.html

領先的斜線

對於單語言網站,帶有或不帶有領先斜線的 url 值都會相對於 baseURL。對於多語言網站,帶有領先斜線的 url 值會相對於 baseURL,而不帶領先斜線的 url 值則會相對於 baseURL 加上語言前綴。

網站類型 前端資料 url 生成的 URL
單語言 /about https://example.org/about/
單語言 about https://example.org/about/
多語言 /about https://example.org/about/
多語言 about https://example.org/de/about/

前端資料中的固定連結令牌

New in v0.131.0

您還可以在設定 url 值時使用 令牌。這通常用於 cascade 區塊:

content/foo/bar/_index.md
     
---
cascade:
- url: /:sections[last]/:slug
title: Bar
---
+++
title = 'Bar'
[[cascade]]
  url = '/:sections[last]/:slug'
+++
{
   "cascade": [
      {
         "url": "/:sections[last]/:slug"
      }
   ],
   "title": "Bar"
}

網站配置

固定連結

在網站配置中,為每個頂層區塊定義 URL 模式。每個 URL 模式可以針對特定語言和/或頁面類型進行設定。

前端資料中的 url 值會覆蓋網站配置中 permalinks 區塊中定義的 URL 模式。

使用以下內容結構:

content/
├── posts/
│   ├── bash-in-slow-motion.md
│   └── tls-in-a-nutshell.md
├── tutorials/
│   ├── git-for-beginners.md
│   └── javascript-bundling-with-hugo.md
└── _index.md

將教程渲染到 “training” 目錄,並將文章渲染到 “articles” 目錄,並基於日期建立階層結構:

hugo.
     
permalinks:
  page:
    posts: /articles/:year/:month/:slug/
    tutorials: /training/:slug/
  section:
    posts: /articles/
    tutorials: /training/
[permalinks]
  [permalinks.page]
    posts = '/articles/:year/:month/:slug/'
    tutorials = '/training/:slug/'
  [permalinks.section]
    posts = '/articles/'
    tutorials = '/training/'
{
   "permalinks": {
      "page": {
         "posts": "/articles/:year/:month/:slug/",
         "tutorials": "/training/:slug/"
      },
      "section": {
         "posts": "/articles/",
         "tutorials": "/training/"
      }
   }
}

公開網站的結構將是:

public/
├── articles/
│   ├── 2023/
│   │   ├── 04/
│   │   │   └── bash-in-slow-motion/
│   │   │       └── index.html
│   │   └── 06/
│   │       └── tls-in-a-nutshell/
│   │           └── index.html
│   └── index.html
├── training/
│   ├── git-for-beginners/
│   │   └── index.html
│   ├── javascript-bundling-with-hugo/
│   │   └── index.html
│   └── index.html
└── index.html

若要為根目錄中的常規頁面創建基於日期的階層結構:

hugo.
     
permalinks:
  page:
    /: /:year/:month/:slug/
[permalinks]
  [permalinks.page]
    '/' = '/:year/:month/:slug/'
{
   "permalinks": {
      "page": {
         "/": "/:year/:month/:slug/"
      }
   }
}

對於分類術語也可以使用相同的方法。例如,若要省略 URL 中的分類段落:

hugo.
     
permalinks:
  term:
    tags: /:slug/
[permalinks]
  [permalinks.term]
    tags = '/:slug/'
{
   "permalinks": {
      "term": {
         "tags": "/:slug/"
      }
   }
}

permalinks 配置作為本地化策略的一部分。

使用以下內容結構:

content/
├── en/
│   ├── books/
│   │   ├── les-miserables.md
│   │   └── the-hunchback-of-notre-dame.md
│   └── _index.md
└── es/
    ├── books/
    │   ├── les-miserables.md
    │   └── the-hunchback-of-notre-dame.md
    └── _index.md

以及這樣的網站配置:

hugo.
     
defaultContentLanguage: en
defaultContentLanguageInSubdir: true
languages:
  en:
    contentDir: content/en
    languageCode: en-US
    languageDirection: ltr
    languageName: English
    permalinks:
      page:
        books: /books/:slug/
      section:
        books: /books/
    weight: 1
  es:
    contentDir: content/es
    languageCode: es-ES
    languageDirection: ltr
    languageName: Español
    permalinks:
      page:
        books: /libros/:slug/
      section:
        books: /libros/
    weight: 2
defaultContentLanguage = 'en'
defaultContentLanguageInSubdir = true
[languages]
  [languages.en]
    contentDir = 'content/en'
    languageCode = 'en-US'
    languageDirection = 'ltr'
    languageName = 'English'
    weight = 1
    [languages.en.permalinks]
      [languages.en.permalinks.page]
        books = '/books/:slug/'
      [languages.en.permalinks.section]
        books = '/books/'
  [languages.es]
    contentDir = 'content/es'
    languageCode = 'es-ES'
    languageDirection = 'ltr'
    languageName = 'Español'
    weight = 2
    [languages.es.permalinks]
      [languages.es.permalinks.page]
        books = '/libros/:slug/'
      [languages.es.permalinks.section]
        books = '/libros/'
{
   "defaultContentLanguage": "en",
   "defaultContentLanguageInSubdir": true,
   "languages": {
      "en": {
         "contentDir": "content/en",
         "languageCode": "en-US",
         "languageDirection": "ltr",
         "languageName": "English",
         "permalinks": {
            "page": {
               "books": "/books/:slug/"
            },
            "section": {
               "books": "/books/"
            }
         },
         "weight": 1
      },
      "es": {
         "contentDir": "content/es",
         "languageCode": "es-ES",
         "languageDirection": "ltr",
         "languageName": "Español",
         "permalinks": {
            "page": {
               "books": "/libros/:slug/"
            },
            "section": {
               "books": "/libros/"
            }
         },
         "weight": 2
      }
   }
}

公開網站的結構將是:

public/
├── en/
│   ├── books/
│   │   ├── les-miserables/
│   │   │   └── index.html
│   │   ├── the-hunchback-of-notre-dame/
│   │   │   └── index.html
│   │   └── index.html
│   └── index.html
├── es/
│   ├── libros/
│   │   ├── les-miserables/
│   │   │   └── index.html
│   │   ├── the-hunchback-of-notre-dame/
│   │   │   └── index.html
│   │   └── index.html
│   └── index.html
└── index.html

令牌

在定義 URL 模式時使用這些令牌。您也可以在前端資料中設定 url 值時使用這些令牌。

:year
前端資料 date 欄位中定義的 4 位數年份。
:month
前端資料 date 欄位中定義的 2 位數月份。
:monthname
前端資料 date 欄位中定義的月份名稱。
:day
前端資料 date 欄位中定義的 2 位數日期。
:weekday
前端資料 date 欄位中定義的星期幾(星期日 = 0)。
:weekdayname
前端資料 date 欄位中定義的星期幾名稱。
:yearday
前端資料 date 欄位中定義的 1 至 3 位數年份中的第幾天。
:section
內容的區塊。
:sections
內容的區塊層次結構。您可以使用 切片語法 選擇某些區塊::sections[1:] 包含除第一個之外的所有區塊,:sections[:last] 包含除最後一個之外的所有區塊,:sections[last] 僅包含最後一個區塊,:sections[1:2] 包含第 2 和第 3 個區塊。注意,這種切片訪問不會拋出任何越界錯誤,因此您不必精確。
:title
如前端資料中所定義的標題,否則為自動生成的標題。Hugo 會自動為無檔案支援的區塊、分類和術語頁面生成標題。
:slug
如前端資料中所定義的 slug,否則為前端資料中定義的標題,否則為自動生成的標題。Hugo 會自動為無檔案支援的區塊、分類和術語頁面生成標題。
:filename
內容的檔案名稱,不包括副檔名,適用於 page 頁面類型。
:slugorfilename
如前端資料中所定義的 slug,否則為內容的檔案名稱,不包括副檔名,適用於 page 頁面類型。

對於時間相關的值,您也可以使用 Go 的 time 包 中定義的佈局字串組件。例如:

hugo.
     
permalinks:
  posts: /:06/:1/:2/:title/
[permalinks]
  posts = '/:06/:1/:2/:title/'
{
   "permalinks": {
      "posts": "/:06/:1/:2/:title/"
   }
}

顯示方式

URL 的顯示方式可以是醜陋或漂亮的。

類型 路徑 URL
醜陋 content/about.md https://example.org/about.html
漂亮 content/about.md https://example.org/about/

預設情況下,Hugo 生成漂亮的 URL。如果要生成醜陋的 URL,可以更改網站配置:

hugo.
     
uglyURLs: true
uglyURLs = true
{
   "uglyURLs": true
}

您也可以按區塊啟用醜陋 URL。例如,對於包含書籍和電影區塊的網站:

hugo.
     
uglyURLs:
  books: true
  films: false
[uglyURLs]
  books = true
  films = false
{
   "uglyURLs": {
      "books": true,
      "films": false
   }
}

後處理

Hugo 提供了兩個互斥的配置選項,用來在渲染頁面 之後 修改 URL。

正規化 URL

如果啟用,Hugo 在渲染頁面之後執行查找和替換。它會查找與 actionhrefsrcsrcseturl 屬性相關的站點相對 URL(以斜線開頭的 URL)。然後,它會將 baseURL 加入前綴來創建絕對 URL。

<a href="/about"> → <a href="https://example.org/about/">
<img src="/a.gif"> → <img src="https://example.org/a.gif">

這是一個不完美的、強硬的方式,可能會影響內容以及 HTML 屬性。如上所述,這是遺留的配置選項,可能會在未來版本中移除。

啟用方法:

hugo.
     
canonifyURLs: true
canonifyURLs = true
{
   "canonifyURLs": true
}

相對 URL

如果啟用,Hugo 會在渲染頁面後執行查找和替換。它會查找與 actionhrefsrcsrcseturl 屬性相關的站點相對 URL(以斜線開頭的 URL)。然後,它會將 URL 轉換為相對於當前頁面的 URL。

例如,當渲染 content/posts/post-1 時:

<a href="/about"> → <a href="../../about">
<img src="/a.gif"> → <img src="../../a.gif">

這是一個不完美的、強硬的方式,可能會影響內容以及 HTML 屬性。如上所述,除非您正在建立一個無伺服器網站,否則不要啟用此選項。

啟用方法:

hugo.
     
relativeURLs: true
relativeURLs = true
{
   "relativeURLs": true
}

別名

透過別名創建從舊 URL 到新 URL 的重定向:

  • 以斜線開頭的別名是相對於 baseURL
  • 沒有斜線開頭的別名是相對於當前目錄的

範例

更改現有頁面的檔案名稱,並從舊的 URL 創建別名到新的 URL:

content/posts/new-file-name.md.
     
aliases:
- /posts/previous-file-name
aliases = ['/posts/previous-file-name']
{
   "aliases": [
      "/posts/previous-file-name"
   ]
}

每個這樣的目錄相對別名與上面的站點相對別名等效:

  • previous-file-name
  • ./previous-file-name
  • ../posts/previous-file-name

您可以為當前頁面創建多個別名:

content/posts/new-file-name.md.
     
aliases:
- previous-file-name
- original-file-name
aliases = ['previous-file-name', 'original-file-name']
{
   "aliases": [
      "previous-file-name",
      "original-file-name"
   ]
}

在多語言網站中,使用目錄相對的別名,或者在站點相對的別名中包括語言前綴:

content/posts/new-file-name.de.md.
     
aliases:
- /de/posts/previous-file-name
aliases = ['/de/posts/previous-file-name']
{
   "aliases": [
      "/de/posts/previous-file-name"
   ]
}

別名如何運作

使用上面的第一個範例,Hugo 會生成以下網站結構:

public/
├── posts/
│   ├── new-file-name/
│   │   └── index.html
│   ├── previous-file-name/
│   │   └── index.html
│   └── index.html
└── index.html

從舊 URL 到新 URL 的別名是一個客戶端重定向:

posts/previous-file-name/index.html
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <title>https://example.org/posts/new-file-name/</title>
    <link rel="canonical" href="https://example.org/posts/new-file-name/">
    <meta name="robots" content="noindex">
    <meta charset="utf-8">
    <meta http-equiv="refresh" content="0; url=https://example.org/posts/new-file-name/">
  </head>
</html>

head 區塊中的元素總體上:

  • 告訴搜尋引擎新的 URL 是正規 URL
  • 告訴搜尋引擎不要索引舊的 URL
  • 告訴瀏覽器重定向到新的 URL

Hugo 在渲染頁面之前會先渲染別名文件。使用舊檔案名稱的新頁面會覆蓋別名,正如預期的那樣。

自訂

若要覆蓋 Hugo 內建的 alias 模板,請將 源代碼 複製到 layouts 目錄中的同名文件中。模板會接收以下上下文:

Permalink
被別名指向的頁面的鏈接。
Page
被別名指向頁面的頁面資料。