我构建了一个极速网站,月费为 $0 — 以下是完整技术栈(Hugo + Cloudflare Pages)
Source: Dev.to
你懂那种感觉。你安装缓存插件来修复慢速的 WordPress 站点。缓存插件需要一个配置插件。配置插件又和你的 SEO 插件冲突。现在你有三个插件在糟糕地完成同一件事,而你的 Core Web Vitals 分数看起来像是参与奖。
我受够了,于是从头开始重建了一切。结果是 laserengraverexpert.com — 一个激光雕刻机评测站点,运行在 Hugo 0.147.0 上,托管在 Cloudflare Pages,部署时间约为 ~25 秒,托管费用恰好是 $0 / month。
本文是完整的技术拆解:技术栈、配置、思路、权衡,以及我最初犯的一个错误导致了两天的调试。无论你在构建内容站点、联盟站点、文档站点,还是任何不需要数据库的项目——这个技术栈都值得认真考虑。
全栈概览
| 层 | 工具 / 成本 |
|---|---|
| 静态站点生成器 | Hugo 0.147.0 — 免费 |
| 托管 + CDN | Cloudflare Pages(免费层) — $0 |
| 分析 | Cloudflare Web Analytics — $0 |
| 构建配置 | wrangler.toml |
| 图像 | WebP(从源文件转换) — 免费 |
| 域名 | Namecheap — ≈ $10 / year |
| 数据库 | 无 |
| 服务器运行时 | 无 |
总基础设施费用: ≈ $10 / year(域名)。其他全部免费。
为什么不选常规候选?
Next.js
生态系统很棒,我也会 React。
但 Next.js 是为应用构建的。虽然可以静态导出,但每当你想要纯静态输出时,就会与框架“斗争”。构建产出比内容站点所需的更重,而且 Vercel 的免费层有带宽上限,流量一大就会受到影响。
Gatsby
在 2019 年它是正确的答案。
GraphQL 数据层很强大,但这是我不需要的额外负担。大型站点的构建时间会变得异常缓慢,生态也出现了碎片化。我不想把生产站点押在它上面。
Eleventy (11ty)
最接近的竞争者。
Eleventy 确实出色:全程使用 JavaScript,零意见,极具可组合性。如果你已经深耕 Node 生态并且想要最大灵活性,Eleventy 是你的选择。我差点就用了它。
为什么 Hugo 获胜
速度——不是网站加载速度,而是构建速度。
Hugo 的构建时间以 毫秒 为单位。我的当前站点,包含所有内容,构建时间 不到 400 毫秒。而使用 Eleventy 时,同等站点的构建时间在 3–5 秒 左右。当你在迭代布局和模板时,这种差异在开发过程中非常重要。
- Hugo 是一个 单一二进制文件 —— 没有
node_modules,没有package.json,没有依赖地狱。 - 在 Cloudflare Pages 上,这意味着构建环境 干净、可复现且快速。
权衡:Go 模板
Hugo 的模板语法有一些锋利的边缘——管道语法、.context 作用域以及局部渲染模型会让人卡壳。我不会假装学习曲线不存在。它确实存在。但它是值得的。
Cloudflare Pages 设置
-
注册 一个 Cloudflare 账户(如果你还没有的话)。
-
连接 你的 GitHub 仓库。这是核心,但有几项细节值得了解。
- 免费层提供 每月 500 次构建。对于发布频率合理的内容站点,你永远不会达到上限。我每月从未超过 30 次。
- 每次推送到
main都会触发构建和部署。每个拉取请求都会获得一个带有独立 URL 的 预览部署——非常适合在合并前审查更改。
wrangler.toml
[build]
command = "hugo --minify"
publish = "public"
[build.environment]
HUGO_VERSION = "0.147.0"
[[headers]]
for = "/*"
[headers.values]
X-Content-Type-Options = "nosniff"
X-Frame-Options = "DENY"
Referrer-Policy = "strict-origin-when-cross-origin"
Permissions-Policy = "camera=(), microphone=(), geolocation=()"
Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' static.cloudflareinsights.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' cloudflareinsights.com; frame-ancestors 'none';"
[[headers]]
for = "/css/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/js/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/img/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
缓存策略 — 为什么不可变缓存是游戏规则改变者
max-age=31536000 告诉浏览器缓存文件 一年。immutable 告诉浏览器甚至不必重新验证——如果文件在缓存中,直接使用,无需网络往返。
如果你更新了 CSS 会怎样?
你使用 内容寻址文件名。Hugo 的资产管道会对文件进行指纹处理——在文件名中加入内容的哈希:
{{ $css := resources.Get "css/main.css" | minify | fingerprint }}
当文件更改时,哈希会变化,生成新的文件名,浏览器会获取最新的资源。
WebP 图像处理流程
WebP 文件在相同视觉质量下比 JPEG 小 60–80 %。
一个 400 KB 的产品 JPEG 可以变成 90 KB 的 WebP。30 张图片相乘,你每次访问就能节省数兆字节。
{{ $original := resources.Get "images/product.jpg" }}
{{ $webp := $original.Resize "800x" | images.Convert "webp" }}
[Image: Product]
构建流水线
- Push 到 GitHub。
- Cloudflare Pages 运行
hugo --minify。 - Hugo 在 ~400 ms 内生成静态站点。
- 构建在 ≈ 25 seconds(端到端,包括网络延迟)内完成。
- 在根目录生成
index.json—— 可直接用于客户端搜索(Fuse.js、Pagefind),无需后续构建更改。
性能 — 预期表现
| 指标 | 预期值 |
|---|---|
| Lighthouse Performance | 95–100 |
| Time‑to‑First‑Byte (TTFB) | — |
包括激光雕刻机对比指南。如果想看看该技术栈在实际中的表现,请使用 PageSpeed Insights 进行测试。
Marcus Webb 撰写关于激光雕刻机以及他围绕它们构建的工具,详见 .