搭博客选框架的经历:Astro、Hugo、Next.js

3909 字
20 分钟
搭博客选框架的经历:Astro、Hugo、Next.js

概述#

静态博客是每个开发者都想过要搭的东西。2026 年,选择不是变少了,而是更多了——每个方案都有自己的生态和拥趸。

我在搭 SelfStack 这个博客时把三个主流方案都试了一遍(Hugo 最早、Next.js 过渡、最终选了 Astro),这篇文章从实际体验出发做一次深度对比。不列参数表格充字数,只说真实使用中的感受和决策依据。


一、三个方案的核心定位#

Astro — 内容优先的静态站点框架#

Astro 的口号是”内容优先的 Web 框架”。它的核心理念是岛屿架构(Islands Architecture)——页面大部分是纯静态 HTML,只在需要交互的地方加载 JS。

  • 语言:TypeScript + JSX(.astro 文件)
  • 模板:.astro 组件、支持 MDX
  • 构建方式:静态站点生成(SSG)+ 服务端渲染(SSR)
  • 发布:2021 年,当前稳定版 6.x
  • 维护方:Astro 团队

Astro 是三者中最年轻、最专注”内容网站”这个场景的框架。

Hugo — 老牌经典,快如闪电#

Hugo 是用 Go 语言写的静态站点生成器,以构建速度闻名。它的理念是”一个二进制搞定一切”——不需要 Node.js、不需要依赖管理。

  • 语言:Go(模板语言是 Go Templates)
  • 模板:Go Templates + .html
  • 构建方式:纯静态站点生成
  • 发布:2013 年,当前稳定版 0.14x
  • 维护方:Bjørn Erik Pedersen 及社区

Hugo 是三者中年龄最大的,也是最”纯粹”的静态站点生成器——它只做静态站点,不做别的。

Next.js — React 生态的全栈框架#

Next.js 是 Vercel 维护的全栈 React 框架。虽然它不是一个专门的”博客框架”,但它的 SSG 能力 + React 生态使其成为搭建博客的常见选择。

  • 语言:TypeScript + React(JSX)
  • 模板:React 组件
  • 构建方式:SSG + SSR + ISR(增量静态再生)
  • 发布:2016 年,当前稳定版 15.x
  • 维护方:Vercel

Next.js 是三者中最重的——它什么都能做,但如果你的目标只是”搭个博客”,它的能力是过剩的。

一句话定位#

Hugo → "一碗面":简单直接,吃就完事
Astro → "套餐":搭配灵活,体验舒适
Next.js → "自助餐":什么都有,但需要你自己搭配

二、架构设计对比#

2.1 构建原理#

Hugo 的原理最直接:读取 Markdown + 模板 → 直接输出 HTML。没有虚拟 DOM、没有水合(hydration)、没有任何 JavaScript 运行时。

Markdown → Hugo → HTML(纯静态)
模板 → CSS/JS(文件复制)

Astro 的原理是在构建时把 .astro 组件渲染成 HTML,页面中交互部分(Islands)按需加载对应的 JS。

.astro → 服务端渲染 → HTML + 部分 CSS
.md → └─ 交互组件(.svelte/.react/.vue) → 按需 JS

Next.js 通过 getStaticProps / generateStaticParams 在构建时生成静态页面,但它仍然保留了一个 Node.js 运行时用于 SSR 和 API Routes。

React 组件 → 构建时 SSG → HTML + JS bundle
.md/.mdx → └─ API Routes(Node.js 运行时)
└─ ISR(按需重新生成)

2.2 内容管理#

# 三者都支持的标准 frontmatter
---
title: Hello World
date: 2026-06-09
tags: [blog]
---
维度HugoAstroNext.js
内容格式Markdown(.md).md / .mdx.md / .mdx
内容目录content/ 目录src/content/(Content Collections)自己组织
内容查询全局变量(.Site.RegularPages)Astro Content Collections API自己写逻辑
分类/标签内建支持需自己定义 schema需自己写
多语言内建 i18n 系统需要自己做或集成库需要自己做
图片优化需要 shortcodeImage 组件next/image

Astro 的 Content Collections 是三者中做得最好的——类型安全、结构化校验、自动生成 API:

---
// Astro Content Collections —— 类型安全
import { getCollection } from 'astro:content';
const posts = await getCollection('posts');
// posts 的类型根据 content.config.ts 自动推断
// 有发布时间、标签等字段约束
// 直接写错字段名 IDE 会报错
---
{posts.map(post => <a href={post.slug}>{post.data.title}</a>)}

Hugo 的内容查询依赖模板层面的全局变量,没有类型安全:

