要点
本篇是 Astro 的条目式速查,按用途分七组:CLI 命令、配置项、内容集合 API(astro:content)、Astro 全局对象、模板指令、脚本与样式处理、环境变量;文末有全量速查表,可只搜表定位条目。版本基线为 Astro 5.2.x 稳定线(截至 2025-02-22),仅在基线成立的行为单独标注。机制讲解不在本篇重复:指令与注水细节见《Astro 语法要点:组件、指令与客户端脚本》,工程从零跑通的步骤见《第一个 Astro 应用》。
CLI 命令组
命令都通过 npx astro 或 package.json scripts 调用。组内共性:dev 与 build 会自动先执行 sync;preview 只碰构建产物,不碰源码。
| 命令 | 一句话用途 | 有什么坑 |
|---|---|---|
| astro dev | 起开发服务器(默认 localhost:4321),热更新 |
dev 环境的表现不能当上线结论,验收看 build + preview |
| astro build | 生产构建,产物在 dist/ |
内容 schema 错误、frontmatter 类型错都在这一步暴露 |
| astro preview | 本地静态服务预览 dist/ |
server 输出模式的 preview 依赖 adapter 支持,不是所有 adapter 都提供 |
| astro sync | 生成内容集合与 astro:env 的类型声明 |
CI 单独跑 check 前先 sync,否则没有 .d.ts 会误报 |
| astro check | 对 .astro 文件跑类型与语法诊断 |
需先安装 @astrojs/check 与 typescript;它不代替构建校验 |
| astro add | 一键装集成/适配器并自动改配置 | 手动 npm install 不写进 integrations 等于没装 |
| astro upgrade | 升级到最新版本 | 跨大版本先读官方升级指南,破坏性变更不自动迁移 |
| astro info | 打印环境信息,报 issue 用 | 输出含系统路径,公开贴出前过目一眼 |
astro sync:类型从哪来
npx astro sync # dev/build 自动执行;手动跑主要为编辑器类型提示与 CI 诊断
一句话语义:内容集合和 astro:env 的 TypeScript 类型是按你的 schema 现生成的,sync 负责生成它们。⚠️ 常见坑:新增集合后编辑器不认 getCollection('新集合') 的参数,多半是类型没刷新——跑一次 sync 或重启 dev server。
astro add:集成的正确装法
npx astro add react # UI 框架:react / vue / svelte / solid / preact / alpine / lit
npx astro add mdx tailwind node # 集成与 adapter 可以一条命令装多个
一句话语义:装包 + 写进 astro.config.mjs 的 integrations/adapter,一步到位。⚠️ 常见坑:装 adapter 前先想清部署平台——adapter 决定运行环境(Node 还是边缘),选错要连代码一起改。
配置组:astro.config.mjs
| 配置项 | 一句话用途 | 有什么坑 |
|---|---|---|
| site | 站点最终部署的 origin(如 https://docs.example.com) |
不填则 sitemap、canonical、Astro.site 全不对;静态部署前必填 |
| base | 部署在子路径时的前缀(如 /docs) |
base 不会自动拼进你自己写的 <a href>,页内链接要手动处理 |
| output | 'static'(默认,构建期出全站 HTML)或 'server'(按需 SSR) |
切 server 不是”更高级”,是换运行时;混排靠逐路由 prerender 控制 |
| adapter | SSR 的部署桥(node / vercel / cloudflare / netlify 等) | 平台 API 不通用:Cloudflare 的 KV 在 node adapter 下不存在 |
| integrations | 集成数组(react、mdx、sitemap 等) | astro add 会自动写;只装包不登记是白装 |
| env | astro:env 的 schema 定义处(见环境变量组) |
schema 里没声明的变量走 import.meta.env 老路,两套混用要分清 |
| vite | Vite 配置透传(alias、插件等) | 排查构建问题先怀疑 Astro 层再动 Vite,别一上来就透传 |
最小可用配置
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://docs.example.com', // 影响 sitemap 与 canonical
// output: 'static' 是默认值;要 SSR 时才显式写 'server' 并配 adapter
});
⚠️ 常见坑:output: 'server' 加了 adapter 之后,默认全部路由变按需渲染——想保持”文档主体静态、个别页面动态”,要在页面里用 export const prerender = true 逐个标回来,而不是整站跟着 adapter 走。
内容集合组:astro:content
| 条目 | 一句话用途 | 有什么坑 |
|---|---|---|
| defineCollection() | 声明一个集合:loader + schema | 配置文件固定为 src/content.config.ts,放别处不生效 |
| glob()(来自 astro/loaders) | 从本地目录读 Markdown/MDX/JSON 等建集合 | base 指目录、pattern 指匹配;内容不再锁死在 src/content/ 下 |
| getCollection(name, filter?) | 取整个集合的条目数组 | 返回 Promise,忘了 await 拿到的是 Promise 本身 |
| getEntry(name, id) | 按 id 取单条 | id 含路径段(如 guide/intro),不是”文件名不含后缀”这么简单 |
| render(entry) | 把 Markdown/MDX 条目编译成可渲染组件 | 返回 { Content, headings, remarkPluginFrontmatter },要 await;旧写法 entry.render() 已被取代,改为从 astro:content 导入 render |
| reference(‘collection’) | schema 内声明跨集合引用 | 引用的 id 必须真实存在,否则构建期报错 |
| entry.id | 条目的唯一标识,动态路由的 params 来源 | 旧版叫 slug,5.0 起统一为 id,老教程照抄会 undefined |
| entry.data | 经过 schema 校验的 frontmatter | 字段拼错在构建期报错——这是 collections 的核心价值,别绕过 |
| entry.body | Markdown 原文(未编译) | 只读场景(导出、统计)用它;要渲染一律走 render() |
定义集合(schema 用 Zod 3)
// src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
draft: z.boolean().default(false),
tags: z.array(z.string()).default([]),
}),
});
export const collections = { blog };
⚠️ 常见坑:Astro 5 的 astro:content 导出的 z 是 Zod 3——collections 的 schema 一律从这里拿,别在项目里再单独装一份 zod 混用,两份 Zod 的校验行为与类型推导可能对不上。
查询与渲染(动态路由全套)
---
// src/pages/blog/[...id].astro
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog', ({ data }) => !data.draft);
return posts.map((entry) => ({ params: { id: entry.id }, props: { entry } }));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<article>
<h1>{entry.data.title}</h1>
<Content />
</article>
⚠️ 常见坑:getCollection 的过滤器在数据量大时值得写——draft、语言、分区过滤都放这里,别取全量再在页面里筛。
Astro 全局对象组
| 条目 | 一句话用途 | 有什么坑 |
|---|---|---|
| Astro.props | 组件入参 | class 不自动包含,要接必须在 Props 里声明 |
| Astro.params | 当前路由的动态段 | 静态模式下没有 getStaticPaths 的 params 就没有它 |
| Astro.url | 当前页 URL(URL 对象) | 做 canonical 或分享链接用它,别手工拼字符串 |
| Astro.site | 配置里 site 的 URL 对象 | 没配 site 时是 undefined,用到前先判空 |
| Astro.cookies | 读写请求 cookie(get/has/set/delete) | 只在 server 输出下有意义,纯静态页没有可读的请求上下文 |
| Astro.redirect() | 服务端重定向 | 静态模式下无效;静态站的重定向交给托管层 301 或 meta refresh |
| Astro.locals | 中间件/adapter 注入的请求级数据 | 没配中间件时是空对象,别把它当全局状态用 |
| Astro.slots | 以字符串形式处理子内容(has/render) | render 返回 HTML 字符串,接到用户内容要消毒 |
| Astro.self | 组件递归调用自己 | 递归要有终止条件,否则构建期爆栈 |
| Astro.currentLocale | i18n 配置下的当前语言 | 没配 i18n 时返回 undefined |
| Astro.generator | 版本串(页脚署名用) | 纯展示用途,别拿它做逻辑分支 |
params 与 cookies 的最小示例
// Astro.params:静态模式必须由 getStaticPaths 提供 params(见内容集合组示例)
const { id } = Astro.params;
// Astro.cookies:server 输出下读写
const theme = Astro.cookies.get('theme')?.value ?? 'light';
Astro.cookies.set('theme', 'dark', { path: '/' });
⚠️ 常见坑:把 Astro.cookies/Astro.redirect 写进纯静态站,构建不报错但行为不是你想要的——静态页构建期就定稿,没有”每个请求”可言。这两个 API 出现在代码里,就是该考虑 server 输出的信号。
模板指令组
机制与选型见语法要点篇,这里只留速查。
| 指令 | 一句话用途 | 有什么坑 |
|---|---|---|
| client:load | 页面加载立即注水 | 只给首屏关键交互,全站滥用等于白用岛架构 |
| client:idle | 浏览器空闲时注水 | 基于 requestIdleCallback,低端机上可能晚半拍 |
| client:visible | 滚入视口才注水 | 基于 IntersectionObserver;首屏内组件用它没收益 |
| client:media | 媒体查询匹配才注水 | 值是字符串,如 "(max-width: 48em)" |
| client:only | 跳过构建期渲染,纯客户端 | 多框架共存必须指名框架,如 client:only="react" |
| class:list | 数组/对象拼 class,假值剔除 | 不做去重排序 |
| set:html | 注入原始 HTML(不转义) | 用户内容用它 = XSS;JSON-LD 是正当用途 |
| set:text | 注入纯文本 | 要”带格式”时做不到,那是 set:html 的活 |
| is:inline | 脚本/样式原样输出 | 失去打包与去重,多实例重复执行 |
| is:global | 样式不限作用域 | 能用 scoped 就别开 |
| is:raw | 子内容当纯文本不解析 | 适合展示代码,别包正文 |
| define:vars | 向脚本/样式传构建期变量 | script 上隐含 is:inline;style 上要求不 inline,方向相反 |
| transition:name | 软导航配对元素过渡动画 | 配合 ClientRouter;name 页面内要唯一 |
| transition:persist | 软导航保留元素状态(如播放器) | 只对岛与元素本身,不等价于”全局状态” |
脚本与样式处理组
| 条目 | 一句话用途 | 有什么坑 |
|---|---|---|
| (默认) | 打包成 module、去重、提 head;可写 TS、import 包 | 按页面去重不按实例——多实例组件的脚本要 querySelectorAll 分派 |
| 原样输出,不打包 | 不能写 TS、不能 import;第三方片段专用 | |
| 把构建期变量序列化进脚本 | 隐含 is:inline,四条特性一起失去 | |
| data-astro-rerun | 软导航后强制重跑脚本 | 只对启用了 ClientRouter 的站有意义;滥用会重复绑定事件 |
| (默认) | 编译期限定当前组件作用域 | 靠属性选择器实现,命中不了框架岛内部 |
| 全局样式 | 互相覆盖,放全局 reset 这类”真全局”再开 | |
| 构建期变量注入为 CSS 自定义属性 | 要求不 inline,与 script 的 define:vars 方向相反 |
<style define:vars={{ accent: 'rebeccapurple' }}>
.btn { background: var(--accent); } /* define:vars 序列化为 CSS 变量 */
</style>
⚠️ 常见坑:给页面里的 React 岛写 scoped 样式——data-astro-cid 属性只加在 .astro 模板的元素上,岛内部命中不了;岛内样式归岛自己(CSS Modules、内联都行),或经 props 传 class。与React 渲染边界同理:边界内外各管各的。
环境变量组
| 条目 | 一句话用途 | 有什么坑 |
|---|---|---|
| import.meta.env.PUBLIC_* | 公开变量,构建期注入产物 | 谁都能在产物里看到——PUBLIC_ 前缀等号”自愿公开”,密钥绝不加它 |
| import.meta.env.MODE/DEV/PROD | 运行模式与开发/生产标记 | 全是构建期定值,运行时改环境变量无效 |
| import.meta.env.BASE_URL | base 配置对应的路径前缀 | 配置 base 后拼链接统一用它,别散落硬编码 |
| env.schema(配置) | 用 envField 声明类型化变量 |
声明后走 astro:env 导入,import.meta.env 里读不到类型 |
| astro:env/client | 客户端可用的类型化变量 | context: ‘client’ 的变量会被打进产物,放密钥就是泄漏 |
| astro:env/server + getSecret | 服务端变量;secret 在运行时读取 | 运行时读取意味着纯静态站拿不到——静态站没有运行时 |
// astro.config.mjs —— 声明 schema
import { defineConfig, envField } from 'astro/config';
export default defineConfig({
env: {
schema: {
API_BASE: { type: 'string', context: 'client', access: 'public' },
SEARCH_KEY: { type: 'string', context: 'server', access: 'secret' },
},
},
});
// 使用:按 context 从对应入口导入
import { API_BASE } from 'astro:env/client';
import { SEARCH_KEY, getSecret } from 'astro:env/server';
const key = SEARCH_KEY ?? (await getSecret('SEARCH_KEY')); // secret 走 getSecret 运行时读
⚠️ 常见坑:两套机制混着用时最容易犯的错是把秘密放 import.meta.env——它在构建时硬编码,产物里 grep 就能拿到。原则:给浏览器的公开值走 client;只在服务端用的走 server secret;纯静态站需要”运行时才知的秘密”,说明该给那一个路由开 server 输出。
速查表
| 条目 | 一句话用途 | 有什么坑 |
|---|---|---|
| astro dev / build / preview | 开发 / 构建 / 预览产物 | 验收以 preview 的产物为准 |
| astro sync / check | 生成类型 / 诊断 .astro | CI 里 check 前先 sync |
| astro add / upgrade / info | 装集成 / 升级 / 环境信息 | add 不写 integrations 等于白装 |
| site / base(配置) | 部署 origin / 子路径前缀 | site 不填 sitemap 全错;base 不自动拼链接 |
| output / adapter | static 或 server / SSR 部署桥 | server 后默认全站按需,静态路由要 prerender 标回 |
| defineCollection + glob() | 集合 = loader + schema | 配置文件必须是 src/content.config.ts |
| getCollection / getEntry | 取集合 / 取单条 | 返回 Promise;过滤器放查询层 |
| render(entry) | 编译内容为组件 | 要 await;entry.render() 是旧写法 |
| entry.id / data / body | 标识 / 校验后数据 / 原文 | id 取代了旧 slug |
| Astro.props / params / url | 入参 / 路由段 / 当前 URL | class 要显式声明;params 依赖 getStaticPaths |
| Astro.cookies / redirect / locals | cookie / 重定向 / 请求级数据 | 纯静态下全部无意义 |
| Astro.slots / self | 子内容字符串 / 组件递归 | render 结果要消毒;递归要有终止 |
| client:load / idle / visible / media / only | 五种注水时机 | only 多框架要指名;props 必须可序列化 |
| class:list / set:html / set:text | 拼 class / 原始 HTML / 纯文本 | set:html 遇用户内容即 XSS |
| is:inline / is:global / is:raw | 脚本原样 / 样式全局 / 文本原样 | inline 失去打包去重 |
| define:vars | 传构建期变量进脚本/样式 | script 隐含 inline,style 要求不 inline |
| 默认管线 | 打包、去重、TS、import | 按页面去重,多实例要分派 |
| data-astro-rerun | 软导航后重跑脚本 | 仅 ClientRouter 场景;滥用重复绑事件 |
| 默认 scoped | 编译期作用域隔离 | 命中不了岛内部 |
| PUBLIC_ 前缀 / import.meta.env | 公开变量 / 构建期注入 | 值硬编码进产物,密钥不能放 |
| astro:env schema / getSecret | 类型化变量 / 运行时读秘密 | secret 只有 server 输出才真”运行时” |
延伸阅读
指令机制、脚本管线与注水决策的完整讲解见Astro 语法要点;这些 API 组合成真实项目的全过程见用 Astro 做一个极速文档站;按阶段串起本系列与相关文章的路径见Astro 学习路线;最基础的三件套(页面、组件、岛)回第一个 Astro 应用。
版本核实(2025-02-22 撰写时检索):本篇基线为 Astro 5.2.x 稳定线(GitHub releases 口径)。Content Layer API(content.config.ts、glob() loader、getCollection/getEntry/render(entry)、entry.id)为 Astro 5.0 引入的现行 API,legacy 集合(type: 'content')已弃用;astro:content 导出 Zod 3,collections schema 用它;Node 基线为 18.17+ / 20+;astro:env 自 Astro 5.0 稳定;client:* 五条指令、模板指令(class:list、set:html、set:text、is:inline、is:global、is:raw、define:vars)、脚本默认处理管线、data-astro-rerun、transition:* 均为官方指令参考现行内容。安装命令不钉版本号,以 docs.astro.build 为准。