Skip to main content

Hugo 中的快取

本文專門介紹 Hugo 的所有快取,因為一般用戶不太了解這些。

快取是什麼

把計算過的東西存下來,下次用就不用重算直接讀取之前的結果,是一個簡單且強大的軟體加速方法,英文是 cache,中文是快取。

Hugo 的快取

  1. Configure file caches 所有的快取選項設定,這裡只列最重要的幾個
    1. assets 如 CSS, SASS, JS 資源
    2. getresource 源碼中使用到 GetRemote 的內容
    3. images 影像處理快取
    4. modules 使用 Hugo module 安裝的 modules
  2. --ignoreCache: 構建網站時無視第一點講的快取內容,但是也不是全部無視,比如 module 還是不會重複下載
  3. --noHTTPCache: 設定 live reload 的 server head 加上不要快取,也就是說本地開發的瀏覽器獲取所有資源都強制要求從磁碟重新讀取,不依賴瀏覽器網路協議層面的快取。不過 favicon 使用自己的另一套快取系統,與 HTTP 快取無關
  4. --disableFastRender: 這不是快取,是取消偷懶模式,Hugo live reload 預設只會部分更新,此 flag 要求 Hugo 全站更新重建
  5. --templateMetrics --templateMetricsHints: 用於效能分析,裡面有一個項目是分析該模板是否可使用 partialCached 快取
  6. partialCached: 快取 partial 模板,context 後面可給多個參數用作快取鍵,每個 site 的快取不共用(site: 每一個語言、role、version)
  7. Configure output formats: 可設定自訂輸出的權重,這樣就會在所有東西渲染前先執行,你就可以把在這個輸出裡面寫自己的快取,比如使用 hugo.Store 或是真的輸出一個 JSON 作為快取

作為一般用戶最應該設定的是 --noHTTPCache 這樣能確保不是瀏覽器作怪,--disableFastRender 用於處理 live reload 時某些東西沒有更新,比如更新 A 會影響 B,B 影響 C,但是 C 沒有隨之更新,這就可以使用 --disableFastRender 解決。

部署快取

部署時需要重新構建整個網站,而部署快取主要是加速圖像處理,這是所有快取裡面最耗費 CPU 效能(最花時間)的東西,請參見官方在論壇的範例完成1

大多數服務商的快取時間只維持一週,如果你一週之內都沒有更新網站快取即失效。

如果你的網站文章很多瓶頸不在圖片可使用 rsync 部署,rsync 的增量更新功能和這種需求是天作之合。

快取資料夾

找到資料夾的方式是在專案目錄中使用 hugo config | grep cachedir,以 macOS 為例會在 ~/Library/Caches/hugo_cache

.Content 快取

partial 中呼叫 .Content 會被快取,同一個 Page 在不同模板呼叫 10 次 .Content 都沒差,都是被快取的,文檔又沒講,到底為什麼就是死不寫?

pageContentOutput.Content() 實際呼叫的是 getOrCreateScopehugolib/page__content.go#L143),內部用 hmaps.Cache 做 get-or-create,key 存在就直接回傳既有結果,不會重新渲染。快取物件 cachedContent 也寫「Content cached for a page instance」,且由每個 page 各自的 pageMeta 建立,不是全站共用一份。key 組成是 scope + 輸出格式名稱,所以同一個 page 若有多種 output format(html/amp/json),會各自獨立快取,彼此不共用。

頁面快取

這其實不是快取,但是他實際作用就和快取一樣。

Hugo 執行時,只要你有多少個 markdown 頁面,他就把多少頁面全部放到記憶體(radix tree)裡面,所有頁面都同時存活,不會有某個頁面提早渲染完成就回收記憶體這件事,會全部一起活到最後一刻。

這也代表 .Store 方法要避免存大型物件,單一一個頁面儲存還好,問題是多個頁面都會存,記憶體用量就倍數增長。

Footnotes

  1. 會需要特別設定這個是因為服務商對 Hugo 沒有自動偵測快取,這些設定主要是把 Hugo 的設定偽裝成其他 JS 工具鏈,這就是為什麼 Hugo 文檔裡面會說到 First, your project must have both a package.json and package-lock.json file in the project root.,這其實是把專案偽裝成 11ty。