{{ range .Site.RegularPages }}
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
{{ end }}
<!-- Hugo 不会检查 .Title 是否存在,模板运行时报错 -->

2.3 模板系统#

Hugo 的 Go Templates 学习曲线最高:

{{/* Hugo Go Templates */}}
{{ define "main" }}
<div class="posts">
{{ range (.Paginate .Site.RegularPages).Pages }}
<article>
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
<time>{{ .Date.Format "2006-01-02" }}</time>
{{ .Summary }}
</article>
{{ end }}
{{ template "_internal/pagination.html" . }}
</div>
{{ end }}

Astro 的 .astro 文件语法最自然(JSX-like):

---
// Astro 组件
import Layout from '../layouts/Layout.astro';
import { getCollection } from 'astro:content';
const posts = await getCollection('posts');
const { pagination } = Astro.props;
---
<Layout title="博客列表">
<div class="posts">
{pagination.data.map(post => (
<article>
<h2><a href={`/${post.slug}/`}>{post.data.title}</a></h2>
<time>{post.data.published.toLocaleDateString()}</time>
<p>{post.data.description}</p>
</article>
))}
</div>
</Layout>

Next.js 就是标准 React 组件:

// Next.js App Router
import Link from 'next/link';
interface Post {
slug: string;
title: string;
date: string;
}
export default async function BlogList() {
const posts: Post[] = await getPosts();
return (
<div className="posts">
{posts.map(post => (
<article key={post.slug}>
<h2><Link href={`/${post.slug}/`}>{post.title}</Link></h2>
<time>{post.date}</time>
</article>
))}
</div>
);
}

2.4 项目结构对比#

Hugo 的项目结构有固定的约定,你的内容必须严格按约定放:

my-hugo-site/
├── archetypes/ # 内容模板
├── content/ # Markdown 内容
│ └── posts/
├── layouts/ # 模板
│ ├── _default/
│ ├── partials/
│ └── index.html
├── static/ # 静态资源
├── assets/ # 需要构建的资源
├── config.toml # 配置文件
└── themes/ # 主题

Astro 的模式自由度高,但社区有惯例:

my-astro-site/
├── src/
│ ├── components/ # UI 组件
│ ├── content/ # Content Collections
│ │ └── posts/
│ ├── layouts/ # 页面布局
│ ├── pages/ # 路由页面
│ ├── config/ # 站点配置
│ └── styles/ # 全局样式
├── public/ # 静态资源
├── astro.config.mjs # Astro 配置
└── package.json

Next.js 强制约定文件系统路由(App Router):

my-next-site/
├── app/
│ ├── layout.tsx # 根布局
│ ├── page.tsx # 首页
│ ├── posts/
│ │ ├── [slug]/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ └── globals.css
├── content/ # 自己组织的内容目录
├── components/ # React 组件
├── lib/ # 工具函数
├── next.config.ts # Next.js 配置
└── package.json

三、开发体验对比#

3.1 上手难度#

Hugo 的上手曲线最陡:Go Templates 语法特别,配置项多(config.toml 可以写几百行),主题系统有自己的约定。如果你的目标是”改主题不说话”,Hugo 可以很快;如果你要自己写模板,需要学的东西不少。

Astro 的上手曲线最平缓:.astro 文件就是 HTML + JS 混合,和写 React/HTML 没有本质区别。Content Collections 开箱即用,安装即有一个完整可用的博客脚手架。

Next.js 的上手看 React 基础:如果你已经熟悉 React,上手 Next.js 没什么问题。如果不熟悉 React,需要先学 React 再学 Next.js。App Router 的 Server Component 模型和传统 React 差异很大,即使有 React 经验也需要适应期。

3.2 热更新速度#

Hugo 的 hugo server 冷启动极快(毫秒级),修改后即时刷新,没有 JS bundle 的过程。这是 Go 语言编译速度的天然优势。

Astro 的 astro dev 也很快(秒级启动),HMR 体验顺滑。修改 .astro 文件只更新对应页面,不会全量重建。

Next.js 的 next dev 启动较慢(5-15 秒,取决于项目大小),修改后的 Turbopack(如果启用)做了大量优化,但速度仍然不如前两者。

冷启动速度:Hugo >>> Astro > Next.js
热更新速度:Hugo > Astro >> Next.js

3.3 内容编写体验#

写博客的核心体验是”写 Markdown → 刷新看到效果”。

Hugo 支持标准的 Markdown,但扩展功能(如表格、提示框、代码高亮)需要 shortcode。

Astro 的 Markdown 体验最好——原生支持 MDX,可以在 Markdown 中直接使用组件:

