<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hugo on kenji.blog</title><link>http://kenji.blog/zh-tw/categories/hugo/</link><description>Recent content in Hugo on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 03:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/zh-tw/categories/hugo/index.xml" rel="self" type="application/rss+xml"/><item><title>Hugo的主題自訂：導入Tailwind CSS的方法</title><link>http://kenji.blog/zh-tw/p/hugo-tailwind-css-customization-guide/</link><pubDate>Sun, 13 Sep 2026 03:00:00 +0900</pubDate><guid>http://kenji.blog/zh-tw/p/hugo-tailwind-css-customization-guide/</guid><description>&lt;img src="http://kenji.blog/p/hugo-tailwind-css-customization-guide/img/eyecatch.jpg" alt="Featured image of post Hugo的主題自訂：導入Tailwind CSS的方法" />&lt;h1 id="前言靜態網站生成器hugo與tailwind-css的強大協同效應">前言：靜態網站生成器Hugo與Tailwind CSS的強大協同效應
&lt;/h1>&lt;p>在現代的Web前端開發中，兼顧效能與開發體驗（DX：Developer Experience）是所有專案中最重要的課題之一。將在靜態網站生成器（SSG）中擁有世界最快建置速度的&lt;strong>Hugo&lt;/strong>，與引入了實用優先（Utility-First）這一革新典範的&lt;strong>Tailwind CSS&lt;/strong>相結合，可以說是由此課題得出的一個終極解答。&lt;/p>
&lt;p>Hugo是使用Go語言編寫的，即使是擁有數千個頁面的網站，也具備在短短幾秒，甚至毫秒級別內完成建置的驚人效能。另一方面，Tailwind CSS透過在HTML中直接寫入預先定義的無數個實用類別（例如：&lt;code>flex&lt;/code>、&lt;code>text-center&lt;/code>、&lt;code>mt-4&lt;/code>等），消除了在CSS檔案與HTML檔案之間來回切換的上下文切換（Context Switch），從而加速了設計的迭代。&lt;/p>
&lt;p>本文將徹底且詳細地解說在Hugo主題中導入Tailwind CSS，並進一步使用PostCSS建立進階資源管道（Hugo Pipes）的步驟，內容涵蓋從架構的基礎到數學的效能最佳化觀點。&lt;/p>
&lt;hr>
&lt;h2 id="1-實用優先css與元件導向的演變">1. 實用優先CSS與元件導向的演變
&lt;/h2>&lt;p>在進入Tailwind CSS的導入步驟之前，深入理解為什麼我們應該使用Tailwind CSS，以及其背景中的CSS設計思想歷史與演變，是非常有幫助的。&lt;/p>
&lt;h3 id="傳統css設計bem與oocss的極限">傳統CSS設計（BEM與OOCSS）的極限
&lt;/h3>&lt;p>在過去的Web開發中，賦予語意化的類別名稱被認為是最佳實踐。例如，當建立卡片元件時，會像以下這樣將HTML與CSS分離。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__image&amp;#34;&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;image.jpg&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;thumbnail&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__content&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h2&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__title&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>標題&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__description&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>說明文字會放在這裡。&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="p">.&lt;/span>&lt;span class="nc">card&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">border-radius&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="kt">px&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">box-shadow&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="nb">rgba&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">background-color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">overflow&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">hidden&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">.&lt;/span>&lt;span class="nc">card__title&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">font-size&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">1.5&lt;/span>&lt;span class="kt">rem&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">font-weight&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">bold&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#333333&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* 之後會接著詳細的樣式 */&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>像這樣基於BEM（Block Element Modifier）的設計，在專案規模較小時還能運作良好，但往往會引發以下問題：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>命名枯竭與疲勞&lt;/strong>：每當製作類似的元件時，就必須思考新的類別名稱（例：&lt;code>card-news&lt;/code>、&lt;code>card-featured&lt;/code>等）。&lt;/li>
&lt;li>&lt;strong>CSS的肥大化&lt;/strong>：每當新增新功能時，CSS的行數就會持續增加，而一旦寫好的CSS因為害怕「不知道在哪裡被使用」，所以很少會被刪除，導致無效程式碼（Dead Code）不斷累積。&lt;/li>
&lt;li>&lt;strong>上下文切換&lt;/strong>：因為將HTML的結構與CSS的樣式分開在不同的檔案中管理，在編輯器上來回切換分頁的次數會呈指數級增加。&lt;/li>
&lt;/ol>
&lt;h3 id="tailwind-css帶來的典範轉移">Tailwind CSS帶來的典範轉移
&lt;/h3>&lt;p>Tailwind CSS透過「實用類別的組合」這種方法來解決這些問題。如果使用Tailwind CSS，上述的卡片元件將會變成如下所示：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;rounded-lg shadow-md bg-white overflow-hidden&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;w-full h-48 object-cover&amp;#34;&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;image.jpg&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;thumbnail&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;p-6&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h2&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-2xl font-bold text-gray-800&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>標題&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-2 text-gray-600&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>說明文字會放在這裡。&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>由於類別名稱本身就代表了樣式的具體數值（例如 &lt;code>p-6&lt;/code> 是 &lt;code>padding: 1.5rem;&lt;/code>），因此只需看HTML就能預測最終的渲染結果。此外，透過Tailwind的JIT（Just-In-Time）編譯器，只有實際被使用的類別才會被提取到正式環境用的CSS檔案中，所以CSS的檔案大小會被縮減到極致。&lt;/p>
&lt;hr>
&lt;h2 id="2-hugo-pipes與postcss的架構">2. Hugo Pipes與PostCSS的架構
&lt;/h2>&lt;p>為了將Tailwind CSS整合到Hugo中，必須理解被稱為&lt;strong>Hugo Pipes&lt;/strong>的資源處理管道。Hugo Pipes是一個強大的功能，它能讓與資源相關的任何處理（如Sass/SCSS的編譯、JavaScript的打包與壓縮（Minify），以及本次將使用的&lt;strong>PostCSS&lt;/strong>的執行等）都在Hugo內部完成。&lt;/p>
&lt;p>PostCSS是一個使用JavaScript外掛來轉換CSS的工具。事實上，Tailwind CSS本身也是作為PostCSS的外掛在運作。&lt;/p>
&lt;h3 id="透過postcss進行的ast抽象語法樹轉換機制">透過PostCSS進行的AST（抽象語法樹）轉換機制
&lt;/h3>&lt;p>理解PostCSS是如何處理CSS的，對於進行疑難排解時會有很大的幫助。以下的Mermaid圖表顯示了PostCSS讀取CSS檔案、透過外掛進行轉換，直到輸出最終CSS的管道處理過程。&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;原始 CSS (styles.css)&amp;#34;] --&amp;gt;|解析器 (Parser)| B[&amp;#34;AST (抽象語法樹)&amp;#34;]
B --&amp;gt; C[&amp;#34;外掛 1: Tailwind CSS&amp;#34;]
C --&amp;gt; D[&amp;#34;外掛 2: Autoprefixer&amp;#34;]
D --&amp;gt; E[&amp;#34;外掛 N: cssnano&amp;#34;]
E --&amp;gt;|字串化器 (Stringifier)| F[&amp;#34;編譯與最佳化後的 CSS&amp;#34;]
&lt;/pre>
&lt;ol>
&lt;li>&lt;strong>Parser（解析器）&lt;/strong>：解析輸入的原始CSS字串，並將其轉換為可供程式操作的資料結構——AST（抽象語法樹）。&lt;/li>
&lt;li>&lt;strong>Plugins（外掛群）&lt;/strong>：
&lt;ul>
&lt;li>&lt;strong>Tailwind CSS&lt;/strong>：掃描樣板檔案（HTML或Markdown），並將使用到的實用類別作為節點新增到AST上。此外，它也會展開 &lt;code>@tailwind&lt;/code> 指令。&lt;/li>
&lt;li>&lt;strong>Autoprefixer&lt;/strong>：參考 &lt;code>Can I Use&lt;/code> 的資料庫，並在必要時將供應商前綴（Vendor Prefix，如 &lt;code>-webkit-&lt;/code>、&lt;code>-moz-&lt;/code> 等）新增到AST的屬性中。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Stringifier（字串化器）&lt;/strong>：將轉換完成的AST重新轉換為瀏覽器可解析的CSS字串並輸出。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-環境建置與先決條件">3. 環境建置與先決條件
&lt;/h2>&lt;p>那麼，我們就進入實際的導入步驟吧。首先要確認是否已安裝必要的軟體。&lt;/p>
&lt;h3 id="必備條件">必備條件
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Hugo Extended Version&lt;/strong>：
必須是包含Sass/SCSS處理功能與原生PostCSS整合功能的&lt;strong>Extended版&lt;/strong>，而不是普通的Hugo版本。請在終端機中執行以下指令，並確認版本資訊中是否包含 &lt;code>extended&lt;/code> 字串。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hugo version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 預期的輸出範例:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># hugo v0.121.2-4146... windows/amd64 BuildDate=... VendorInfo=gohugoio +extended&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Node.js與npm&lt;/strong>：
Tailwind CSS與PostCSS等依賴套件是在Node.js上運作的。請確認是否已安裝Node.js（建議使用LTS版）。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">node -v
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm -v
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;h3 id="安裝npm套件">安裝npm套件
&lt;/h3>&lt;p>在專案的根目錄（即Hugo設定檔 &lt;code>hugo.toml&lt;/code> 所在的層級）初始化npm，並安裝必要的套件。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 產生 package.json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm init -y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 安裝 Tailwind CSS、PostCSS、Autoprefixer 作為開發依賴套件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm install -D tailwindcss postcss postcss-cli autoprefixer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;blockquote>
&lt;p>[!IMPORTANT]
如果沒有安裝 &lt;code>postcss-cli&lt;/code>，在從Hugo內部呼叫PostCSS時可能會發生錯誤。因為Hugo Pipes在內部會使用 &lt;code>postcss-cli&lt;/code>，所以請務必將其安裝。&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="4-建立設定檔postcss--tailwind-css">4. 建立設定檔（PostCSS &amp;amp; Tailwind CSS）
&lt;/h2>&lt;p>套件安裝完成後，接著要建立兩個控制專案行為的重要設定檔。請將它們放置在專案的根目錄。&lt;/p>
&lt;h3 id="建立-tailwindconfigjs">建立 tailwind.config.js
&lt;/h3>&lt;p>在終端機中執行以下指令，將會產生預設的設定檔。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npx tailwindcss init
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>使用編輯器打開生成的 &lt;code>tailwind.config.js&lt;/code>，並設定 &lt;code>content&lt;/code> 屬性。這部分非常重要。Tailwind會解析這裡指定路徑的檔案，並提取被使用的類別。請配合Hugo的專案結構，準確地指定版面配置檔（Layout）和內容檔（Content）。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/** @type {import(&amp;#39;tailwindcss&amp;#39;).Config} */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 配合Hugo的目錄結構指定掃描對象
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./content/**/*.md&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./content/**/*.html&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./layouts/**/*.html&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./assets/**/*.js&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 如果有使用主題，也必須包含主題的目錄
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// &amp;#34;./themes/my-theme/layouts/**/*.html&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">theme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">extend&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 在此擴充自訂顏色或字型
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">colors&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;brand-primary&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;#3490dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;brand-secondary&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;#ffed4a&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">fontFamily&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;sans&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Helvetica Neue&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Arial&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Hiragino Kaku Gothic ProN&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Meiryo&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;sans-serif&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 視需要加入官方外掛（例如：Typography 外掛）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// require(&amp;#39;@tailwindcss/typography&amp;#39;),
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="建立-postcssconfigjs">建立 postcss.config.js
&lt;/h3>&lt;p>接著，在專案根目錄建立 &lt;code>postcss.config.js&lt;/code>，用來定義PostCSS要以什麼順序執行哪些外掛。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tailwindcss&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">autoprefixer&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過這個設定，當Hugo呼叫PostCSS時，會先進行Tailwind CSS的處理，然後再由Autoprefixer賦予供應商前綴。&lt;/p>
&lt;hr>
&lt;h2 id="5-在hugo中建立css資源管道">5. 在Hugo中建立CSS資源管道
&lt;/h2>&lt;p>設定完成後，終於要在Hugo的主題端整合Tailwind CSS了。&lt;/p>
&lt;h3 id="5-1-建立作為進入點的css檔案">5-1. 建立作為進入點的CSS檔案
&lt;/h3>&lt;p>在 &lt;code>assets/css/&lt;/code> 目錄（如果不存在請建立它）中，建立作為進入點的CSS檔案。這裡我們將其命名為 &lt;code>main.css&lt;/code>。&lt;/p>
&lt;p>&lt;strong>檔案路徑：&lt;code>assets/css/main.css&lt;/code>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* 載入Tailwind的基礎樣式（Reset CSS等） */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">base&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* 載入元件類別 */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">components&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* 載入實用類別 */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">utilities&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* 如果需要自有的客製化CSS，可以寫在這裡，
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> 但建議盡可能透過 tailwind.config.js 的 extend 來處理 */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">layer&lt;/span> &lt;span class="nt">components&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="nc">btn-primary&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">@apply&lt;/span> &lt;span class="err">bg-blue-500&lt;/span> &lt;span class="n">hover&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">bg-blue-700&lt;/span> &lt;span class="kc">text&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">white&lt;/span> &lt;span class="k">font&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">bold&lt;/span> &lt;span class="n">py-2&lt;/span> &lt;span class="n">px-4&lt;/span> &lt;span class="n">rounded&lt;/span> &lt;span class="k">transition&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">colors&lt;/span> &lt;span class="n">duration-300&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="5-2-編輯版面配置檔headhtml">5-2. 編輯版面配置檔（head.html）
&lt;/h3>&lt;p>接著，要撰寫從Hugo的樣板載入上述CSS檔案，並透過PostCSS處理的管道。一般來說，會編輯定義 &lt;code>&amp;lt;head&amp;gt;&lt;/code> 標籤內的局部樣板（Partial Template）（例如：&lt;code>layouts/partials/head.html&lt;/code>）。&lt;/p>
&lt;p>&lt;strong>檔案路徑：&lt;code>layouts/partials/head.html&lt;/code>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go-html-template" data-lang="go-html-template">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">head&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">charset&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;viewport&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;width=device-width, initial-scale=1&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Title&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span> | &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Site.Title&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 取得 assets/css/main.css --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">:=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">resources&lt;/span>&lt;span class="na">.Get&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;css/main.css&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 定義PostCSS的選項 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$options&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">:=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">dict&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;inlineImports&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">resources&lt;/span>&lt;span class="na">.PostCSS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$options&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 針對正式環境（Production）的資源最佳化管道 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">hugo&lt;/span>&lt;span class="na">.IsProduction&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 1. 壓縮（Minify） --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">minify&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 2. Fingerprint（為了快取破壞（Cache Busting）的雜湊賦予） --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">fingerprint&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;sha512&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 3. 輸出包含SRI（Subresource Integrity）的標籤 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;stylesheet&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.RelPermalink&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="na">integrity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.Data.Integrity&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="na">crossorigin&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;anonymous&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 在開發環境（Development）不進行壓縮，直接輸出（優先考量建置速度） --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;stylesheet&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.RelPermalink&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">end&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">head&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="管道解說與mermaid圖解">管道解說與Mermaid圖解
&lt;/h4>&lt;p>上述的Go樣板程式碼是如何處理CSS檔案的，這裡將一連串的管道處理進行圖解。&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;assets/css/main.css&amp;#34;] --&amp;gt;|resources.Get| B[&amp;#34;Hugo 記憶體空間&amp;#34;]
B --&amp;gt;|resources.PostCSS| C[&amp;#34;PostCSS + Tailwind JIT 處理&amp;#34;]
C --&amp;gt; D{&amp;#34;hugo.IsProduction ?&amp;#34;}
D -- Yes (正式環境) --&amp;gt; E[&amp;#34;minify (刪除空白與換行)&amp;#34;]
E --&amp;gt; F[&amp;#34;fingerprint (雜湊計算)&amp;#34;]
F --&amp;gt; G[&amp;#34;public/css/main.[hash].css (附帶 SRI)&amp;#34;]
D -- No (開發環境) --&amp;gt; H[&amp;#34;public/css/main.css&amp;#34;]
&lt;/pre>
&lt;ol>
&lt;li>&lt;strong>&lt;code>resources.Get&lt;/code>&lt;/strong>：尋找 &lt;code>assets&lt;/code> 目錄內指定的檔案，並將其作為資源物件載入到記憶體中。&lt;/li>
&lt;li>&lt;strong>&lt;code>resources.PostCSS&lt;/code>&lt;/strong>：參考專案根目錄的 &lt;code>postcss.config.js&lt;/code>，對CSS原始碼套用Tailwind CSS與Autoprefixer的處理。在開發環境（&lt;code>hugo server&lt;/code>）中，JIT模式會啟動，在修改檔案時，能高速生成僅需的類別。&lt;/li>
&lt;li>&lt;strong>&lt;code>minify&lt;/code>&lt;/strong>：在正式環境建置時（如 &lt;code>hugo --environment production&lt;/code>），刪除不需要的空白與註解，將檔案大小最小化。&lt;/li>
&lt;li>&lt;strong>&lt;code>fingerprint&lt;/code>&lt;/strong>：根據檔案的內容計算SHA雜湊值，並附加到檔案名稱上（例：&lt;code>main.ab12cd...css&lt;/code>）。藉此，在利用瀏覽器強大快取的同時，也能實現在CSS更新時確保讀取新檔案的「快取破壞（Cache Busting）」。&lt;/li>
&lt;li>&lt;strong>&lt;code>integrity&lt;/code>&lt;/strong>：使用Fingerprint計算出的雜湊值，輸出SRI屬性，以防止來自CDN等的竄改。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="6-css最佳化中的數學效能分析">6. CSS最佳化中的數學效能分析
&lt;/h2>&lt;p>導入Tailwind CSS最大的好處之一，就是能將傳輸的CSS檔案大小極小化。這會對網頁效能（特別是首次內容繪製：FCP）帶來什麼樣的影響呢？讓我們使用數學模型來進行量化分析。&lt;/p>
&lt;h3 id="css檔案大小的縮減模型">CSS檔案大小的縮減模型
&lt;/h3>&lt;p>在傳統的CSS框架（如Bootstrap等）中，因為包含未使用的樣式也會全部載入，檔案大小 $S_{original}$ 通常會很大（約150KB～200KB）。
若將Tailwind CSS的JIT編譯器套用清除（Purge）不需要類別後的檔案大小設為 $S_{purged}$，使用縮減率 $R_{purge}$ 則可以表示如下：&lt;/p>
$$
S_{purged} = S_{original} \times (1 - R_{purge})
$$&lt;p>在典型的專案中，$R_{purge}$ 可接近 $0.9$（減少90%），而 $S_{purged}$ 僅有約10KB～20KB左右。&lt;/p>
&lt;p>此外，傳輸時伺服器端還會透過Brotli或Gzip進行壓縮。若將壓縮率設為 $R_{compress}$（通常在0.7～0.8左右），則網路上傳輸的最終負載大小 $S_{final}$ 透過以下公式計算：&lt;/p>
$$
S_{final} = S_{purged} \times (1 - R_{compress})
$$&lt;h3 id="關鍵渲染路徑與網路延遲">關鍵渲染路徑與網路延遲
&lt;/h3>&lt;p>瀏覽器直到在畫面上繪製出最初內容為止的時間（FCP），可以由HTML的下載時間、CSS的下載時間，以及渲染時間的總和來近似計算。&lt;/p>
$$
T_{FCP} \approx RTT + \frac{S_{HTML}}{BW} + RTT + \frac{S_{final}}{BW} + T_{render}
$$&lt;p>這裡的：&lt;/p>
&lt;ul>
&lt;li>$RTT$：Round Trip Time（與伺服器來回通訊的延遲時間）&lt;/li>
&lt;li>$BW$：網路頻寬（Bandwidth）&lt;/li>
&lt;/ul>
&lt;p>在如行動網路等 $BW$ 較窄且 $RTT$ 較大（延遲較高）的環境中，Tailwind CSS能將 $S_{final}$ 削減到數KB單位的方法，可以使 $\frac{S_{final}}{BW}$ 這一項極度逼近零，這正是能夠在Google PageSpeed Insights等工具中獲得驚人高分的動力來源。&lt;/p>
&lt;hr>
&lt;h2 id="7-啟動開發伺服器與確認熱重載hot-reload">7. 啟動開發伺服器與確認熱重載（Hot Reload）
&lt;/h2>&lt;p>當所有設定都完成後，啟動Hugo的開發伺服器，並確認Tailwind CSS是否能正常運作。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>使用瀏覽器造訪 &lt;code>http://localhost:1313/&lt;/code>，並確認網站是否正常顯示。
請打開Markdown的內容檔或是Hugo的樣板（&lt;code>layouts/&lt;/code> 以下的檔案），試著加入類別看看。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- 測試用的Tailwind類別套用範例 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;bg-gradient-to-r from-blue-500 to-purple-600 text-white p-8 rounded-xl shadow-2xl text-center transform transition duration-500 hover:scale-105&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h1&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-4xl font-extrabold tracking-tight&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Tailwind CSS + Hugo is Awesome!&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h1&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-4 text-lg font-medium&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>請確認熱重載（Hot Reload）是否瞬間反映。&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在儲存檔案的瞬間，Hugo強大的檔案監視器與Tailwind的JIT編譯器會互相配合，在毫秒級別內重新建置CSS，你應該能體驗到瀏覽器自動重新載入（熱重載）的快感。&lt;/p>
&lt;h3 id="疑難排解如果樣式沒有反映的情況">疑難排解：如果樣式沒有反映的情況
&lt;/h3>&lt;p>如果變更沒有反映，請檢查以下幾點：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>tailwind.config.js&lt;/code> 的 &lt;code>content&lt;/code> 路徑設定&lt;/strong>
如果掃描對象的檔案路徑有誤，Tailwind就無法偵測到該檔案內使用的類別，也不會輸出到CSS中。特別是當有使用主題時，請確認是否遺漏了主題目錄的路徑。&lt;/li>
&lt;li>&lt;strong>PostCSS錯誤&lt;/strong>
如果在終端機的Hugo伺服器日誌中出現如 &lt;code>Error: failed to transform resource: PostCSS not found&lt;/code> 這樣的錯誤，可能是 &lt;code>npm install&lt;/code> 沒有正確執行，或者是缺少了 &lt;code>postcss-cli&lt;/code>。&lt;/li>
&lt;li>&lt;strong>清除Hugo的快取&lt;/strong>
有時候會因為Hugo快取的原因而殘留舊的CSS。請停止伺服器，然後使用 &lt;code>hugo server --ignoreCache&lt;/code> 來啟動，或是試著刪除OS的暫存目錄（例如 &lt;code>/tmp/hugo_cache/&lt;/code>）。&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-針對正式環境的建置與進一步的進階設定">8. 針對正式環境的建置與進一步的進階設定
&lt;/h2>&lt;p>將網站部署到正式伺服器（如Netlify、Vercel、GitHub Pages、Cloudflare Pages等）時，必須設定環境變數並執行正式環境用的最佳化管道。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 正式環境建置指令的範例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NODE_ENV&lt;/span>&lt;span class="o">=&lt;/span>production hugo --minify --environment production
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過加上 &lt;code>--environment production&lt;/code> 標籤，會執行 &lt;code>head.html&lt;/code> 內的 &lt;code>{{ if hugo.IsProduction }}&lt;/code> 區塊，進行CSS的壓縮（Minify）並賦予Fingerprint。&lt;/p>
&lt;h3 id="使用typography外掛進行markdown的樣式設定">使用Typography外掛進行Markdown的樣式設定
&lt;/h3>&lt;p>在像Hugo這類的部落格或文件網站中，無法直接對由Markdown生成的純HTML元素（如 &lt;code>&amp;lt;h1&amp;gt;&lt;/code>、&lt;code>&amp;lt;p&amp;gt;&lt;/code>、&lt;code>&amp;lt;ul&amp;gt;&lt;/code> 等）加上類別。在這種情況下，非常有用的就是Tailwind官方的 &lt;strong>Typography 外掛&lt;/strong>。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>安裝外掛&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npm install -D @tailwindcss/typography
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>新增到 &lt;code>tailwind.config.js&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;@tailwindcss/typography&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>在樣板中套用
只要在輸出文章本文的容器元素上加上 &lt;code>prose&lt;/code> 類別（以及個人喜好的顏色或尺寸變體），就能套用美麗的預設樣式。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go-html-template" data-lang="go-html-template">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">article&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;prose prose-lg prose-blue mx-auto mt-10&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Content&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">article&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>這樣一來，就完全不需要手寫複雜的CSS選擇器（如 &lt;code>.article-content h2 { ... }&lt;/code>），能完全保持元件的模組性。&lt;/p>
&lt;hr>
&lt;h2 id="9-總結完成具高維護性的前端生態系統">9. 總結：完成具高維護性的前端生態系統
&lt;/h2>&lt;p>辛苦了。到這裡，具備Hugo超高速靜態網站生成引擎、Tailwind CSS現代化樣式設定功能，以及PostCSS擴充性的完美Web開發資源管道就完成了。&lt;/p>
&lt;p>這個架構的優點在於，&lt;strong>「設定只需在最初進行一次即可」&lt;/strong>。只要建立好管道，開發者就不需要打開CSS檔案，只需在HTML或Markdown樣板中寫入直觀的實用類別，就能以驚人的速度構建出複雜的UI。&lt;/p>
&lt;p>此外，由於輸出的CSS大小始終會被最小化，這將直接提升Core Web Vitals的分數，從SEO的角度來看也非常有利。&lt;/p>
&lt;p>Hugo與Tailwind CSS的組合，從個人技術部落格到大型企業網站，在所有專案中都將會是「最佳選擇」之一。請務必活用這個強大的工具鏈，享受舒適的Web開發生活！&lt;/p></description></item><item><title>Hugo 靜態網站產生器入門（從 WordPress 移轉的步驟）</title><link>http://kenji.blog/zh-tw/p/hugo-static-site-generator-wordpress-migration/</link><pubDate>Sun, 13 Sep 2026 02:00:00 +0900</pubDate><guid>http://kenji.blog/zh-tw/p/hugo-static-site-generator-wordpress-migration/</guid><description>&lt;img src="http://kenji.blog/p/hugo-static-site-generator-wordpress-migration/img/eyecatch.jpg" alt="Featured image of post Hugo 靜態網站產生器入門（從 WordPress 移轉的步驟）" />&lt;p>在現代的網頁開發與部落格營運中，網站的載入速度、安全性以及可維護性已成為極其重要的要素。長期以來在部落格與企業網站基底中佔據壓倒性市佔率的「WordPress」，憑藉其靈活的外掛生態系統與直覺的管理介面，受到廣大使用者的青睞。然而，由於其伴隨著與資料庫的通訊以及在伺服器端動態產生頁面（透過 PHP 處理），因此也存在著對流量突增的脆弱性以及顯示延遲（Latency）等課題。&lt;/p>
&lt;p>因此，近年來「靜態網站產生器（SSG: Static Site Generator）」正迅速普及。本篇文章將深入探討在眾多 SSG 中，基於 Go 語言開發且以壓倒性建置速度聞名的「&lt;strong>Hugo&lt;/strong>」。我們將從與 WordPress 等動態 CMS（Content Management System）的技術架構比較開始，徹底解說具體的移轉步驟、使用數理模型進行的效能評估，以及 Hugo 特有的目錄結構與模板的尋找順序（Lookup Order）。&lt;/p>
&lt;hr>
&lt;h2 id="1-動態-cmswordpress與靜態網站產生器hugo的技術差異">1. 動態 CMS（WordPress）與靜態網站產生器（Hugo）的技術差異
&lt;/h2>&lt;p>在傳遞網站內容的機制上，WordPress 與 Hugo 採取了根本上不同的方法。&lt;/p>
&lt;h3 id="11-wordpress-的架構動態產生">1.1 WordPress 的架構（動態產生）
&lt;/h3>&lt;p>WordPress 是動態 CMS 的代表，會在每次收到請求時於伺服器端組裝頁面。當使用者（瀏覽器）存取頁面時，網頁伺服器（Apache、Nginx 等）會執行 PHP 腳本，並向 MySQL（或 MariaDB）等關聯式資料庫發出查詢。接著將從資料庫取得的內容（文章資料、分類、標籤、網站設定等）與模板檔案結合，產生最終的 HTML 並回傳給客戶端。&lt;/p>
&lt;p>這個機制的優點在於可以針對每位訪客即時產生不同的內容（例如：電商網站的購物車、登入使用者專屬頁面）。但是，除非妥善設計快取機制（如反向代理或外掛等），否則會劇烈消耗伺服器資源。&lt;/p>
&lt;h3 id="12-hugo-的架構建置時預先產生">1.2 Hugo 的架構（建置時預先產生）
&lt;/h3>&lt;p>另一方面，Hugo 誠如「靜態網站產生器」其名，內容的產生並非在「請求時」，而是在「建置時」進行。內容不是儲存在資料庫中，而是作為由 Git 等版本控制系統管理的本機「Markdown 檔案」來保存。
當開發者執行指令（&lt;code>hugo&lt;/code>）時，Hugo 會讀取 Markdown 檔案，將資料注入指定的 HTML 模板（佈局檔案）中，產生一組完整純粹的 HTML/CSS/JS 檔案集合。&lt;/p>
&lt;p>產生出的檔案群（靜態資源）只需部署到 Amazon S3、Cloudflare Pages、Netlify、Vercel 或是簡單的 Nginx 伺服器等「靜態託管環境」即可進行發布。由於不需要資料庫與伺服器端語言（如 PHP），安全性風險（如 SQL 注入或 PHP 漏洞等）會急遽降低，且透過 CDN（Content Delivery Network）邊緣節點的快取，發布速度能達到極限的提升。&lt;/p>
&lt;p>以下透過 Mermaid 圖表展示兩者架構的差異：&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph WordPress[&amp;#34;動態 CMS (WordPress)&amp;#34;]
direction TB
Req1[&amp;#34;使用者的請求&amp;#34;] --&amp;gt; WebServer1[&amp;#34;Web 伺服器 (Nginx/Apache)&amp;#34;]
WebServer1 --&amp;gt; PHP[&amp;#34;PHP 處理環境&amp;#34;]
PHP &amp;lt;--&amp;gt; DB[&amp;#34;資料庫 (MySQL)&amp;#34;]
PHP --&amp;gt; HTML1[&amp;#34;產生 HTML&amp;#34;]
HTML1 --&amp;gt; Res1[&amp;#34;回傳回應&amp;#34;]
end
subgraph Hugo[&amp;#34;靜態網站產生器 (Hugo)&amp;#34;]
direction TB
Dev[&amp;#34;開發者 / CI/CD&amp;#34;] --&amp;gt; HugoBuild[&amp;#34;Hugo 建置處理&amp;#34;]
Markdown[&amp;#34;Markdown 檔案群&amp;#34;] --&amp;gt; HugoBuild
Templates[&amp;#34;模板 (HTML)&amp;#34;] --&amp;gt; HugoBuild
HugoBuild --&amp;gt; StaticFiles[&amp;#34;靜態檔案群 (HTML/CSS/JS)&amp;#34;]
StaticFiles --&amp;gt; CDN[&amp;#34;CDN / 靜態託管&amp;#34;]
Req2[&amp;#34;使用者的請求&amp;#34;] --&amp;gt; CDN
CDN --&amp;gt; Res2[&amp;#34;即時回傳回應&amp;#34;]
end
&lt;/pre>
&lt;hr>
&lt;h2 id="2-透過數理模型進行效能評估">2. 透過數理模型進行效能評估
&lt;/h2>&lt;p>從 WordPress 移轉到 Hugo 的最大優勢之一就是效能（顯示速度）的提升。為了定量地理解這一點，我們試著用簡單的數學模型來表現。&lt;/p>
&lt;p>頁面讀取完成所需的時間（Load Time: $T_{load}$），主要可分為伺服器的回應時間（TTFB: Time To First Byte）與瀏覽器的渲染及資源獲取時間（$T_{render}$）。&lt;/p>
$$ T_{load} = T_{ttfb} + T_{render} $$&lt;p>在動態 CMS（WordPress）的情況下，$T_{ttfb}$ 是以下要素的總和：網路延遲（$T_{network}$）、伺服器端腳本執行時間（$T_{php}$）、資料庫查詢處理時間（$T_{db}$）。&lt;/p>
$$ T_{ttfb\_wp} = T_{network} + T_{php} + T_{db} $$&lt;p>在存取集中的狀態（高負載時），$T_{php}$ 與 $T_{db}$ 會呈非線性增加，可能成為整個系統的瓶頸。以數學公式表示，相對於請求數（$N$），會出現如下的回應時間惡化（$k$ 為處理的負擔係數）。&lt;/p>
$$ T_{php}(N) \approx O(N^k), \quad T_{db}(N) \approx O(N^k) \quad \text{where } k > 1 $$&lt;p>另一方面，結合了靜態網站產生器（Hugo）與 CDN 的架構中，不存在伺服器端的動態處理（PHP 或 DB 查詢）。由於內容已被快取在分散於世界各地的邊緣伺服器中，$T_{ttfb}$ 純粹只取決於從客戶端到最近邊緣伺服器的網路延遲（$T_{edge}$）。&lt;/p>
$$ T_{ttfb\_hugo} = T_{edge} $$&lt;p>藉此，$T_{edge} \ll (T_{network} + T_{php} + T_{db})$ 成立，TTFB 將劇烈縮短至幾毫秒到幾十毫秒左右。此外，即使請求數 $N$ 增加，得益於邊緣伺服器的負載平衡功能，回應時間也能保持幾乎固定（$O(1)$）。&lt;/p>
$$ \lim_{N \to \infty} T_{ttfb\_hugo}(N) \approx \text{Constant} $$&lt;p>這就是 Hugo（靜態網站）對流量突增（如爆紅時）具有極高穩健性的數理依據。&lt;/p>
&lt;hr>
&lt;h2 id="3-hugo-的基本結構與運作原理">3. Hugo 的基本結構與運作原理
&lt;/h2>&lt;p>要精通 Hugo，就必須理解其獨特的目錄結構以及「Front Matter」與「Template Lookup Order」的概念。&lt;/p>
&lt;h3 id="31-目錄結構詳細解說">3.1 目錄結構詳細解說
&lt;/h3>&lt;p>建立新的 Hugo 專案（&lt;code>hugo new site mysite&lt;/code>）時，會產生如下的目錄結構：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">mysite/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── archetypes/ # 建立新內容時的模板（Front Matter 的雛形）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── assets/ # 交由 Hugo Pipes 處理的檔案群（SCSS/Sass, JavaScript 等）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── content/ # 實際的網站內容（Markdown 檔案群）。這裡將取代 DB。
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── data/ # 整個網站共用的外部資料與設定（JSON, TOML, YAML, CSV 等）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── layouts/ # 決定網站外觀的 HTML 模板群（使用 Go html/template）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── public/ # 執行建置指令後，產生的靜態檔案輸出的位置
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── static/ # 原封不動發布的靜態檔案（圖片、favicon、機器人用的文字檔等）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── themes/ # 第三方或自製的主題目錄
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── hugo.toml # 整個網站的設定檔（以前主要是 config.toml）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在 WordPress 中，內容會儲存在 MySQL 的 &lt;code>wp_posts&lt;/code> 資料表中，但在 Hugo 則是全部作為 &lt;code>content/&lt;/code> 目錄內的文字檔案（主要是 Markdown）來管理。這使得內容的版本控制（Git）變得容易。&lt;/p>
&lt;h3 id="32-內容管理markdown-與-front-matter">3.2 內容管理：Markdown 與 Front Matter
&lt;/h3>&lt;p>Hugo 的每篇文章檔案最上方都會有一個被稱為「Front Matter（前置作業資料）」的中介資料區塊，其下方接著本文（Markdown）。Front Matter 可以使用 TOML、YAML、JSON 之一來撰寫，但最廣泛使用的是 YAML。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;理解 Hugo 的分類系統&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">date&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="ld">2026-09-13T10:00:00&lt;/span>&lt;span class="m">+09&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="m">00&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">draft&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">categories&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;技術解說&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Go&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">aliases&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/old-category/hugo-taxonomy/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">從這裡開始是本文。以 **Markdown** 進行撰寫。&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">將解說 Hugo 強大的功能...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這裡值得注意的是 &lt;code>aliases&lt;/code> 鍵。從 WordPress 移轉時，如果永久連結（URL）改變，對 SEO 會帶來很大的負面影響。只要使用 Hugo 的別名功能指定舊 URL，Hugo 就會自動產生用於重新導向的 HTML（透過 meta refresh 進行轉址）。因為不需要設定伺服器端的重新導向（如 .htaccess 等），所以非常方便。&lt;/p>
&lt;h3 id="33-模板的尋找順序template-lookup-order">3.3 模板的尋找順序（Template Lookup Order）
&lt;/h3>&lt;p>Hugo 強大的功能之一就是靈活的模板尋找機制（Template Lookup Order）。Hugo 在渲染特定頁面時，為了找到最適合的模板，會以特定的順序搜尋目錄與檔案名稱。&lt;/p>
&lt;p>例如，在繪製 &lt;code>content/post/hello-world.md&lt;/code> 這篇單一文章（Single Page）時，Hugo 大致上會依照以下順序尋找佈局檔案：&lt;/p>
&lt;ol>
&lt;li>&lt;code>layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>layouts/post/list.html&lt;/code> （雖然沒有錯，但通常是用於列表）&lt;/li>
&lt;li>&lt;code>layouts/_default/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;THEME_NAME&amp;gt;/layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;THEME_NAME&amp;gt;/layouts/_default/single.html&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>開發者無需直接修改主題的原始碼，只需在自己專案的 &lt;code>layouts/&lt;/code> 目錄中建立相同名稱的檔案，就能**覆蓋（Override）**主題的模板。這樣一來，就能在不阻礙基礎主題更新的情況下，進行專屬的客製化。&lt;/p>
&lt;h3 id="34-分類系統taxonomy">3.4 分類系統（Taxonomy）
&lt;/h3>&lt;p>相當於 WordPress 的「分類」與「標籤」的分類系統，在 Hugo 中稱為「Taxonomy」。
Hugo 預設支援 &lt;code>categories&lt;/code> 與 &lt;code>tags&lt;/code> 兩種分類，但透過編輯 &lt;code>hugo.toml&lt;/code>，可以自由加入自訂分類（例如：&lt;code>series&lt;/code>、&lt;code>authors&lt;/code> 等）。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># hugo.toml 的範例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">taxonomies&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">category&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;categories&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tag&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;tags&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">series&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;series&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">author&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;authors&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如此一來，就能以多種維度對內容進行整理與條列化。&lt;/p>
&lt;hr>
&lt;h2 id="4-從-wordpress-到-hugo-的移轉流程migration">4. 從 WordPress 到 Hugo 的移轉流程（Migration）
&lt;/h2>&lt;p>從 WordPress 移轉到 Hugo 的成功關鍵，在於如何將資料庫內的動態內容乾淨地轉換成靜態檔案（Markdown + Front Matter），並維持既有的 URL 結構。&lt;/p>
&lt;p>以下展示一般的移轉工作流程。&lt;/p>
&lt;pre class="mermaid">
flowchart LR
WPDB[&amp;#34;WP 資料庫&amp;#34;] --&amp;gt;|Plugin| Exporter[&amp;#34;匯出工具&amp;#34;]
Exporter --&amp;gt;| 擷取文字、\n中介資料、圖片 | ZipFile[&amp;#34;Zip / 資料夾&amp;#34;]
ZipFile --&amp;gt;|Unpack| MarkdownFiles[&amp;#34;Markdown 檔案 \n(content/)&amp;#34;]
ZipFile --&amp;gt;|Unpack| ImageFiles[&amp;#34;圖片 \n(static/wp-content/)&amp;#34;]
MarkdownFiles --&amp;gt; Formatting[&amp;#34;審查與格式化 \n(修復短代碼)&amp;#34;]
Formatting --&amp;gt; Git[&amp;#34;提交至 Git&amp;#34;]
&lt;/pre>
&lt;h3 id="41-萃取資料並轉為-markdown">4.1 萃取資料並轉為 Markdown
&lt;/h3>&lt;p>為了將 WordPress 的資料輸出給 Hugo 使用，最簡單且確定的方法是使用專用的外掛。以下介紹幾種具代表性的方法。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>使用 Jekyll Exporter 外掛&lt;/strong>
由於 Hugo 與同為 SSG 的 Jekyll 在資料結構上非常相似，因此使用 WordPress 專用的「Jekyll Exporter」外掛是常見的做法。安裝並執行此外掛後，所有的文章與固定頁面都會被轉換成帶有 Front Matter 的 Markdown 檔案，並與圖片檔案群一起打包成 ZIP 檔供下載。&lt;/li>
&lt;li>&lt;strong>利用 WordPress API 自製腳本&lt;/strong>
這是一種透過 Python 或 Node.js 等呼叫 WordPress 的 REST API (&lt;code>/wp-json/wp/v2/posts&lt;/code>)，解析 JSON 資料並自行產生 Markdown 檔案的腳本方法。這對大量使用外掛無法完全支援的複雜自訂欄位（如 ACF 等）的網站非常有效。&lt;/li>
&lt;li>&lt;strong>活用 wp2hugo 工具&lt;/strong>
也有利用 Go 語言等撰寫的 CLI 工具，直接從 WordPress 的匯出 XML 檔（WXR）轉換成 Hugo 格式的方法。&lt;/li>
&lt;/ol>
&lt;h3 id="42-維持永久連結url結構">4.2 維持永久連結（URL）結構
&lt;/h3>&lt;p>為了繼承 SEO 的評價，維持 WordPress 時期的 URL 是非常重要的。如果 WordPress 中的永久連結設定為類似 &lt;code>https://example.com/2026/09/13/my-post/&lt;/code> 的結構，請在 Hugo 的 &lt;code>hugo.toml&lt;/code> 中指定永久連結的結構。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">permalinks&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">post&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;/:year/:month/:day/:slug/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>或者，也可以在每篇文章的 Front Matter 內直接指定 &lt;code>url&lt;/code> 參數，強制固定 URL。
此外，對於 URL 會變更的頁面，請使用前述的 &lt;code>aliases&lt;/code> 來設定重新導向。&lt;/p>
&lt;h3 id="43-短代碼shortcode的轉換">4.3 短代碼（Shortcode）的轉換
&lt;/h3>&lt;p>WordPress 特有的短代碼（例如：&lt;code>[gallery]&lt;/code>、&lt;code>[caption]&lt;/code>、各種外掛的專屬代碼），在匯出時通常會以原字串保留，因此需要進行處理。
可以使用取代腳本（sed 或 Python）將其一次性刪除，或者利用 Hugo 強大的&lt;strong>自訂短代碼功能&lt;/strong>（在 &lt;code>layouts/shortcodes/&lt;/code> 內建立專屬佈局），讓它們能在 Hugo 端正確地被渲染。&lt;/p>
&lt;hr>
&lt;h2 id="5-hugo-的-cli-工具與建置部署">5. Hugo 的 CLI 工具與建置、部署
&lt;/h2>&lt;p>移轉作業完成後，終於要使用 Hugo 建置網站並向全世界發布了。作為 Go 語言二進位檔案提供的 Hugo，即使是擁有數千到數萬個頁面的網站，也擁有能在短短幾秒內完成建置的驚人速度。&lt;/p>
&lt;h3 id="51-啟動本機開發用伺服器">5.1 啟動本機開發用伺服器
&lt;/h3>&lt;p>在撰寫文章或調整設計時，可以啟動本機伺服器。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 開發伺服器的啟動指令（若要包含 Draft 文章則加上 -D）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>執行此指令後，即可在 &lt;code>http://localhost:1313/&lt;/code> 預覽網站。Hugo 內建了強大的「LiveReload」功能，在您編輯並儲存 Markdown 檔案、模板或 CSS 的瞬間，瀏覽器畫面就會自動高速更新。這使得寫作與開發體驗遠比 WordPress 的管理介面舒適得多。&lt;/p>
&lt;h3 id="52-正式環境建置與效能最佳化">5.2 正式環境建置與效能最佳化
&lt;/h3>&lt;p>要產生用於部署到正式環境的靜態檔案，只需輸入 &lt;code>hugo&lt;/code> 即可。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 執行正式環境建置。透過 --minify 選項來最小化 HTML/CSS/JS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo --minify
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過此指令，整個網站的檔案會被輸出到 &lt;code>public/&lt;/code> 目錄。加上 &lt;code>--minify&lt;/code> 選項可以刪除不必要的換行與空白，進一步縮減檔案大小。這將直接貢獻於降低前述數學模型中的網路延遲（$T_{network}$）。&lt;/p>
&lt;h3 id="53-部署的自動化cicd">5.3 部署的自動化（CI/CD）
&lt;/h3>&lt;p>每次都在本機 PC 上產生靜態檔案，再用 FTP 等方式上傳是沒有效率的。在現代的 SSG 營運中，將 Push 至 Git 儲存庫（如 GitHub 等）作為觸發條件，自動進行建置與部署的 CI/CD 環境建構是最佳實踐。&lt;/p>
&lt;p>例如，使用 GitHub Actions 部署至 Cloudflare Pages 或 GitHub Pages 的設定檔（YAML 檔案）基本形式如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># .github/workflows/hugo.yml 的範例&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy Hugo site to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">push&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">workflow_dispatch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">permissions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">contents&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">read&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pages&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id-token&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Checkout&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">submodules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">recursive&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 若透過子模組管理主題時&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fetch-depth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Setup Hugo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">peaceiris/actions-hugo@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hugo-version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;latest&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extended&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">hugo --minify&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Upload artifact&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/upload-pages-artifact@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">path&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">./public&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">github-pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">url&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ steps.deployment.outputs.page_url }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">needs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/deploy-pages@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過這樣的設定，只需執行「用 Markdown 寫文章並 Push 到 GitHub」的動作，幾分鐘後最新的網站就會公開到正式環境，完成了自動化管線。&lt;/p>
&lt;hr>
&lt;h2 id="6-移轉後的-seo-與營運面的優勢">6. 移轉後的 SEO 與營運面的優勢
&lt;/h2>&lt;p>完成從 WordPress 移轉至 Hugo 的網站營運者，大多能感受到以下三個顯著的優勢。&lt;/p>
&lt;h3 id="61-網站速度與-core-web-vitals-的劇烈提升">6.1 網站速度與 Core Web Vitals 的劇烈提升
&lt;/h3>&lt;p>排除了資料庫查詢與伺服器端渲染後，頁面載入時間縮短至毫秒等級。這將直接帶動 Google 排名因素「Core Web Vitals」（LCP、FID/INP、CLS）分數的大幅提升。可以期待使用者跳出率的降低以及 SEO 評價的提升。&lt;/p>
&lt;h3 id="62-擺脫安全威脅">6.2 擺脫安全威脅
&lt;/h3>&lt;p>因為 WordPress 在全世界被廣泛使用，所以總是成為攻擊目標。伴隨著被利用外掛漏洞進行竄改，或是遭到暴力破解突破登入等風險。
然而，由 Hugo 產生的靜態網站，既沒有資料庫也沒有 PHP 環境，甚至連管理介面（登入表單）都不存在。駭客根本沒有入侵伺服器篡改資料庫的餘地，安全風險幾乎降至極限的零。&lt;/p>
&lt;h3 id="63-免維護的營運">6.3 免維護的營運
&lt;/h3>&lt;p>在 WordPress 的營運中，需要不斷進行核心程式升級、外掛更新、跟進 PHP 版本等永無止盡的維護作業。總是需要擔心因相容性問題導致網站崩壞的風險。
而在 Hugo 的情況，只需要視需求進行工具本身的更新即可，網站程式碼本身是獨立的文字檔案群，因此擁有「放著不管也不會壞」的壓倒性安心感。&lt;/p>
&lt;hr>
&lt;h2 id="7-總結">7. 總結
&lt;/h2>&lt;p>本篇文章從技術架構的差異、透過數理模型的效能證明，到具體的移轉步驟，詳細解說了從 WordPress 這種動態 CMS 移轉到基於 Go 語言強大的靜態網站產生器「Hugo」的過程。&lt;/p>
&lt;p>移轉至靜態網站產生器雖然需要初期的學習成本（Git 的操作、Markdown 的語法、從終端機執行 CLI 指令、理解模板引擎的規範等），但它所帶來的是「壓倒性的顯示速度」、「堅固的安全性」以及「免維護」等足以彌補這些成本的豐厚回報。&lt;/p>
&lt;p>如果您的網站不需要頻繁更改設計或複雜的動態處理（如會員專屬功能或進階的電商功能），且主要目的是發布資訊（部落格、媒體、企業網站），那麼移轉到 Hugo 將會是最有效的技術投資之一。請務必參考本篇文章，邁出使用 Hugo 營運次世代網站的第一步。&lt;/p></description></item><item><title>Hugo 部落格的 SEO 策略：大幅增加流量的 Frontmatter 設定</title><link>http://kenji.blog/zh-tw/p/hugo-blog-seo-frontmatter-tips/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/zh-tw/p/hugo-blog-seo-frontmatter-tips/</guid><description>&lt;img src="http://kenji.blog/p/hugo-blog-seo-frontmatter-tips/img/eyecatch.jpg" alt="Featured image of post Hugo 部落格的 SEO 策略：大幅增加流量的 Frontmatter 設定" />&lt;p>Hugo 是一款以 Go 語言編寫、世界最快等級的靜態網站產生器 (SSG)。憑藉其壓倒性的建置速度與靈活的模板系統，獲得了許多工程師與部落客的高度支持。然而，僅僅是網站能高速生成與顯示，並無法獲得搜尋引擎 (如 Google 或 Bing) 的高評價，也就無法將文章傳遞給使用者。&lt;/p>
&lt;p>為了提升搜尋排名、增強在社群媒體上的擴散力，進而大幅增加部落格的流量，縝密的 SEO (搜尋引擎最佳化) 策略是不可或缺的。Hugo 中 SEO 策略的核心，在於每篇 Markdown 文章開頭所撰寫的 &lt;strong>Frontmatter&lt;/strong>，與解析它並將中繼資料展開至 HTML &lt;code>&amp;lt;head&amp;gt;&lt;/code> 標籤內的&lt;strong>模板 (Layouts)&lt;/strong> 之間的協作。&lt;/p>
&lt;p>本文將徹底解說如何將 Hugo 的功能發揮到極致，以實作進階 SEO 策略的 Frontmatter 設定，涵蓋各種 Meta 標籤、OGP (Open Graph Protocol)、Twitter Cards，以及使用 JSON-LD 輸出結構化資料。內容將以壓倒性的豐富度詳細說明。&lt;/p>
&lt;hr>
&lt;h2 id="1-seo-與流量的數學背景">1. SEO 與流量的數學背景
&lt;/h2>&lt;p>在進入具體的實作之前，讓我們先從數學的角度來理解為何細微的 SEO 中繼資料如此重要。網站能獲得的搜尋流量 $T$，是由目標關鍵字的搜尋量，以及基於搜尋排名的點擊率 (CTR) 所決定的。&lt;/p>
&lt;p>用數學公式表示如下：&lt;/p>
$$ T = \sum_{i=1}^{n} V_i \times CTR(R_i) $$&lt;ul>
&lt;li>$V_i$ : 關鍵字 $i$ 的每月搜尋量&lt;/li>
&lt;li>$R_i$ : 關鍵字 $i$ 的搜尋排名&lt;/li>
&lt;li>$CTR(R_i)$ : 排名 $R_i$ 的點擊率&lt;/li>
&lt;/ul>
&lt;p>其中，搜尋排名 $R_i$ 取決於內容品質與反向連結 (PageRank) 等許多因素，但 Google 早期的 PageRank 演算法被模型化如下：&lt;/p>
$$ PR(u) = \frac{1-d}{N} + d \sum_{v \in B(u)} \frac{PR(v)}{L(v)} $$&lt;ul>
&lt;li>$PR(u)$ : 頁面 $u$ 的 PageRank&lt;/li>
&lt;li>$d$ : 阻尼係數 (通常為 0.85)&lt;/li>
&lt;li>$B(u)$ : 連結到頁面 $u$ 的頁面集合&lt;/li>
&lt;li>$L(v)$ : 頁面 $v$ 的對外連結數&lt;/li>
&lt;/ul>
&lt;p>這裡最重要的是，&lt;strong>除了努力提升搜尋排名 $R_i$ 之外，還要注意如何將點擊率 $CTR(R_i)$ 最大化&lt;/strong>。透過最佳化顯示在搜尋結果 (SERPs) 中的標題與摘要 (description)，以及在社群媒體上分享時的吸睛圖片 (OGP)，可以有意識地提高 $CTR(R_i)$。Frontmatter 的 SEO 設定，正是直接關乎這項 $CTR$ 的最大化。&lt;/p>
&lt;hr>
&lt;h2 id="2-hugo-的建置流程與-frontmatter-的作用">2. Hugo 的建置流程與 Frontmatter 的作用
&lt;/h2>&lt;p>Hugo 會讀取 Markdown 檔案內的 Frontmatter (YAML/TOML/JSON)，並將其作為頁面變數傳遞給模板引擎。首先，讓我們視覺化地了解這個資訊的流向。&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Markdown 檔案&amp;#34;] --&amp;gt; B[&amp;#34;Frontmatter 解析&amp;#34;]
A --&amp;gt; C[&amp;#34;內容解析&amp;#34;]
B --&amp;gt; D[&amp;#34;Hugo 頁面變數 (.Title, .Params)&amp;#34;]
C --&amp;gt; D
E[&amp;#34;layouts/partials/head.html&amp;#34;] --&amp;gt; F[&amp;#34;Go 模板引擎&amp;#34;]
D --&amp;gt; F
F --&amp;gt; G[&amp;#34;最終 HTML &amp;lt;head&amp;gt; 標籤&amp;#34;]
G --&amp;gt; H[&amp;#34;Googlebot / 爬蟲&amp;#34;]
G --&amp;gt; I[&amp;#34;社群媒體爬蟲 (OGP)&amp;#34;]
&lt;/pre>
&lt;p>如此一來，在 Frontmatter 中設定的值會作為 &lt;code>.Title&lt;/code> 或 &lt;code>.Params.description&lt;/code> 等變數傳遞給 &lt;code>head.html&lt;/code>，並輸出為最終的 HTML 中繼資料。因此，SEO 的成功取決於兩個步驟：「在 Frontmatter 中定義適當的資訊」與「在模板中將其正確地轉換為 HTML」。&lt;/p>
&lt;hr>
&lt;h2 id="3-基本中繼資料設定title-description-canonical-url">3. 基本中繼資料設定：Title, Description, Canonical URL
&lt;/h2>&lt;p>為了讓搜尋引擎理解頁面內容，最基本的標籤就是 &lt;code>&amp;lt;title&amp;gt;&lt;/code> 和 &lt;code>&amp;lt;meta name=&amp;quot;description&amp;quot;&amp;gt;&lt;/code>。此外，為了避免重複內容的懲罰，&lt;code>&amp;lt;link rel=&amp;quot;canonical&amp;quot;&amp;gt;&lt;/code> 也是必須的。&lt;/p>
&lt;h3 id="31-frontmatter-的設定範例">3.1. Frontmatter 的設定範例
&lt;/h3>&lt;p>在文章的 Frontmatter 中，我們會準備專為 SEO 設計的欄位。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;Hugo 部落格的 SEO 策略：大幅增加流量的 Frontmatter 設定&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">seo_title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;Hugo SEO 策略完全指南：用 Frontmatter 提升流量&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 選用：提供給搜尋引擎&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;運用 Hugo 的 Frontmatter 進行進階 SEO 策略的手法。詳細解說 OGP、JSON-LD 以及中繼資料的設定方式。&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">slug&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;hugo-seo-frontmatter-tips&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">canonicalUrl&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;https://example.com/post/hugo-seo-frontmatter-tips/&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 明確的標準 URL&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="32-layoutspartialsheadhtml-的實作">3.2. &lt;code>layouts/partials/head.html&lt;/code> 的實作
&lt;/h3>&lt;p>為了正確輸出這些變數，我們將建立 HTML 模板。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- 標題最佳化 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $title := .Title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.seo_title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $title = .Params.seo_title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>{{ $title }} | {{ .Site.Title }}&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Description 最佳化 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $description := .Summary | plainify | truncate 120 }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.description }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $description = .Params.description }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Canonical URL (標準化) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $canonical := .Permalink }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.canonicalUrl }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $canonical = .Params.canonicalUrl }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;canonical&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $canonical }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- 機器人控制 (例如拒絕索引設定) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.noindex }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;robots&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;noindex, nofollow&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;robots&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;index, follow&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過使用 Hugo 的 &lt;code>.Summary&lt;/code> 作為後備方案，即使尚未設定 &lt;code>description&lt;/code>，也能自動擷取文章的開頭文字。&lt;/p>
&lt;hr>
&lt;h2 id="4-ogp-與-twitter-cards將社群媒體的-ctr-最大化">4. OGP 與 Twitter Cards：將社群媒體的 CTR 最大化
&lt;/h2>&lt;p>當文章在 Twitter (X) 或 Facebook 等社群網路服務 (SNS) 上被分享時，為了讓它以具吸引力的卡片格式顯示，Open Graph Protocol (OGP) 與 Twitter Cards 的設定是不可或缺的。這同樣可由 Frontmatter 動態產生。&lt;/p>
&lt;h3 id="41-內建模板的挑戰">4.1. 內建模板的挑戰
&lt;/h3>&lt;p>雖然 Hugo 有個方便的內建模板 &lt;code>{{ template &amp;quot;_internal/opengraph.html&amp;quot; . }}&lt;/code>，但它的客製化程度不足，有時無法符合中文環境或特定需求。因此，強烈建議您在 &lt;code>head.html&lt;/code> 內實作自訂的 OGP 標籤。&lt;/p>
&lt;h3 id="42-在-frontmatter-中指定圖片">4.2. 在 Frontmatter 中指定圖片
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;img/eyecatch.jpg&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">images&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;img/eyecatch-large.jpg&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># 用於指定多張圖片或絕對路徑&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="43-ogp-與-twitter-cards-的自訂實作程式碼">4.3. OGP 與 Twitter Cards 的自訂實作程式碼
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Open Graph Protocol --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:title&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:type&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ if .IsPage }}article{{ else }}website{{ end }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:url&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:site_name&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ .Site.Title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- OGP Image 的解析 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $ogImage := &amp;#34;&amp;#34; }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.image }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = .Params.image | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else if .Params.images }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = index .Params.images 0 | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else if .Site.Params.defaultImage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = .Site.Params.defaultImage | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if $ogImage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:image&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:image&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:card&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;summary_large_image&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:card&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;summary&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Twitter Cards --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:title&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Site.Params.twitterAccount }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:site&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;@{{ .Site.Params.twitterAccount }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>透過套用 &lt;code>absURL&lt;/code> 函式，可以將以相對路徑指定的圖片 URL 轉換為絕對路徑。由於 OGP 強制要求必須使用絕對路徑，因此這個處理非常重要。&lt;/p>
&lt;hr>
&lt;h2 id="5-實作結構化資料-json-ld">5. 實作結構化資料 (JSON-LD)
&lt;/h2>&lt;p>在現今的 SEO 中，&lt;strong>JSON-LD (JavaScript Object Notation for Linked Data)&lt;/strong> 已成為向搜尋引擎精確傳達頁面語意結構的主流技術。透過這項設定，能更容易在搜尋結果中顯示複合式摘要 (如星級評分、作者名稱、發布日期等)。&lt;/p>
&lt;h3 id="51-json-ld-的結構">5.1. JSON-LD 的結構
&lt;/h3>&lt;p>在部落格文章中，我們主要會實作 &lt;code>Article&lt;/code> (文章) 結構描述與 &lt;code>BreadcrumbList&lt;/code> (導覽標記) 結構描述這兩種。&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Schema.org 定義&amp;#34;] --&amp;gt; B[&amp;#34;Article 結構描述&amp;#34;]
A --&amp;gt; C[&amp;#34;BreadcrumbList 結構描述&amp;#34;]
B --&amp;gt; D[&amp;#34;headline&amp;#34;]
B --&amp;gt; E[&amp;#34;datePublished&amp;#34;]
B --&amp;gt; F[&amp;#34;dateModified&amp;#34;]
B --&amp;gt; G[&amp;#34;author&amp;#34;]
B --&amp;gt; H[&amp;#34;image&amp;#34;]
C --&amp;gt; I[&amp;#34;ListItem 1&amp;#34;]
C --&amp;gt; J[&amp;#34;ListItem 2&amp;#34;]
I --&amp;gt; K[&amp;#34;position: 1&amp;#34;]
I --&amp;gt; L[&amp;#34;name: 首頁&amp;#34;]
J --&amp;gt; M[&amp;#34;position: 2&amp;#34;]
J --&amp;gt; N[&amp;#34;name: 分類 / 部落格&amp;#34;]
&lt;/pre>
&lt;h3 id="52-在-hugo-模板中產生-json-ld">5.2. 在 Hugo 模板中產生 JSON-LD
&lt;/h3>&lt;p>活用 Frontmatter 的 &lt;code>.Date&lt;/code> 或 &lt;code>.Lastmod&lt;/code> 等變數，來動態輸出 JSON-LD。這會使用 &lt;code>&amp;lt;script type=&amp;quot;application/ld+json&amp;quot;&amp;gt;&lt;/code> 標籤撰寫在 &lt;code>head.html&lt;/code> 內。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">{{ if .IsPage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Article&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mainEntityOfPage&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;WebPage&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@id&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;headline&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Title | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ $description | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;datePublished&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Date.Format &amp;#34;&lt;/span>&lt;span class="mi">2006&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">01&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">02&lt;/span>&lt;span class="nx">T15&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">04&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">05&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">00&lt;/span>&lt;span class="s2">&amp;#34; }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;dateModified&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Lastmod.Format &amp;#34;&lt;/span>&lt;span class="mi">2006&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">01&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">02&lt;/span>&lt;span class="nx">T15&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">04&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">05&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">00&lt;/span>&lt;span class="s2">&amp;#34; }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;author&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Person&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ if .Params.author }}{{ .Params.author }}{{ else }}{{ .Site.Params.author }}{{ end }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;publisher&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Organization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.Title }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;logo&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ImageObject&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.Params.logo | absURL }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- BreadcrumbList Schema --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;BreadcrumbList&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;itemListElement&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Home&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.BaseURL }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">range&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="nx">Params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">categories&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">,{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="p">}},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ . }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ &amp;#34;&lt;/span>&lt;span class="nx">categories&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="s2">&amp;#34; | relLangURL }}{{ . | urlize | lower }}/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">add&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">end&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">,{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="p">}},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Title | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在 JSON-LD 內展開字串時，關鍵在於使用 &lt;code>htmlEscape&lt;/code> (或 &lt;code>jsonify&lt;/code>)，以防止雙引號遭到破壞。這麼一來，無論 Frontmatter 中使用了什麼符號，都能避免 JSON 的語法錯誤。&lt;/p>
&lt;hr>
&lt;h2 id="6-frontmatter-的進階應用技巧">6. Frontmatter 的進階應用技巧
&lt;/h2>&lt;p>除了基本的 SEO 中繼資料之外，Hugo 的 Frontmatter 還具備了能實現更進階 SEO 策略的功能。&lt;/p>
&lt;h3 id="61-透過別名-aliases-進行的重新導向處理">6.1. 透過別名 (Aliases) 進行的重新導向處理
&lt;/h3>&lt;p>當您從過去的部落格服務轉移至 Hugo，或是變更了永久連結 (Permalink) 結構時，您必須將來自現有 URL 的流量重新導向至新的 URL。只要使用 Hugo 的 &lt;code>aliases&lt;/code> 欄位，就能自動為舊 URL 產生 HTTP-Equiv 重新整理 (Meta 重新導向) 頁面。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;新的文章標題&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">slug&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;new-seo-post&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">aliases&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/old-category/old-seo-post/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/2020/05/12/seo-tips/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-文章的有效期限與排程">6.2. 文章的有效期限與排程
&lt;/h3>&lt;p>對於期間限定的活動文章，或是過時後就會失去價值的資訊，透過設定 &lt;code>expiryDate&lt;/code>，您可以在特定日期時間之後將其從建置結果中排除，讓它不再顯示於網站上 (傳回 404)。這麼做可以防止品質低落的舊內容持續留在索引中，進而降低網站整體的評價。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;2026 年限定的 SEO 技巧&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">publishDate&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;2026-01-01T00:00:00Z&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">expiryDate&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;2026-12-31T23:59:59Z&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-網站效能與-core-web-vitals">7. 網站效能與 Core Web Vitals
&lt;/h2>&lt;p>在 SEO 領域，與標籤最佳化同等重要的，就是&lt;strong>頁面的載入速度&lt;/strong>。Google 已將 Core Web Vitals (LCP, FID/INP, CLS) 納入排名因素之中。&lt;/p>
&lt;p>作為靜態網站的 Hugo 本身在 TTFB (Time to First Byte) 上就表現優異，但在大量使用圖片的部落格中，圖片最佳化是不可或缺的。透過將 Hugo 強大的圖片處理功能 (Image Processing) 結合 Frontmatter 一同使用，可以在建置時自動進行調整大小或轉換為次世代格式 (如 WebP 等)。&lt;/p>
&lt;p>舉例來說，您可以建立一個 Shortcode，讓它根據 Frontmatter 中指定的圖片路徑，在模板端自動產生 WebP 圖片。如此一來，就有可能大幅提升 SEO 的評價。&lt;/p>
&lt;hr>
&lt;h2 id="8-總結">8. 總結
&lt;/h2>&lt;p>在使用 Hugo 經營部落格的過程中，Frontmatter 並不單純只是「一堆設定值」，而是用來與搜尋引擎及 SNS 進行對話的「控制面板」。&lt;/p>
&lt;p>只要確實實作本文所解說的以下重點，您的部落格 SEO 基礎將會變得十分堅固。&lt;/p>
&lt;ol>
&lt;li>&lt;strong>動態產生基本中繼資料&lt;/strong>: 確實輸出 Title, Description, Canonical&lt;/li>
&lt;li>&lt;strong>社群分享最佳化&lt;/strong>: 透過自訂實作 OGP 與 Twitter Cards 來提升 CTR&lt;/li>
&lt;li>&lt;strong>完整支援結構化資料&lt;/strong>: 透過 JSON-LD (Article, Breadcrumb) 支援複合式搜尋結果&lt;/li>
&lt;li>&lt;strong>進階流量管理&lt;/strong>: 透過 Aliases 進行重新導向，以及使用 Meta 標籤進行機器人控制&lt;/li>
&lt;/ol>
&lt;p>儘管搜尋引擎的演算法日新月異，但提供能讓搜尋引擎「正確理解頁面內容」的訊號，這項 SEO 根本原則是不會改變的。透過鑽研 Hugo 靈活的模板引擎與 Frontmatter，持續發送出最高品質的訊號，讓部落格的流量獲得戲劇性的增長吧！&lt;/p></description></item></channel></rss>