Article
第一章:快速入门
1.1 环境准备与项目创建
| 步骤名称 | 操作细节 | 注意事项 |
|---|---|---|
| 安装 Node.js | 访问 nodejs.org 下载并安装 LTS 版本(≥18.14.1) | Astro 要求 Node.js 18.14.1 或更高版本,建议使用 LTS 版本以确保稳定性 |
| 创建 Astro 项目 | 在终端执行:npm create astro@latest或 pnpm create astro@latest或 yarn create astro | 命令会启动交互式向导,可选择模板(如 “Just the basics”)、是否集成 UI 框架(React/Vue/Svelte 等)、是否启用 TypeScript、是否初始化 Git 仓库等 |
| 进入项目目录 | cd your-project-name | 替换 your-project-name 为实际项目名 |
| 安装依赖 | 自动由创建命令完成,无需手动执行 | 若中断可手动运行 npm install |
| 启动开发服务器 | npm run dev | 默认在 http://localhost:4321 启动,支持热重载 |
1.2 项目结构解析
| 文件/目录 | 说明 | 注意事项 |
|---|---|---|
src/ | 源代码根目录 | 所有页面、组件、静态资源应放在此目录下 |
src/pages/ | 页面路由目录 | 基于文件系统的路由,.astro、.md、.html 等文件会自动映射为页面路径 |
src/layouts/ | 布局组件目录 | 存放可复用的页面布局(如页眉、页脚) |
src/components/ | 组件目录 | 存放 Astro 原生组件或集成的框架组件(如 .jsx, .vue) |
public/ | 静态资源目录 | 放置 favicon.ico、robots.txt 等需直接拷贝到根目录的文件,访问路径为 /filename |
astro.config.mjs | Astro 主配置文件 | 使用 ESM 模块语法,可配置站点元数据、集成、适配器等 |
package.json | 项目依赖与脚本定义 | 包含 dev、build、preview 等脚本命令 |
tsconfig.json(可选) | TypeScript 配置 | 若启用 TS 则自动生成 |
1.3 第一个 Astro 页面
| 方法/概念 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 创建首页 | 在 src/pages/index.astro 中编写 | 定义网站根路径 / 的内容 | ---import Layout from '../layouts/BlogPost.astro';---<Layout><h1>Hello, Astro!</h1><p>Welcome to my first Astro page.</p></Layout> | 文件扩展名为 .astro;Frontmatter(三横线之间)用于导入组件和定义元数据;模板部分使用类似 HTML 的语法 |
| 使用内置组件 | 直接在模板中使用 HTML 标签 | 渲染静态内容 | <main><article><h2>My First Post</h2><p>This is a paragraph.</p></article></main> | Astro 默认不包含 JavaScript,所有内容在构建时静态生成,无客户端 JS 开销 |
| 添加样式 | 在组件内使用 <style> 标签 | 为当前组件添加 CSS | <style>h1 { color: #333; }p { font-size: 16px; }</style> | 样式作用域默认为局部(scoped),不会污染全局 |
| 导航栏 | 在 components/Header.astro 中添加 HeadLink 标签 | 指向其他 Pages 页面 | <HeaderLink href="/">Home</HeaderLink><HeaderLink href="/blog">Blog</HeaderLink><HeaderLink href="/about">About</HeaderLink> | 需要在 index.astro 中使用 <Header/> 才能生效 |
注意:Astro 页面默认为静态 HTML,若需交互功能,需通过
client:指令引入框架组件(将在第四章详述)。
第二章:核心概念
2.1 Astro 文件语法(.astro 组件)
| 语法元素 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| Frontmatter(元数据区) | 使用 --- 包裹的 JavaScript/TypeScript 代码块 | 导入组件、定义变量、执行逻辑 | ---import Layout from '../layouts/Layout.astro';const title = 'My Page';--- | 必须位于文件顶部;支持 ES 模块导入;可包含任意 JS 逻辑(仅在构建时运行) |
| 模板部分(Template) | 类似 HTML 的标记语言 | 定义组件渲染结构 | <Layout><h1>{title}</h1></Layout> | 支持 JSX 风格表达式(如 {variable});不支持原生 <script> 标签(需用 client: 指令或单独 script 标签) |
| 局部样式 | <style> 标签 | 为当前组件定义 CSS | <style>h1 { color: blue; }</style> | 样式默认作用域隔离(scoped),不会影响其他组件;支持嵌套选择器(需预处理器如 Sass) |
| 全局样式 | <style global> | 定义全局生效的 CSS | <style global>body { margin: 0; }</style> | 谨慎使用,避免样式冲突;适用于重置样式或全局主题 |
| 组件属性(Props) | 在 Frontmatter 中解构 Astro.props | 接收父组件传递的数据 | ---const { name } = Astro.props;---<p>Hello, {name}!</p> | 所有 props 通过 Astro.props 对象传入;建议使用 TypeScript 定义类型以增强可维护性 |
| 动态内容生成 | 在模板中使用 JavaScript 表达式 | 渲染动态文本或列表 | <ul>{items.map(item => <li>{item}</li>)}</ul> | 表达式必须返回合法的 Astro 元素或字符串;不能包含异步逻辑(因在构建时执行) |
2.2 群岛架构(Islands Architecture)原理
| 概念名称 | 说明 | 注意事项 |
|---|---|---|
| 群岛架构(Islands Architecture) | 将页面视为由多个独立交互区域(“岛屿”)组成的静态“海洋”。每个岛屿是一个可交互的 UI 组件(如 React/Vue 组件),其余部分为纯静态 HTML。 | 核心目标是减少不必要的 JavaScript 加载,提升性能和 SEO |
| 静态“海洋” | 页面中非交互区域,完全由 Astro 在构建时生成为静态 HTML,无任何客户端 JavaScript。 | 默认行为,无需额外配置;适合内容展示型区域(如文章、导航栏) |
| 交互“岛屿” | 通过集成框架(React/Vue/Svelte 等)实现的可交互组件,仅在需要时加载并激活。 | 必须使用 client: 指令(如 client:load, client:idle)控制加载时机 |
| 零 JavaScript 默认 | Astro 默认不向浏览器发送任何 JavaScript,除非显式引入框架组件。 | 显著降低首屏 JS 体积,提升 Lighthouse 性能评分 |
| 岛屿隔离 | 每个岛屿独立加载和运行,互不影响。即使一个岛屿崩溃,其他岛屿仍正常工作。 | 提高应用健壮性;适合微前端或模块化开发场景 |
2.3 静态站点生成(SSG)与混合渲染
| 渲染模式 | 说明 | 触发方式 | 注意事项 |
|---|---|---|---|
| 静态站点生成(SSG) | 在构建时将所有页面预渲染为静态 HTML 文件,部署后直接由 CDN 提供服务。 | 默认行为;通过 astro build 生成 | 适合内容不变或更新频率低的网站(如博客、文档站);极致性能与 SEO 友好 |
| 静态路径生成(getStaticPaths) | 在 .astro 页面中导出 getStaticPaths() 函数,动态生成多页面(如博客文章列表)。 | 在页面组件 Frontmatter 中定义:export async function getStaticPaths() { return [{ params: { id: '1' } }]; } | 返回对象数组,每个对象的 params 用于填充动态路由参数;函数仅在构建时运行一次 |
| 混合渲染(Hybrid Rendering) | 同一项目中部分页面 SSG,部分页面 SSR(服务端渲染)或 ISR(增量静态再生)。 | 通过适配器(Adapter)启用 SSR,并在页面中使用 export const prerender = false; | 需要部署到支持服务器的平台(如 Node.js 服务器、Deno、Cloudflare Workers);SSR 页面无法在纯静态托管(如 GitHub Pages)上运行 |
| 预渲染开关(prerender) | 控制单个页面是否参与静态生成。 | 在页面组件中设置:export const prerender = true; // 或 false | 默认为 true;设为 false 时该页面将跳过 SSG,需配合 SSR 适配器使用 |
| 输出格式(output) | 在 astro.config.mjs 中配置全局渲染模式。 | astro.config.mjs 中设置:export default defineConfig({ output: 'static' }); // 或 'server' | 'static' 为默认值;'server' 启用 SSR 模式,所有页面默认不预渲染(除非显式设置 prerender: true) |
提示:Astro 的混合渲染能力使其既能构建高性能静态站点,也能处理需要动态数据的页面(如用户仪表盘),实现“按需动态化”。
第三章:页面与路由
3.1 基于文件系统的路由(File-based Routing)
| 概念/操作 | 说明 | 文件路径示例 | 对应 URL 路径 | 注意事项 |
|---|---|---|---|---|
| 基础页面映射 | src/pages/ 目录下的 .astro、.md、.html 等文件自动映射为网站路由 | src/pages/index.astro | / | index.* 文件始终对应根路径 / |
| 嵌套路由 | 子目录结构直接反映在 URL 路径中 | src/pages/about/team.astro | /about/team | 目录名即 URL 路径段,不区分大小写(但建议小写) |
| 多格式支持 | 同一路由可由不同格式文件实现,优先级:.astro > .md > .html | src/pages/contact.astro 和 src/pages/contact.md | /contact(仅 .astro 生效) | 避免同名不同后缀文件共存,以防混淆 |
| 自定义 404 页面 | 创建 src/pages/404.astro | src/pages/404.astro | 任意未匹配路径 | 仅在生产构建(astro build)后生效;开发服务器(dev)默认返回简单 404 |
| 路由忽略规则 | 以下划线 _ 开头的文件或目录不会生成路由 | src/pages/_utils/helper.jssrc/pages/blog/_drafts/post1.astro | 不生成任何路由 | 适用于工具函数、草稿内容等非公开页面 |
3.2 动态路由
| 概念/方法 | 语法/格式 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 动态段定义 | 使用 [param].astro 命名文件 | 捕获 URL 中的动态参数 | src/pages/posts/[id].astro → 匹配 /posts/123 | 参数名 id 可通过 Astro.params.id 获取 |
| 多参数动态路由 | 支持多个 [param] 段 | 处理复合路径 | src/pages/users/[userId]/posts/[postId].astro → /users/5/posts/42 | 每个 [xxx] 对应一个路径段 |
getStaticPaths() 函数 | 在动态页面中导出此函数 | 预生成所有可能的静态页面 | ---export async function getStaticPaths() {return [{ params: { id: '1' } }, { params: { id: '2' } }];}const { id } = Astro.params;--- | 必须返回 { params: { ... } } 对象数组;仅在构建时运行;若未定义,则该页面无法 SSG,需 SSR |
| 可选参数(实验性) | 使用 [...param].astro 或 [[param]].astro | 捕获可变长度路径或可选段 | src/pages/files/[...path].astro → /files/a/b/csrc/pages/blog/[[page]].astro → /blog 或 /blog/2 | [...param] 为“rest”参数,接收数组;[[param]] 为可选单段(存在则捕获,否则为空);需 Astro ≥3.0 |
| 参数类型限制 | 通过命名约定暗示类型(无强制校验) | 提高可读性 | [slug].astro(字符串)[id].astro(数字/字符串) | Astro 不验证参数类型,需在组件内自行处理(如 parseInt(id)) |
3.3 自定义 404 与错误页面
| 页面类型 | 文件路径 | 触发条件 | 代码示例要点 | 注意事项 |
|---|---|---|---|---|
| 自定义 404 页面 | src/pages/404.astro | 用户访问不存在的路径(生产环境) | <h1>Page Not Found</h1><p>The page you're looking for doesn't exist.</p> | 仅在 astro build 后部署时生效;开发服务器(npm run dev)使用内置简单 404 |
| 自定义 500 错误页面(SSR 模式) | src/pages/500.astro | 服务器渲染时发生未捕获异常(需启用 SSR) | <h1>Internal Server Error</h1> | 仅在 output: 'server' 模式下有效;静态站点(output: 'static')无法捕获运行时错误 |
| 全局错误边界(实验性) | 使用中间件或适配器自定义 | 捕获更广泛的错误(如布局崩溃) | 目前 Astro 官方未提供统一错误边界 API,需依赖框架组件(如 React ErrorBoundary) | 建议在集成的 UI 框架组件内部处理交互部分的错误 |
| 开发环境错误提示 | 自动由 Astro Dev Server 提供 | 代码语法错误、导入失败等 | 浏览器显示红色错误面板 | 无需手动配置,仅限开发阶段 |
重要提示:
- 404 页面必须命名为
404.astro(不区分大小写,但推荐小写)。- 若使用动态路由且未通过
getStaticPaths预生成某路径,访问该路径将返回 404(即使文件存在)。- 在混合渲染项目中,SSR 页面的 404 需由服务器逻辑处理,Astro 的
404.astro仅覆盖静态未匹配路径。
第四章:组件与 UI 框架集成
4.1 Astro 原生组件开发
| 概念/方法 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 组件定义 | 创建 .astro 文件,包含 Frontmatter 和模板 | 封装可复用 UI 单元 | ---// MyComponent.astroconst { title } = Astro.props;---<div class="card"><h2>{title}</h2></div> | 组件默认无 JavaScript,纯静态 HTML 输出 |
| 组件导入与使用 | 在其他 .astro 文件中通过 ES import 引入 | 复用组件 | ---import MyComponent from '../components/MyComponent.astro';---<MyComponent title="Hello" /> | 支持命名导入和默认导入;路径相对于当前文件 |
| Props 传递 | 通过 JSX 属性语法传参 | 向子组件传递数据 | <MyComponent title="Welcome" count={5} /> | 所有属性通过 Astro.props 接收;支持字符串、数字、对象、函数(仅构建时可用) |
| Slots(插槽) | 使用 <slot> 标签 | 实现内容分发(类似 Vue/React children) | ---// Card.astro<div class="card"><slot /></div>// 使用:<Card><h2>Title</h2><p>Content</p></Card> | 支持具名插槽(<slot name="header" />),使用时通过 slot="header" 指定 |
| 组件样式作用域 | <style> 标签自动局部作用域 | 避免样式污染 | <style>.card { padding: 1rem; }</style> | 样式仅作用于当前组件;可通过 :global() 选择器突破作用域 |
4.2 集成 React / Vue / Svelte 等框架组件
| 框架 | 集成步骤 | 代码示例(组件定义) | 代码示例(在 Astro 中使用) | 注意事项 |
|---|---|---|---|---|
| React | 1. 安装适配器:npm install @astrojs/react2. 在 astro.config.mjs 中添加:react() | // Counter.jsximport { useState } from 'react';export default function Counter() {const [count, setCount] = useState(0);return <button onClick={() => setCount(c => c+1)}>{count}</button>;} | ---import Counter from '../components/Counter.jsx';---<Counter client:load /> | 必须使用 client: 指令激活;JSX 文件需正确配置 Babel 或 TypeScript |
| Vue | 1. 安装适配器:npm install @astrojs/vue vue2. 在 astro.config.mjs 中添加:vue() | <!-- MyButton.vue --><template><button @click="count++">{{ count }}</button></template><script setup>import { ref } from 'vue';const count = ref(0);</script> | ---import MyButton from '../components/MyButton.vue';---<MyButton client:idle /> | Vue 组件必须以 .vue 扩展名保存;需显式安装 vue 依赖 |
| Svelte | 1. 安装适配器:npm install @astrojs/svelte svelte2. 在 astro.config.mjs 中添加:svelte() | <!-- Clicker.svelte --><script>let count = 0;function increment() { count += 1; }</script><button on:click={increment}>{count}</button> | ---import Clicker from '../components/Clicker.svelte';---<Clicker client:visible /> | 需显式安装 svelte;Svelte 组件响应式更新由其自身运行时处理 |
| Preact | 类似 React,使用 @astrojs/preact | // 类似 React 写法,使用 preact API | ---import { h } from 'preact';import MyPreactComp from './MyPreactComp.jsx';---<MyPreactComp client:load /> | 更轻量的 React 替代方案;API 兼容 React |
| Lit | 1. 安装 @astrojs/lit2. 配置集成 | // 使用 Web Components 语法定义 | ---import './my-element.js';---<my-element client:only /> | 适用于原生 Web Components;client:only 表示仅在客户端渲染 |
通用注意事项:
- 所有框架组件必须放置在
src/components/或其子目录下。- Astro 不会自动打包框架运行时,仅在需要时通过
client:指令加载。- 框架组件无法直接访问 Astro 的
Astro.props,需通过属性传递数据。
4.3 客户端指令(client: directives)详解
| 指令名称 | 触发时机 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
client:load | 页面加载完成后立即执行 | 适用于关键交互组件(如导航菜单) | <MyNav client:load /> | 会阻塞页面交互直到组件加载完成;慎用于非关键组件 |
client:idle | 浏览器主线程空闲时(使用 requestIdleCallback) | 适用于低优先级组件(如推荐模块) | <Recommendations client:idle /> | 可能延迟加载;若浏览器不支持 requestIdleCallback,则回退到 load |
client:visible | 组件进入视口时(使用 Intersection Observer) | 适用于首屏外组件(如图片懒加载、评论区) | <CommentSection client:visible /> | 需要用户滚动到该区域才激活;节省初始带宽 |
client:media | 满足指定媒体查询条件时 | 适用于响应式组件(如移动端专属控件) | <MobileMenu client:media="(max-width: 768px)" /> | 媒体查询字符串需用双引号包裹;动态响应窗口大小变化 |
client:only | 仅在客户端渲染,不在服务端/构建时渲染 | 适用于依赖浏览器 API 的组件(如地图、Canvas) | <MapComponent client:only="react" /> | 必须指定框架名(如 "react");SSR/SSG 时该组件为空占位符 |
client:hydrate | (已弃用)旧版指令,等同于 client:load | — | — | Astro 2.0+ 已移除,统一使用上述新指令 |
重要说明:
- 客户端指令仅对集成的 UI 框架组件有效,对 Astro 原生组件无效(因其无 JS)。
- 同一组件只能使用一个
client:指令。- 使用
client:only时,若未指定框架或框架未正确集成,将导致运行时错误。
第五章:数据获取与内容管理
5.1 静态数据加载(getStaticPaths)
| 方法/概念 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
getStaticPaths() 函数 | 在 .astro 页面组件的 Frontmatter 中导出异步函数 | 为动态路由预生成多个静态页面 | ---export async function getStaticPaths() {const posts = await fetchPosts();return posts.map(post => ({params: { slug: post.slug },props: { title: post.title, content: post.body }}));}const { title, content } = Astro.props;--- | 必须返回 { params: {...}, props?: {...} } 对象数组;仅在构建时运行一次 |
params 对象 | 路径参数映射 | 填充动态路由段(如 [slug].astro) | { params: { slug: 'hello-world' } } → 生成 /hello-world | 参数名必须与文件中的动态段名称一致(如 [id] 对应 params.id) |
props 对象 | 页面属性传递 | 将数据直接注入页面组件,避免重复请求 | props: { author: 'Alice', date: '2026-06-23' } | 接收方式:const { author, date } = Astro.props;;适用于 SSG 场景 |
无 getStaticPaths 的动态路由 | 未定义该函数 | 该动态页面无法参与静态生成 | — | 访问该路径将返回 404(除非启用 SSR 并设置 prerender: false) |
| 与 CMS 集成 | 在 getStaticPaths 中调用 CMS API | 构建时拉取内容生成静态页 | export async function getStaticPaths() {const res = await fetch('https://api.example.com/posts');const posts = await res.json();return posts.map(p => ({ params: { id: p.id } }));} | 确保 API 在构建时可访问;建议添加错误处理和缓存 |
5.2 Markdown 与 MDX 内容处理
| 功能 | 说明 | 文件位置示例 | 使用方式 | 注意事项 |
|---|---|---|---|---|
| Markdown 页面 | .md 文件自动转为页面 | src/pages/blog/post.md → /blog/post | 直接编写 Markdown 内容:# TitleContent here... | 支持 frontmatter(YAML)定义元数据:---title: My Postdate: 2026-06-23--- |
| MDX 支持 | 安装 @astrojs/mdx 后支持 .mdx | src/pages/guide.mdx | 在 Markdown 中嵌入 JSX 组件:# Guide<MyComponent /> | 需在 astro.config.mjs 中启用 mdx() 集成;组件需在 MDX 文件中导入 |
| Markdown 数据查询 | 使用 Astro.glob() 批量读取 | 在 .astro 组件中:const posts = await Astro.glob('../pages/blog/*.md'); | 遍历获取 frontmatter 和渲染函数:posts.map(post => ({...post.frontmatter,Content: post.Content})) | Astro.glob() 仅支持相对路径;返回对象包含 frontmatter 和 Content(组件) |
| 自定义 Markdown 渲染 | 通过 remark/rehype 插件扩展 | 在 astro.config.mjs 中配置:markdown: {remarkPlugins: [remarkGfm],rehypePlugins: [rehypeAutolinkHeadings]} | 支持 GitHub Flavored Markdown、自动目录等 | 需安装对应插件(如 remark-gfm);插件在构建时运行 |
| 图片与资源引用 | 在 Markdown 中使用相对路径 |  | 图片需放在 public/ 或同级目录 | 若放在 src/ 下,需确保路径正确;推荐使用 public/ 存放全局资源 |
5.3 从 API 获取动态数据
| 场景 | 方法 | 代码示例 | 注意事项 |
|---|---|---|---|
| 构建时获取(SSG) | 在 getStaticPaths 或页面顶层作用域中调用 API | ---const res = await fetch('https://api.example.com/data');const data = await res.json();---<div>{data.message}</div> | 仅在 astro build 时执行;适合公开、不频繁变化的数据;API 必须在构建时可访问 |
| 客户端获取(CSR) | 在集成的框架组件(React/Vue 等)中使用 useEffect 或 onMount | // React 示例useEffect(() => {fetch('/api/user').then(r => r.json()).then(setUser);}, []); | 数据在浏览器中加载;适合用户私有数据或实时性要求高的场景;需自行处理 loading/error 状态 |
| 服务端获取(SSR) | 在 prerender: false 的页面中,使用 Astro.request 或直接 fetch | ---export const prerender = false;const user = await fetch('https://api.example.com/user', {headers: { Cookie: Astro.request.headers.get('cookie') }}).then(r => r.json());--- | 仅在 SSR 模式下有效(output: 'server');可访问请求头(如认证信息);每次请求都会执行 |
| 混合方案(SSG + CSR) | 静态骨架 + 客户端补充数据 | 先渲染静态内容,再在客户端组件中加载个性化数据 | <UserProfileSkeleton /><ClientUserData client:load /> |
| 环境变量安全 | 使用 .env 文件存储敏感信息 | 在 astro.config.mjs 中:import { defineConfig } from 'astro';export default defineConfig({vite: { envPrefix: 'PUBLIC_' }});// 组件中: import.meta.env.PUBLIC_API_URL | 以 PUBLIC_ 开头的变量会暴露给客户端;其他变量仅在构建/服务端可用 |
关键区别总结:
- SSG(构建时):数据固化到 HTML,极致性能,但无法实时更新。
- SSR(服务端):每次请求获取最新数据,支持用户上下文,但需服务器支持。
- CSR(客户端):灵活交互,但增加 JS 体积和首屏延迟。
Astro 推荐优先使用 SSG,按需引入 SSR 或 CSR。
第六章:构建与部署
6.1 构建命令与输出结构
| 操作/概念 | 命令或说明 | 输出路径 | 文件结构示例 | 注意事项 |
|---|---|---|---|---|
| 默认构建命令 | npm run build 或 astro build | dist/(默认) | dist/├── index.html├── about/│ └── index.html├── _astro/│ ├── Layout.astro.hash.js│ └── react-framework.hash.js└── favicon.ico | 所有静态 HTML、CSS、JS、资源文件均输出至此目录;_astro/ 存放框架运行时和组件 JS |
| 自定义输出目录 | 在 astro.config.mjs 中设置:outDir: './public' | 指定目录(如 ./public) | 同上,但根目录为 public/ | 需确保 .gitignore 或部署配置同步更新 |
| 输出格式(output) | output: 'static'(默认)output: 'server'(SSR) | static → dist/server → dist/ + 服务端入口 | SSR 模式下包含 server/ 目录和 entry.mjs 等 | 切换 output 需重新构建;SSR 需配合适配器使用 |
| 静态资源处理 | 放置在 public/ 目录的文件直接复制到输出根目录 | public/favicon.ico → dist/favicon.ico | — | 不经过构建流程;适合 robots.txt、sitemap.xml 等 |
| 资源哈希与缓存 | JS/CSS 文件自动添加内容哈希(如 Layout.abc123.js) | _astro/ 目录下 | — | 利于长期缓存;HTML 文件无哈希,需短缓存策略 |
6.2 部署到 Vercel / Netlify / GitHub Pages
| 平台 | 部署方式 | 配置要点 | 注意事项 |
|---|---|---|---|
| Vercel | 1. 连接 Git 仓库 2. 自动检测 Astro 项目 3. 或手动设置 | - Build Command: astro build- Output Directory: dist- 若使用 SSR,需安装对应适配器(如 @astrojs/vercel) | 支持 SSG 和 SSR;SSR 需在 astro.config.mjs 中配置 vercel() 适配器;自动启用边缘函数(Edge Functions) |
| Netlify | 1. Git 集成或拖拽 dist 目录2. 或通过 CLI 部署 | - Build Command: astro build- Publish directory: dist- SSR 需使用 @astrojs/netlify 适配器 | 免费支持 SSG;SSR 需配置 Netlify Functions;可自定义 _redirects 或 netlify.toml 处理重定向 |
| GitHub Pages | 1. 构建后推送 dist 到 gh-pages 分支2. 或使用 Actions 自动部署 | 在 .github/workflows/deploy.yml 中:run: npm run builddeploy to: github-pages- 项目设置中指定 source 为 gh-pages 分支 | 仅支持 SSG(纯静态);不支持 SSR 或 API 路由;若项目不在根路径(如 user.github.io/repo),需设置 base: '/repo/' in astro.config.mjs |
| 通用注意事项 | — | 所有平台均需确保 dist/ 包含完整静态站点 | 若使用动态导入或客户端路由(如集成 React Router),需配置 SPA 回退(如 _redirects 中 /* /index.html 200) |
6.3 自定义服务器适配器(Adapter)
| 适配器类型 | 安装命令 | 配置方式(astro.config.mjs) | 适用部署目标 | 注意事项 |
|---|---|---|---|---|
| Node.js | npm install @astrojs/node | import node from '@astrojs/node';export default defineConfig({ output: 'server', adapter: node() }); | 自托管 Node 服务器、Docker 容器 | 生成 dist/server/entry.mjs,可通过 node dist/server/entry.mjs 启动 |
| Deno | npm install @astrojs/deno | import deno from '@astrojs/deno';export default defineConfig({ output: 'server', adapter: deno() }); | Deno Deploy、本地 Deno 运行时 | 需使用 Deno 运行构建产物;兼容 Deno 标准库 |
| Cloudflare Pages | npm install @astrojs/cloudflare | import cloudflare from '@astrojs/cloudflare';export default defineConfig({ output: 'server', adapter: cloudflare() }); | Cloudflare Pages(带 SSR 支持) | 自动编译为 Workers 兼容格式;支持 Durable Objects、KV 等 Cloudflare 特性 |
| Vercel | npm install @astrojs/vercel | import vercel from '@astrojs/vercel/serverless'; // 或 edgeexport default defineConfig({ output: 'server', adapter: vercel() }); | Vercel Serverless Functions 或 Edge Functions | 可选 serverless(传统)或 edge(低延迟)模式;自动处理路由和函数打包 |
| Netlify | npm install @astrojs/netlify | import netlify from '@astrojs/netlify';export default defineConfig({ output: 'server', adapter: netlify() }); | Netlify Functions | 生成 Netlify 兼容的函数入口;支持表单处理、身份验证等 |
| 自定义适配器 | 实现 Astro 适配器接口 | 需导出 { name, serverEntrypoint, ... } | 任意支持 JavaScript 的服务器环境 | 参考官方适配器源码;需处理请求/响应对象、静态资源服务、错误边界等 |
关键说明:
- 使用适配器前必须将
output设置为'server'。- 适配器决定了 SSR 代码如何打包和运行,不能混用(如 Vercel 项目不能用 Netlify 适配器)。
- 静态站点(
output: 'static')无需任何适配器。- 适配器通常会修改构建输出结构(如增加
server/目录),部署时需按平台要求上传完整产物。
第七章:高级功能
7.1 中间件(Middleware)
| 概念/方法 | 语法/文件位置 | 用途 | 代码示例 | 注意事项 |
|---|---|---|---|---|
| 中间件定义 | src/middleware.ts(或 .js) | 拦截所有请求,执行逻辑(如重定向、认证、日志) | export async function onRequest(context, next) {const { request } = context;console.log('URL:', request.url);const response = await next();return response;} | 必须导出 onRequest 函数;仅在 SSR 模式(output: 'server')下生效 |
| 上下文对象(context) | context.request, context.url, context.site 等 | 获取请求信息和环境数据 | const { pathname } = new URL(request.url);if (pathname.startsWith('/admin') && !isAdmin) {return new Response(null, { status: 403 });} | context.site 来自 astro.config.mjs 中的 site 配置;可用于生成绝对 URL |
| 调用链(next()) | const response = await next(); | 将控制权交给下一个中间件或页面处理器 | const response = await next();response.headers.set('X-Custom', 'true');return response; | 可修改响应;若不调用 next(),则中断请求链(可用于返回自定义响应) |
| 多中间件顺序 | Astro 不支持多个中间件文件 | — | — | 仅识别 src/middleware.* 单个文件;复杂逻辑需在该文件内组织 |
| 与适配器兼容性 | 所有官方服务器适配器均支持 | 确保中间件在目标平台运行 | 在 Vercel Edge Functions 中使用时,避免 Node.js 特有 API | 中间件代码需兼容部署环境(如 Edge Runtime 不支持 fs、path 等) |
7.2 国际化(i18n)支持
| 方案类型 | 实现方式 | 目录结构示例 | 路由形式 | 注意事项 |
|---|---|---|---|---|
| 基于子目录的 i18n(推荐) | 手动创建多语言页面目录 | src/pages/├── en/│ ├── index.astro│ └── about.astro└── zh/├── index.astro└── about.astro | /en/, /zh/about | 简单可靠;适合静态站点;需手动维护各语言版本 |
| 动态路由 + getStaticPaths | 使用 [lang] 动态段 + 数据驱动 | src/pages/[lang]/[slug].astro | /en/post-1, /zh/post-1 | 在 getStaticPaths 中遍历语言和内容:langs.map(lang => posts.map(post => ({ params: { lang, slug: post.slug } }))) |
| 客户端 i18n 库集成 | 在 UI 框架组件中使用 react-i18next、vue-i18n 等 | 组件内切换语言 | 单一 URL(如 /app),语言状态存于 localStorage 或 URL hash | 适用于高度交互应用;牺牲部分 SEO;需加载额外 JS |
| 自动语言重定向 | 通过中间件检测 Accept-Language | — | 用户访问 / → 重定向到 /en/ 或 /zh/ | export async function onRequest({ request }, next) {const lang = detectLanguage(request.headers.get('Accept-Language'));return Response.redirect(new URL('\/\${lang}/\', request.url), 302);} |
| 翻译内容管理 | 使用 JSON/YAML 存储翻译文本 | public/locales/├── en.json└── zh.json | — | 在 Astro 组件中导入:import en from '../locales/en.json';const t = en; |
最佳实践建议:
- 优先使用 子目录方案 以获得最佳 SEO 和可访问性。
- 避免混合使用多种 i18n 方案,以免路由冲突。
- 为
<html>标签设置lang属性(如<html lang={lang}>)以提升无障碍体验。
7.3 性能优化与 Lighthouse 最佳实践
| 优化类别 | 具体措施 | Astro 相关配置/用法 | 对 Lighthouse 指标影响 | 注意事项 |
|---|---|---|---|---|
| 减少 JavaScript | 默认无 JS;仅对交互组件使用 client: 指令 | <InteractiveComp client:visible /> | 提升 Performance, Best Practices | 避免对非交互组件添加 client:;优先使用 Astro 原生组件 |
| 图片优化 | 使用 <Image /> 组件(需集成 @astrojs/image) | <Image src="/photo.jpg" widths={[400, 800]} formats={['avif', 'webp']} /> | 提升 Performance(LCP, TBT) | 自动生成多尺寸、现代格式;需配置适配器(如 sharp) |
| 字体优化 | 预加载关键字体,使用 font-display: swap | <link rel="preload" as="font" href="/fonts/inter.woff2" type="font/woff2" crossorigin><style>@font-face { font-family: 'Inter'; src: url(...); font-display: swap; }</style> | 提升 Performance(FCP, LCP) | 避免阻塞渲染;本地托管字体优于第三方 CDN(如 Google Fonts) |
| 资源预加载/预取 | 使用 <link rel="prefetch"> 或 <link rel="preload"> | 在 Astro 组件 <head> 中添加:<link rel="prefetch" href="/next-page.html"> | 提升后续页面加载速度 | preload 用于当前页关键资源;prefetch 用于未来可能访问的页面 |
| 压缩与缓存 | 启用 Brotli/Gzip;设置长期缓存头 | 由部署平台(Vercel/Netlify)自动处理;或在自定义服务器中配置 | 提升 Performance(TTFB, Transfer Size) | 确保 _astro/ 下带哈希的资源设置 Cache-Control: max-age=31536000 |
| 移除未使用 CSS | Astro 自动作用域样式,但全局 CSS 需手动精简 | 避免大型 CSS 框架全量引入;使用按需导入(如 Tailwind PurgeCSS) | 提升 Performance(TTI, TBT) | 在 tailwind.config.cjs 中配置 content 扫描 Astro 文件 |
| Lighthouse CI 集成 | 在 CI 中运行 Lighthouse 并设基线 | 使用 lighthouse-ci 工具:lhci autorun --upload.target=temporary-public-storage | 自动监控性能回归 | 可在 PR 中评论分数;建议设定阈值(如 Performance ≥ 90) |
关键指标对应关系:
- LCP(最大内容绘制):优化图片、字体、关键资源加载。
- FID/TBT(交互延迟):减少主线程 JS 执行时间,延迟非关键组件。
- CLS(累积布局偏移):为图片/广告预留空间(设置
width/height)。
Astro 天然符合 “渐进增强” 和 “少即是多” 的性能哲学,合理利用其静态优先特性可轻松达成 Lighthouse 90+ 分数。
第八章:工具与生态
8.1 Astro 集成(Integrations)机制
| 概念/方法 | 语法/结构 | 用途 | 代码示例(astro.config.mjs) | 注意事项 |
|---|---|---|---|---|
| 集成定义 | 函数返回 { name, hooks } 对象 | 扩展 Astro 构建、开发、服务行为 | import myPlugin from './my-integration.js';export default defineConfig({integrations: [myPlugin()]}); | 集成必须是一个函数,调用后返回配置对象 |
| 核心钩子(Hooks) | astro:config:setup, astro:config:done, astro:build:start 等 | 在构建生命周期中注入逻辑 | export default function myIntegration() {return {name: 'my-integration',hooks: {'astro:config:setup': ({ config, updateConfig }) => {updateConfig({ vite: { ... } });}}};} | 常用钩子: - config:setup:修改配置- build:start:构建前执行- server:setup:开发服务器启动时 |
| Vite 插件集成 | 通过 updateConfig({ vite: { plugins: [...] } }) 注入 | 复用 Vite 生态(如 SVG、PWA) | hooks: {'astro:config:setup': ({ updateConfig }) => {updateConfig({vite: {plugins: [svgPlugin()]}});}} | Astro 底层基于 Vite,可无缝使用 Vite 插件 |
| 条件启用集成 | 使用环境变量或配置开关 | 按需加载(如仅生产环境启用 PWA) | integrations: [process.env.NODE_ENV === 'production' ? pwa() : null].filter(Boolean) | 避免开发时加载不必要的插件 |
| 集成参数传递 | 集成函数接受选项对象 | 自定义行为 | integrations: [mdx({ optimize: true })] | 官方集成通常提供类型定义,支持 TS 智能提示 |
8.2 常用官方与社区集成列表
| 集成名称 | 类别 | 用途 | 安装命令 | 适用场景 |
|---|---|---|---|---|
kronk-cms | CMS(内容管理系统)插件 | 无需切换浏览器,在IDE中管理内容,支持Hugo、Jekyll、Astro静态站点生成器,快速应用主题 | npm install kronk-cms# 在项目中初始化 cd my-astro-blogkronk init | 博客页面开发 |
@astrojs/react | UI 框架 | 在 Astro 中使用 React 组件 | npm install @astrojs/react react react-dom | 需要 React 生态(如状态管理、Hooks) |
@astrojs/vue | UI 框架 | 集成 Vue 3 组件 | npm install @astrojs/vue vue | Vue 开发者快速迁移;组合式 API 支持 |
@astrojs/svelte | UI 框架 | 使用 Svelte 组件 | npm install @astrojs/svelte svelte | 极简响应式组件;无虚拟 DOM 开销 |
@astrojs/tailwind | CSS 工具 | 集成 Tailwind CSS | npm install @astrojs/tailwind tailwindcss | 实用优先的原子化 CSS;自动 Purge 未使用类 |
@astrojs/mdx | 内容 | 支持 .mdx 文件(Markdown + JSX) | npm install @astrojs/mdx | 技术文档、博客中嵌入交互组件 |
@astrojs/image | 资源优化 | 自动优化图片(WebP/AVIF、响应式尺寸) | npm install @astrojs/image sharp | 提升 LCP;需配合适配器(如 sharp) |
@astrojs/partytown | 性能 | 将第三方脚本(如 Google Analytics)移至 Web Worker | npm install @astrojs/partytown | 避免第三方 JS 阻塞主线程 |
@astrojs/sitemap | SEO | 自动生成 sitemap.xml | npm install @astrojs/sitemap | 提升搜索引擎收录;支持多语言站点 |
@astrojs/rss | 内容分发 | 生成 RSS/Atom 订阅源 | npm install @astrojs/rss | 博客、新闻站内容聚合 |
@astrojs/check | 开发体验 | 类型检查 Astro 项目(实验性) | npm install @astrojs/check | 提前发现模板/Props 类型错误 |
astro-icon(社区) | UI 组件 | 内联 SVG 图标库 | npm install astro-icon | 轻量图标方案;支持自定义集合 |
astro-compress(社区) | 构建优化 | 自动压缩 HTML/CSS/JS | npm install astro-compress | 减小传输体积;适用于静态部署 |
选型建议:
- 优先使用 官方集成(以
@astrojs/开头),兼容性和维护性有保障。- 社区集成需检查更新频率、GitHub Stars 及是否支持最新 Astro 版本。
- 避免同时启用功能重叠的集成(如多个图片优化插件)。
8.3 开发者工具(VS Code 插件、调试技巧)
| 工具/技巧 | 说明 | 安装/使用方式 | 注意事项 |
|---|---|---|---|
| Official Astro VS Code Extension | 官方插件,提供语法高亮、智能提示、错误诊断 | VS Code 商店搜索 “Astro” 并安装 | 必装;支持 .astro 文件的 TypeScript/JSX 语法 |
| TypeScript 支持 | 在 Astro 项目中启用 TS | 创建 tsconfig.json;组件中使用 <script lang="ts"> | Astro 自动读取 tsconfig.json;无需额外配置 |
| 调试构建错误 | 查看详细错误堆栈 | 运行 astro build --verbose | 可定位到具体文件和行号;结合 --drafts 跳过草稿页 |
| 开发服务器热更新 | 修改文件自动刷新 | npm run dev 启动开发服务器 | 支持 .astro、.md、CSS、集成框架组件的 HMR |
| 审查客户端组件 | 调试 React/Vue 组件 | 浏览器 DevTools → Sources 中查找 _astro/ 下的组件 JS | 使用 client:load 的组件会出现在 JS 文件中;可打 debugger 断点 |
| 模拟 SSR 环境 | 本地测试中间件和动态路由 | 设置 output: 'server' 并运行 astro preview | astro preview 启动本地 Node 服务器,模拟生产 SSR 行为 |
| Lighthouse 审计 | 性能与最佳实践检测 | Chrome DevTools → Lighthouse 标签 | 建议在 生产构建(astro build && astro preview)后运行 |
| Astro REPL(实验性) | 交互式 Astro 代码测试 | 目前无官方 REPL;可使用在线 Playground(如 astro.new) | 适合快速验证语法;不支持完整项目上下文 |
高效开发建议:
- 启用 VS Code 的 Emmet 支持:在设置中添加
"emmet.includeLanguages": { "astro": "html" }。- 使用
console.log在getStaticPaths或页面顶层作用域中调试构建时数据流。- 遇到集成冲突时,尝试创建最小复现仓库,便于排查问题。