---
title: 用 MDX 写文章
---
这是一篇普通的 Markdown 文章。
<Note type="tip">
这是 MDX 组件,直接在 Markdown 中使用
</Note>
<Gallery>
<Image src="/photo1.jpg" alt="照片1" />
<Image src="/photo2.jpg" alt="照片2" />
</Gallery>

Next.js 也支持 MDX,但需要额外的配置(@next/mdx),配置起来比 Astro 复杂一些。

3.4 生态与插件#

Hugo 的”插件”体系是 shortcode + 模板片段。生态集中在主题层面,有丰富的主题市场,但功能扩展能力有限。

Astro 的集成体系成熟:官方集成覆盖了最常用的场景,社区集成也在快速增长。

Astro 的集成是首屈一指的——你想要的功能基本都有官方或社区集成。

Next.js 的”生态”其实就是 React 生态。你能找到的 npm 包最多,但每个都需要自己集成配置。

生态丰富度:Next.js(Node.js 生态系统)> Astro >> Hugo
集成开箱度:Astro > Hugo > Next.js

3.5 构建性能#

Hugo 在这个维度是碾压级的。

以 1000 篇文章的博客为例:

全量构建时间:
Hugo: < 1 秒
Astro: ~5-10 秒
Next.js: ~30-60 秒(纯 SSG)

Hugo 的构建速度是 Go 语言级别的——它不依赖任何 JS 运行时,直接解析模板和 Markdown 输出 HTML。如果你有上万篇文章,Hugo 是唯一能保持秒级构建的方案。

Astro 的构建速度在几百篇文章的范围内完全可接受(几秒到十几秒),已经很快了。

Next.js 的纯静态构建速度一般,而且随着页面数量增加,构建时间线性增长。如果使用增量静态再生(ISR),可以解决首次构建慢的问题,但又引入了运行时依赖。


四、部署与运维#

4.1 输出产物#

Hugo 输出纯静态文件——一个完全自包含的目录:

hugo --minify
# 输出到 ./public/
public/
├── index.html
├── posts/
├── tags/
├── css/
├── js/
└── ...
# 直接扔到任何静态文件服务器即可

Astro 同样输出纯静态文件(如果使用 SSG 模式):

npm run build
# 输出到 ./dist/
dist/
├── index.html
├── posts/
├── _astro/ # 资源文件(哈希命名)
└── ...
# 扔到任何静态服务器

Next.js 输出两种东西:静态文件 + Node.js 运行时(如果使用 API Routes 或 ISR):

npm run build
# 输出到 .next/
.next/
├── server/ # 服务端代码
├── static/ # 静态资源
└── ...
# 需要一个 Node.js 运行时(Vercel / 自己的服务器)

4.2 托管选项#

平台HugoAstroNext.js
GitHub Pages✅ 完美✅ 完美⚠️ 需要适配
Cloudflare Pages✅ 完美✅ 完美⚠️ 有限支持
Netlify✅ 完美✅ 完美✅ 完美
Vercel✅ 完美✅ 完美✅ 原生最优
自托管 Nginx✅ 扔文件✅ 扔文件⚠️ 需要 Node.js
对象存储(S3/R2)✅ 直接上传✅ 直接上传❌ 不支持

Hugo 和 Astro 的纯静态输出可以部署在任何静态文件托管上——这是它们最大的运维优势。

Next.js 的部署选择受限:Vercel 是原生平台,自托管需要 Node.js 环境,Cloudflare Pages 的支持不完整。

4.3 运维复杂度#

运维复杂度:Next.js > Astro ≈ Hugo

Hugo 和 Astro 的运维基本上就是”上传文件”四个字。CI/CD 流程简单到极致:

# Hugo/Astro 的典型 CI
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install && npm run build # Hugo 甚至不需要 npm install
- run: npx pagefind --site dist # Astro 可选
- uses: cloudflare/pages-action@v1 # 部署到 Cloudflare

Next.js 的 CI/CD 相对复杂,尤其是自托管场景(需要 pm2、反向代理、环境变量管理等)。


五、实际使用体验#

5.1 Hugo —— 我在 2023 年的体验#

最早我用的就是 Hugo。它的构建速度确实让人印象深刻——上千篇文章一秒不到就构建完成。主题市场丰富,找到一个合适的主题就能很快上线。

但真正开始写内容后,痛点就来了:

  • 想改一个细小的布局,需要学 Go Templates 的语法,文档难啃
  • 想加一个功能(比如图片懒加载),要么找 shortcode 要么自己写
  • 主题的”自定义”路径不直观,经常需要 override 整个模板文件
  • 非开发者使用难度大 —— 如果只写内容不碰模板,Hugo 可以。但只要你需要定制,就要学一套和主流前端完全不同的技术栈。

