跳转到内容
TakatoBlog TakatoBlog
返回

Astro 快速上手指南

编辑文章

专为熟悉 React/Vue/Next/Nuxt 的开发者准备

目录

一、Astro 核心概念(对比你熟悉的框架)

Astro 是什么?

Astro 是一个内容优先的静态站点生成器,类似于 Next.js 的 SSG 模式,但更专注于零 JavaScript 运行时

核心特点:

与 Next.js/Nuxt 的对比

特性Next.jsNuxtAstro
默认渲染SSR/SSGSSR/SSG静态 HTML
客户端 JS默认发送默认发送默认不发送
框架支持ReactVue所有框架
性能极快(零 JS)
适用场景全栈应用全栈应用内容网站、博客

Astro 组件语法

Astro 组件使用 .astro 扩展名,语法类似 JSX,但更简单:

---
// 组件脚本部分(类似 Vue 的 <script>)
// 只在构建时运行,不会发送到客户端
const name = "Astro";
const items = [1, 2, 3];
---

<!-- 模板部分(类似 Vue 的 <template>) -->
<div>
  <h1>Hello {name}!</h1>
  <ul>
    {items.map(item => <li>{item}</li>)}
  </ul>
</div>

<style>
  /* 样式部分(类似 Vue 的 <style>) */
  /* 默认是 scoped 的 */
  h1 {
    color: blue;
  }
</style>

关键点:

客户端组件(Client Components)

如果需要交互性,使用 client:* 指令:

---
import MyReactComponent from "./MyReactComponent.jsx";
---

<!-- 默认:不发送 JS -->
<MyReactComponent />

<!-- 激活为客户端组件 -->
<MyReactComponent client:load />
<!-- 立即加载 -->
<MyReactComponent client:idle />
<!-- 浏览器空闲时加载 -->
<MyReactComponent client:visible />
<!-- 进入视口时加载 -->
<MyReactComponent client:only="react" />
<!-- 仅客户端渲染 -->

类比 Next.js:


二、项目结构详解

根目录文件

takato-blog/
├── astro.config.ts          # Astro 配置文件(类似 next.config.js)
├── package.json              # 项目依赖
├── tsconfig.json            # TypeScript 配置
├── public/                   # 静态资源(直接复制到 dist/)
└── src/                      # 源代码目录

astro.config.ts - 核心配置文件

export default defineConfig({
  site: SITE.website,              // 部署域名
  integrations: [                 // 集成插件(类似 Next.js 插件)
    sitemap(),                     // 自动生成 sitemap
  ],
  markdown: {                     // Markdown 配置
    remarkPlugins: [...],          // Markdown 插件
    shikiConfig: {...},            // 代码高亮配置
  },
  vite: {                         // Vite 配置(Astro 基于 Vite)
    plugins: [tailwindcss()],
  },
});

类比:

src/ 目录结构

src/
├── assets/              # 需要处理的资源(图片、字体等)
│   ├── icons/          # SVG 图标
│   └── images/         # 图片资源
├── components/          # Astro 组件(类似 React/Vue 组件)
│   ├── Card.astro
│   ├── Header.astro
│   └── Footer.astro
├── layouts/            # 布局组件(类似 Next.js 的 _app.js)
│   ├── Layout.astro    # 基础布局(HTML 结构)
│   └── PostDetails.astro
├── pages/              # 路由页面(类似 Next.js 的 pages/)
│   ├── index.astro     # 首页 (/)
│   ├── about.md        # 关于页 (/about)
│   ├── posts/
│   │   └── [...slug]/  # 动态路由(类似 [...slug].jsx)
│   └── tags/
│       └── [tag]/      # 动态路由参数
├── data/               # 内容数据(Markdown 文件)
│   └── blog/          # 博客文章
├── styles/            # 全局样式
├── utils/             # 工具函数
├── config.ts          # 站点配置
└── content.config.ts   # 内容集合配置

三、关键路径文件详解

src/pages/ - 路由系统

类比 Next.js:

关键文件:

src/pages/index.astro - 首页

---
// 构建时执行,获取所有文章
const posts = await getCollection("blog");
const sortedPosts = getSortedPosts(posts);
---

<Layout>
  <Header />
  <main>
    {sortedPosts.map(post => <Card {...post} />)}
  </main>
  <Footer />
</Layout>

src/pages/posts/[...slug]/index.astro - 动态路由

---
// 类似 Next.js 的 getStaticPaths
export async function getStaticPaths() {
  const posts = await getCollection("blog");
  return posts.map(post => ({
    params: { slug: getPath(post.id) },
    props: { post },
  }));
}

