FisherHub Blog
← 返回列表 | 开发实践

用 Astro 构建高性能个人博客的完整方案

从零开始:Content Collections、MDX、Tailwind v4、SSR 搜索、RSS、Sitemap——一个博客需要的所有东西

为什么选 Astro 做博客

  1. 零 JS 输出:博客页面不需要 JS,Astro 默认输出纯 HTML
  2. MDX 原生支持:Markdown 里写组件,比纯 MD 灵活
  3. Content Collections:类型安全的内容管理
  4. 构建速度:比 Gatsby/Next.js 快一个数量级

项目结构

blog/
├── src/
│   ├── content/
│   │   └── blog/       # MDX 文章
│   ├── pages/
│   │   ├── index.astro  # 首页
│   │   ├── blog/
│   │   │   ├── index.astro     # 文章列表
│   │   │   └── [...slug].astro # 文章详情
│   │   ├── tags/        # 标签页
│   │   └── search/      # 搜索页
│   ├── layouts/         # 布局
│   ├── components/      # 组件
│   └── styles/          # 全局样式
├── astro.config.mjs
└── package.json

关键配置

// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://blog.fisherhub.cn',
  output: 'server',
  adapter: node({ mode: 'standalone' }),
  integrations: [sitemap()],
});

RSS Feed

// src/pages/rss.xml.ts
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';

export async function GET() {
  const posts = await getCollection('blog', ({ data }) => !data.draft);
  return rss({
    title: 'FisherHub Blog',
    description: '探索者笔记',
    site: 'https://blog.fisherhub.cn',
    items: posts.map(post => ({
      title: post.data.title,
      description: post.data.description,
      pubDate: post.data.pubDate,
      link: `/blog/${post.id.replace(/\.mdx$/, '')}/`,
    })),
  });
}

部署

# Cloudflare Pages
npx wrangler pages deploy dist

# 或 Docker
docker build -t blog .
docker run -p 3000:3000 blog

这套方案足够支撑一个独立开发者的技术博客——性能好、SEO 友好、完全在自己控制之下。