5.2 Next.js —— 我在 2024 年的尝试#

作为一个前端开发者,Next.js 是我的自然选择。React 生态熟悉、组件复用方便、Vercel 部署丝滑。

但用了一段时间后也发现了问题:

  • 我只想写个博客,但 Next.js 给我的是一整套全栈框架
  • App Router 的学习曲线比预期的陡 —— Server Component、RSC、'use client' 的边界需要理解
  • 构建速度慢,100 篇文章的站点构建要 30 秒以上
  • 部署锁定 Vercel —— 自托管太麻烦
  • “能力过剩” —— 博客不需要 ISR、不需要 API Routes、不需要中间件,但这些都在 bundle 里

5.3 Astro —— 最终选择#

最后选 Astro 的原因很简单:它在 Hugo 和 Next.js 之间找到了最佳平衡点

  • 开发体验好:写 .astro 文件就像写 HTML + JS,零学习成本
  • 内容管理强大:Content Collections 的类型安全让我这种重视可靠性的人很安心
  • 组件生态灵活:可以在 Astro 中用 React/Svelte/Vue 组件,不需要选边站
  • 性能优秀:岛屿架构让页面几乎不加载 JS,速度快
  • 部署自由:纯静态输出,扔到任何地方都能跑
  • 集成丰富:MDX、Tailwind、Sitemap、RSS 全部官方集成,一行配置搞定

SelfStack 这个博客就是用 Astro + Svelte + Tailwind 搭建的,目前体验非常满意。

5.4 三者的典型用户画像#

Hugo 适合谁:
├── 非前端开发者(后端/运维/Go 开发者)
├── 大内容站点(数千篇以上)
├── 不想碰 Node.js 生态的人
└── 只要博客能用就行,不想折腾
Astro 适合谁:
├── 前端开发者
├── 内容创作者 + 开发者混合身份
├── 对页面性能和 JS 体积有要求的人
├── 想要灵活性和生态(React/Vue/Svelte 混用)
└── 需要 Content Collections 类型安全的人
Next.js 适合谁:
├── React 重度用户
├── 需要 API Routes / 全栈能力的站点
├── 电商/应用类网站(不只是博客)
└── 准备用 Vercel 部署的人

六、选型建议#

6.1 决策树#

Q: 你有多少篇文章?
├── < 10 篇:随便选,哪个学得快用哪个
├── 10 ~ 500 篇
│ ├── 会前端 → Astro
│ └── 不会前端 → Hugo
│ └── 必须用 React → Next.js
├── 500 ~ 5000 篇
│ ├── 性能优先 → Hugo
│ └── 体验优先 → Astro
└── > 5000 篇 → Hugo

6.2 如果你是初学者#

想做博客 → 会编程
├── 会前端(HTML/CSS/JS)→ Astro(最推荐)
├── 会 Go 或不想学前端 → Hugo
└── 只会 React → Next.js
想做博客 → 不会编程
├── 完全不会写代码 → WordPress / Notion 更合适
└── 愿意学一点 → Astro + 主题模板

6.3 我的个人建议#

Astro 是 2026 年搭建内容类站点(博客、文档站、公司官网)的最佳选择。它在三个方案中取得了最好的平衡:

  • 比 Hugo 更现代、更好扩展、开发体验更好
  • 比 Next.js 更专注、更轻量、部署更自由
  • 两边的优点它都占了,两边的缺点它都避开了

如果你已经在用 Hugo 而且用得很顺手,没有迁移的必要。如果你已经在用 Next.js 而且需要它的全栈能力,也没必要换成 Astro。

但如果你正在选型阶段,或者对现有方案不满意——Astro 值得一试


七、快速开始的命令对比#

Terminal window
# Hugo
hugo new site my-blog
cd my-blog
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
echo "theme = 'ananke'" >> hugo.toml
hugo new posts/my-first-post.md
hugo server -D
# Astro
pnpm create astro@latest my-blog -- --template blog
cd my-blog
pnpm dev
# Next.js
npx create-next-app@latest my-blog -- --typescript --tailwind
cd my-blog
# 还需要自己配置 MDX、内容管理等...
npm run dev

从零到能在浏览器看到内容,Astro 只需要两行命令。这不是偶然——Astro 从一开始就是为”内容网站”这个场景设计的。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

搭博客选框架的经历:Astro、Hugo、Next.js
https://selfstack.xiaoxiaotan.online/posts/搭博客选框架/
作者
zicai
发布于
2026-05-30
许可协议
CC BY-NC-SA 4.0
zicai
Hello, I'm zicai.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
11
分类
4
标签
56
总字数
29,238
运行时长
0
最后活动
0 天前

文章目录