Skip to main content

Solving Circular References in Hugo

Circular references come up more or less inevitably in Hugo. Far too many people waste time searching for an answer, or waste compute asking an AI to solve it. This article lays out clearly how to actually deal with circular references.

Defining the Problem

When two pages each need information from the other, and that information happens to trigger content rendering, you get a circular reference: page A needs page B's rendered output before it can render itself, while page B needs page A's rendered output before it can render itself.

The methods that trigger content rendering are:

  • Content
  • ContentWithoutSummary
  • FuzzyWordCount
  • Len
  • Plain
  • PlainWords
  • ReadingTime
  • Summary
  • Truncated
  • WordCount

Only these content-rendering methods cause circular references between pages; every other method is safe and won't trigger one.

Solution

There isn't one. The only real option is for the user to avoid the pattern themselves. I've seen the same conclusion repeated across multiple official statements on the matter.

The Scratch/Store Approach

What if you used .Page.Scratch/.Page.Store to record page references, and automatically dropped the "content rendering request" from whichever page already has one recorded? An implementation along these lines can be seen in #3001.

But this creates more problems than it solves. Hugo renders all pages in parallel, which means there is no way to control which page's summary ends up getting cancelled. Your local build and your CI build may produce different results, and even a local live-reload can flip the outcome — the output ends up unstable and non-reproducible.


中文版本

英文版本結束,開始中文版本

Hugo 中或多或少都會遇到循環引用的問題,而且太多人都浪費時間搜尋、浪費電要求 AI 解決,於是本文清楚說明該如何解決循環引用的問題。

定義問題

在兩個頁面互相要求對方的資訊,只要這些資訊會觸發內容渲染,那就會引發循環引用:因為 A 要求 B 有渲染結果才能渲染自己,而 B 又要求 A 有渲染結果才能渲染自己。

會觸發內容渲染的方法如下:

  • Content
  • ContentWithoutSummary
  • FuzzyWordCount
  • Len
  • Plain
  • PlainWords
  • ReadingTime
  • Summary
  • Truncated
  • WordCount

只有觸發內容渲染才會造成頁面之間的循環引用,其他 method 不會引發循環引用。

解決方案

無解,只能用戶自行避免。我在多個官方說法都看到同樣的結論。

Scratch/Store 方案

使用 .Page.Scratch/.Page.Store 方式記錄頁面引用,有的話就自動取消別的頁面的「內容渲染要求」呢?做起來大概會像 #3001 這樣。

然而這引發更多問題,Hugo 所有頁面是平行渲染的,這代表哪個頁面的 summary 被取消是完全無法控制的,你在本地/CI 結果可能會不一樣,甚至本地 live reload 之後結果也會改變,造成輸出不穩定且不可重現。