
关于
使用 Astro 构建内容优先的网站 — 默认零 JS、Islands 架构、多框架组件和 Markdown/MDX 支持。
name: astro description: "使用 Astro 构建以内容为核心的网站 — 默认零 JS、岛屿架构、多框架组件以及 Markdown/MDX 支持。" category: frontend risk: safe source: community date_added: "2026-03-18" author: suhaibjanjua tags: [astro, ssg, ssr, islands, content, markdown, mdx, performance] tools: [claude, cursor, gemini]
Astro Web 框架
概述
Astro 是一个专为内容丰富的网站设计的 Web 框架 — 博客、文档、作品集、营销网站和电商网站。其核心创新是岛屿架构:默认情况下,Astro 不向浏览器发送任何 JavaScript。交互式组件作为独立的"岛屿"被选择性地水合。Astro 支持在同一项目中同时使用 React、Vue、Svelte、Solid 和其他 UI 框架,让你可以为每个组件选择最合适的工具。
何时使用此技能
- 构建博客、文档站点、营销页面或作品集时使用
- 性能和 Core Web Vitals 是首要优先级时使用
- 项目以 Markdown 或 MDX 文件为主的内容密集型项目时使用
- 需要 SSG(静态)输出并可选 SSR 用于动态路由时使用
- 用户询问
.astro文件、Astro.props、内容集合或client:指令时使用
工作原理
步骤 1:项目设置
npm create astro@latest my-site
cd my-site
npm install
npm run dev
根据需要添加集成:
npx astro add tailwind # Tailwind CSS
npx astro add react # React 组件支持
npx astro add mdx # MDX 支持
npx astro add sitemap # 自动 sitemap.xml
npx astro add vercel # Vercel SSR 适配器
项目结构:
src/
pages/ ← 基于文件的路由(.astro、.md、.mdx)
layouts/ ← 可复用的页面外壳
components/ ← UI 组件(.astro、.tsx、.vue 等)
content/ ← 类型安全的内容集合(Markdown/MDX)
styles/ ← 全局 CSS
public/ ← 静态资源(原样复制)
astro.config.mjs ← 框架配置
步骤 2:Astro 组件语法
.astro 文件顶部有一个代码围栏(仅服务端),下方是模板:
---
// src/components/Card.astro
// 此代码块仅在服务端运行 — 永远不会在浏览器中执行
interface Props {
title: string;
href: string;
description: string;
}
const { title, href, description } = Astro.props;
---
<article class="card">
<h2><a href={href}>{title}</a></h2>
<p>{description}</p>
</article>
<style>
/* 自动限定作用域到此组件 */
.card { border: 1px solid #eee; padding: 1rem; }
</style>
步骤 3:基于文件的页面和路由
src/pages/index.astro → /
src/pages/about.astro → /about
src/pages/blog/[slug].astro → /blog/:slug(动态)
src/pages/blog/[...path].astro → /blog/*(通配)
使用 getStaticPaths 的动态路由:
---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<h1>{post.data.title}</h1>
<Content />
步骤 4:内容集合
内容集合为你提供对 Markdown 和 MDX 文件的类型安全访问:
// src/content/config.ts
import { z, defineCollection } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
const posts = (await getCollection('blog'))
.filter(p => !p.data.draft)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
---
<ul>
{posts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<time>{post.data.date.toLocaleDateString()}</time>
</li>
))}
</ul>
步骤 5:岛屿 — 选择性水合
默认情况下,UI 框架组件渲染为静态 HTML,不包含 JS。使用 client: 指令进行水合:
---
import Counter from '../components/Counter.tsx'; // React 组件
import VideoPlayer from '../components/VideoPlayer.svelte';
---
<!-- 静态 HTML — 不向浏览器发送 JavaScript -->
<Counter initialCount={0} />
<!-- 页面加载时立即水合 -->
<Counter initialCount={0} client:load />
<!-- 组件滚动到视口时水合 -->
<VideoPlayer src="/demo.mp4" client:visible />
<!-- 仅在浏览器空闲时水合 -->
<Analytics client:idle />
<!-- 仅在特定媒体查询匹配时水合 -->
<MobileMenu client:media="(max-width: 768px)" />
步骤 6:布局
---
// src/layouts/BaseLayout.astro
interface Props {
title: string;
description?: string;
}
const { title, description = 'My Astro Site' } = Astro.props;
---
<html lang="zh">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="description" content={description} />
<title>{title}</title>
</head>
<body>
<nav><!-- 导航 --></nav>
<main>
<slot /> <!-- 页面内容插入此处 -->
</main>
<footer><!-- 页脚 --></footer>
</body>
</html>
兼容工具
Claude CodeCursor
标签
前端开发