const { post } = Astro.props; // 类似 Next.js 的 props
---

<PostDetails post={post} />

关键点:

src/layouts/ - 布局系统

类比 Next.js:

src/layouts/Layout.astro

---
// Props 定义(类似 TypeScript interface)
type Props = {
  title?: string;
  description?: string;
};

const { title, description } = Astro.props;
---

<!doctype html>
<html>
  <head>
    <title>{title}</title>
    <meta name="description" content={description} />
  </head>
  <body>
    <slot />
    <!-- 类似 Vue 的 <slot> 或 React 的 {children} -->
  </body>
</html>

关键点:

src/components/ - 组件系统

类比 React/Vue:

src/components/Card.astro 示例

---
// Props 类型定义
type Props = {
  variant?: "h2" | "h3";
} & CollectionEntry<"blog">;

const { variant = "h2", id, data } = Astro.props;
const { title, description } = data;
---

<li>
  <a href={getPath(id)}>
    <h2>{title}</h2>
  </a>
  <p>{description}</p>
</li>

关键点:

src/data/blog/ - 内容集合(Content Collections)

类比:

Markdown 文件结构

---
title: 文章标题
author: 作者
pubDatetime: 2024-01-01T00:00:00Z
draft: false
tags: [JavaScript, React]
description: 文章描述
---

# 文章内容

这里是 Markdown 内容...

关键点:

src/content.config.ts - 内容集合配置

import { defineCollection, z } from "astro:content";

const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
  schema: z.object({
    title: z.string(),
    pubDatetime: z.date(),
    draft: z.boolean().optional(),
    tags: z.array(z.string()),
  }),
});

export const collections = { blog };

类比:

src/config.ts - 站点配置

export const SITE = {
  website: "https://example.com",
  author: "Your Name",
  title: "My Blog",
  postPerIndex: 4,
  // ...
} as const;

类比:

src/utils/ - 工具函数

常用工具函数:

类比:


四、开发工作流

启动开发服务器

npm run dev
# 或
pnpm dev

类比:

构建生产版本

npm run build

类比:

预览生产构建

npm run preview

类比:


五、常见开发场景

场景 1:创建新页面

创建 src/pages/about.astro

---
import Layout from "@/layouts/Layout.astro";
---

<Layout title="关于我">
  <h1>关于我</h1>
  <p>这是我的介绍...</p>
</Layout>

路由自动生成: /about

场景 2:创建新组件

创建 src/components/Button.astro

---
type Props = {
  href: string;
  children: string;
};

const { href, children } = Astro.props;
---

<a href={href} class="btn">
  {children}
</a>

<style>
  .btn {
    padding: 0.5rem 1rem;
    background: blue;
    color: white;
  }
</style>

使用组件:

---
import Button from "@/components/Button.astro";
---

<Button href="/about">关于我</Button>

场景 3:使用 React/Vue 组件

安装集成:

npx astro add react
# 或
npx astro add vue

使用:

---
import MyReactComponent from "./MyReactComponent.jsx";
---

<MyReactComponent client:load />

场景 4:获取内容集合数据

---
import { getCollection } from "astro:content";

// 获取所有文章
const posts = await getCollection("blog");

// 过滤草稿
const publishedPosts = await getCollection("blog", ({ data }) => !data.draft);

// 获取单篇文章
const post = await getEntry("blog", "post-id");
---

<ul>
  {
    publishedPosts.map(post => (
      <li>
        <a href={`/posts/${post.slug}`}>{post.data.title}</a>
      </li>
    ))
  }
</ul>

场景 5:动态路由

src/pages/posts/[id].astro

---
export async function getStaticPaths() {
  const posts = await getCollection("blog");
  return posts.map(post => ({
    params: { id: post.id },
    props: { post },
  }));
}

const { post } = Astro.props;
---

<Layout>
  <article>
    <h1>{post.data.title}</h1>
    <div set:html={post.body} />
  </article>
</Layout>

六、关键概念速查

Astro 全局对象

指令(Directives)

内容集合 API


七、学习资源

  1. 官方文档https://docs.astro.build
  2. API 参考https://docs.astro.build/en/reference/api-reference/
  3. 集成列表https://docs.astro.build/en/guides/integrations-guide/

八、快速上手清单


祝你开发愉快! 🚀

如有问题,可以查看项目中的示例文件或 Astro 官方文档。


编辑文章
Share this post on:

上一篇文章
项目结构详细说明