<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>前端 on kkkk24 的博客</title>
    <link>https://web.943827561.xyz/tags/%E5%89%8D%E7%AB%AF/</link>
    <description>Recent content in 前端 on kkkk24 的博客</description>
    <generator>Hugo -- 0.155.2</generator>
    <language>zh-cn</language>
    <lastBuildDate>Wed, 04 Feb 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://web.943827561.xyz/tags/%E5%89%8D%E7%AB%AF/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Hugo 博客加载速度优化实践</title>
      <link>https://web.943827561.xyz/posts/hugo-blog-performance-optimization/</link>
      <pubDate>Wed, 04 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://web.943827561.xyz/posts/hugo-blog-performance-optimization/</guid>
      <description>记录优化 Hugo &#43; PaperMod 博客加载速度的完整过程，包括构建配置、图片懒加载、资源压缩等多个方面</description>
      <content:encoded><![CDATA[<h2 id="发现问题">发现问题</h2>
<p>博客搭建完成后，访问时总觉得有点卡。打开 Chrome DevTools 看了下 Network 面板，发现几个问题：</p>
<ol>
<li>图片没有做懒加载，首屏就加载了所有图片</li>
<li>HTML/CSS/JS 文件可以进一步压缩</li>
<li>没有利用好浏览器缓存</li>
<li>外部资源（如字体）请求有延迟</li>
</ol>
<p>既然发现了问题，那就一个个解决。</p>
<h2 id="hugo-构建优化">Hugo 构建优化</h2>
<h3 id="深度压缩配置">深度压缩配置</h3>
<p>Hugo 自带 minify 功能，但默认配置比较保守。在 <code>hugo.toml</code> 中可以配置更激进的压缩选项：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">minify</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="nx">disableXML</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">  <span class="nx">minifyOutput</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">.</span><span class="nx">css</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepCSS2</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">      <span class="nx">precision</span> <span class="p">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">.</span><span class="nx">html</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepDocumentTags</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepEndTags</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepQuotes</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepWhitespace</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">.</span><span class="nx">js</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepVarNames</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">      <span class="nx">precision</span> <span class="p">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">.</span><span class="nx">json</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepNumbers</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">      <span class="nx">precision</span> <span class="p">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="nx">minify</span><span class="p">.</span><span class="nx">tdewolff</span><span class="p">.</span><span class="nx">svg</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="nx">keepComments</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">      <span class="nx">precision</span> <span class="p">=</span> <span class="mi">0</span>
</span></span></code></pre></div><p>这个配置使用了 <a href="https://github.com/tdewolff/minify">tdewolff/minify</a> 库的参数，可以对各类资源做深度压缩：</p>
<ul>
<li><strong>CSS</strong>: 移除不必要的空格、简化数值精度</li>
<li><strong>HTML</strong>: 移除空白、可选引号</li>
<li><strong>JS</strong>: 压缩变量名</li>
<li><strong>SVG</strong>: 移除注释、简化数值</li>
</ul>
<h3 id="构建缓存">构建缓存</h3>
<p>重复构建时，很多资源是不变的，可以利用缓存加速：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">build</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="nx">writeStats</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="nx">caches</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">caches</span><span class="p">.</span><span class="nx">assets</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dir</span> <span class="p">=</span> <span class="s2">&#34;:resourceDir/_gen&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">maxAge</span> <span class="p">=</span> <span class="s2">&#34;720h&#34;</span>  <span class="c"># 30 天</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">caches</span><span class="p">.</span><span class="nx">getcsv</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dir</span> <span class="p">=</span> <span class="s2">&#34;:cacheDir/:project&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">maxAge</span> <span class="p">=</span> <span class="s2">&#34;4h&#34;</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">caches</span><span class="p">.</span><span class="nx">getjson</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dir</span> <span class="p">=</span> <span class="s2">&#34;:cacheDir/:project&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">maxAge</span> <span class="p">=</span> <span class="s2">&#34;4h&#34;</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">caches</span><span class="p">.</span><span class="nx">getresource</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dir</span> <span class="p">=</span> <span class="s2">&#34;:cacheDir/:project&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">maxAge</span> <span class="p">=</span> <span class="s2">&#34;4h&#34;</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">caches</span><span class="p">.</span><span class="nx">images</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">dir</span> <span class="p">=</span> <span class="s2">&#34;:resourceDir/_gen&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">maxAge</span> <span class="p">=</span> <span class="s2">&#34;720h&#34;</span>
</span></span></code></pre></div><p><code>writeStats = true</code> 会生成一个包含所有使用过的类名的文件，可以配合 PurgeCSS 做 tree-shaking（虽然 PaperMod 主题本身已经很精简了）。</p>
<h3 id="图片处理优化">图片处理优化</h3>
<p>Hugo 的图片处理功能很强大，合理配置可以减小图片体积：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">imaging</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="nx">quality</span> <span class="p">=</span> <span class="mi">80</span>
</span></span><span class="line"><span class="cl">  <span class="nx">resampleFilter</span> <span class="p">=</span> <span class="s2">&#34;Lanczos&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">hint</span> <span class="p">=</span> <span class="s2">&#34;photo&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">anchor</span> <span class="p">=</span> <span class="s2">&#34;Smart&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">bgColor</span> <span class="p">=</span> <span class="s2">&#34;#ffffff&#34;</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">imaging</span><span class="p">.</span><span class="nx">exif</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">disableDate</span> <span class="p">=</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">    <span class="nx">disableLatLong</span> <span class="p">=</span> <span class="kc">true</span>  <span class="c"># 保护隐私</span>
</span></span></code></pre></div><ul>
<li><code>quality = 80</code>：图片质量设为 80%，肉眼几乎看不出差别，但体积能减小不少</li>
<li><code>resampleFilter = &quot;Lanczos&quot;</code>：高质量重采样算法，适合缩放照片</li>
<li><code>anchor = &quot;Smart&quot;</code>：智能裁剪，自动识别图片主体</li>
<li><code>disableLatLong = true</code>：移除 EXIF 中的位置信息，保护隐私</li>
</ul>
<h2 id="前端优化">前端优化</h2>
<h3 id="dns-预解析和预连接">DNS 预解析和预连接</h3>
<p>浏览器解析域名需要时间，可以用 <code>dns-prefetch</code> 提前解析外部域名：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- 放在 layouts/partials/extend_head.html --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;dns-prefetch&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;//fonts.googleapis.com&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;dns-prefetch&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;//fonts.gstatic.com&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;dns-prefetch&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;//cdn.jsdelivr.net&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;preconnect&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://fonts.googleapis.com&#34;</span> <span class="na">crossorigin</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;preconnect&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://fonts.gstatic.com&#34;</span> <span class="na">crossorigin</span><span class="p">&gt;</span>
</span></span></code></pre></div><p><code>preconnect</code> 比 <code>dns-prefetch</code> 更进一步，会提前建立完整的 TCP 连接。</p>
<h3 id="图片懒加载">图片懒加载</h3>
<p>现代浏览器都支持原生的 <code>loading=&quot;lazy&quot;</code> 属性，不需要额外的 JS 库：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;DOMContentLoaded&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">function</span> <span class="nx">addLoadedClass</span><span class="p">(</span><span class="nx">img</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">img</span><span class="p">.</span><span class="nx">complete</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">img</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="s1">&#39;loaded&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">img</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;load&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">img</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="s1">&#39;loaded&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">  <span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s1">&#39;.post-content img&#39;</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">img</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">img</span><span class="p">.</span><span class="nx">hasAttribute</span><span class="p">(</span><span class="s1">&#39;loading&#39;</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">img</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;loading&#39;</span><span class="p">,</span> <span class="s1">&#39;lazy&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="nx">img</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;decoding&#39;</span><span class="p">,</span> <span class="s1">&#39;async&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="nx">addLoadedClass</span><span class="p">(</span><span class="nx">img</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>这段代码做了两件事：</p>
<ol>
<li>给所有文章图片添加 <code>loading=&quot;lazy&quot;</code> 和 <code>decoding=&quot;async&quot;</code> 属性</li>
<li>图片加载完成后添加 <code>loaded</code> 类，配合 CSS 做渐显效果</li>
</ol>
<h3 id="图片渐显效果">图片渐显效果</h3>
<p>配合上面的 JS，在 CSS 中实现平滑的渐显效果：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* assets/css/extended/custom.css */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">post-content</span> <span class="nt">img</span><span class="o">,</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">entry-cover</span> <span class="nt">img</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">code</span><span class="o">-</span><span class="n">bg</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">transition</span><span class="p">:</span> <span class="k">opacity</span> <span class="mf">0.3</span><span class="kt">s</span> <span class="kc">ease-in-out</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">post-content</span> <span class="nt">img</span><span class="o">[</span><span class="nt">loading</span><span class="o">=</span><span class="s2">&#34;lazy&#34;</span><span class="o">],</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">entry-cover</span> <span class="nt">img</span><span class="o">[</span><span class="nt">loading</span><span class="o">=</span><span class="s2">&#34;lazy&#34;</span><span class="o">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">opacity</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">post-content</span> <span class="nt">img</span><span class="p">.</span><span class="nc">loaded</span><span class="o">,</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">entry-cover</span> <span class="nt">img</span><span class="p">.</span><span class="nc">loaded</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">opacity</span><span class="p">:</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>这样图片在加载时会显示一个灰色占位背景，加载完成后平滑显示。</p>
<h3 id="减少布局偏移">减少布局偏移</h3>
<p>图片加载时如果没有预留空间，会导致页面布局跳动（CLS 指标），用户体验很差：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">.</span><span class="nc">post-content</span> <span class="nt">img</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">aspect-ratio</span><span class="p">:</span> <span class="nb">attr</span><span class="p">(</span><span class="n">width</span><span class="p">)</span> <span class="o">/</span> <span class="nb">attr</span><span class="p">(</span><span class="n">height</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">height</span><span class="p">:</span> <span class="kc">auto</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">max-width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>如果图片设置了 width 和 height 属性，浏览器可以提前计算出图片的宽高比，预留好空间。</p>
<h3 id="尊重用户偏好">尊重用户偏好</h3>
<p>有些用户可能对动画敏感，可以检测并禁用过渡效果：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-reduced-motion</span><span class="o">:</span> <span class="nt">no-preference</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">html</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">scroll-behavior</span><span class="p">:</span> <span class="kc">smooth</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">media</span> <span class="o">(</span><span class="nt">prefers-reduced-motion</span><span class="o">:</span> <span class="nt">reduce</span><span class="o">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="o">*,</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">::</span><span class="nd">before</span><span class="o">,</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">::</span><span class="nd">after</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">animation-duration</span><span class="p">:</span> <span class="mf">0.01</span><span class="kt">ms</span> <span class="cp">!important</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">transition-duration</span><span class="p">:</span> <span class="mf">0.01</span><span class="kt">ms</span> <span class="cp">!important</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">scroll-behavior</span><span class="p">:</span> <span class="kc">auto</span> <span class="cp">!important</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="优化效果">优化效果</h2>
<p>做完这些优化后，再看 Lighthouse 跑分：</p>
<table>
  <thead>
      <tr>
          <th>指标</th>
          <th>优化前</th>
          <th>优化后</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>首次内容绘制 (FCP)</td>
          <td>~1.5s</td>
          <td>~0.8s</td>
      </tr>
      <tr>
          <td>最大内容绘制 (LCP)</td>
          <td>~2.5s</td>
          <td>~1.5s</td>
      </tr>
      <tr>
          <td>累积布局偏移 (CLS)</td>
          <td>0.15</td>
          <td>&lt; 0.05</td>
      </tr>
  </tbody>
</table>
<p>当然，实际效果还取决于服务器性能和用户网络。</p>
<h2 id="更多优化思路">更多优化思路</h2>
<p>这次只做了 Hugo 本身的优化，还有一些可以继续优化的方向：</p>
<ol>
<li><strong>CDN 加速</strong>：把静态资源放到 CDN 上，全球访问都很快</li>
<li><strong>Gzip/Brotli 压缩</strong>：服务器开启压缩，进一步减小传输体积</li>
<li><strong>HTTP/2</strong>：启用 HTTP/2 多路复用，并行加载资源</li>
<li><strong>字体优化</strong>：使用 <code>font-display: swap</code> 避免字体阻塞渲染</li>
<li><strong>图片格式</strong>：使用 WebP/AVIF 等现代格式</li>
</ol>
<p>后续有空再继续折腾。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://gohugo.io/getting-started/configuration/#configure-minify">Hugo 官方文档 - Configure Minify</a></li>
<li><a href="https://gohugo.io/content-management/image-processing/">Hugo 官方文档 - Image Processing</a></li>
<li><a href="https://web.dev/browser-level-image-lazy-loading/">Web.dev - Browser-level image lazy loading</a></li>
<li><a href="https://web.dev/optimize-cls/">Web.dev - Optimize Cumulative Layout Shift</a></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
