约 2 分钟更新于

Astro 主题开发速查:从配置到部署

一篇文章带你过完 Astro 主题开发的完整链路:配置文件、路由约定、集合 schema、全局样式与构建部署,附常用命令与坑位提醒。

开发一个 Astro 主题,核心是理解四个约定:配置文件、页面路由、内容集合和样式入口。本文以本主题为例,做一个速查。

一、配置文件

astro.config.mjs 是主题的总开关:

import { defineConfig } from 'astro/config';
import { headingAnchors } from './src/plugins/heading-anchors.mjs';

export default defineConfig({
  site: 'https://example.com',
  markdown: {
    shikiConfig: { theme: 'github-light', wrap: true },
    rehypePlugins: [headingAnchors],
  },
});
  • site:部署域名,决定 canonical、RSS、sitemap 的绝对地址,务必改掉
  • shikiConfig:代码高亮主题,github-light 在深色模式下会偏亮,可以换成 github-dark-dimmed 配合 [data-theme='dark'] 切换
  • rehypePlugins:Markdown 渲染后的处理插件,这里给 h2-h4 添加锚点链接

二、路由约定

src/pages/ 下的文件路径就是 URL:

src/pages/
├── index.astro        → /
├── archive.astro      → /archive
├── about.astro        → /about
├── search.astro       → /search
├── tags/
│   ├── index.astro    → /tags
│   └── [tag].astro    → /tags/<标签>
├── posts/
│   └── [id].astro     → /posts/<文章id>
├── page/
│   └── [page].astro   → /page/<页码>
├── rss.xml.js         → /rss.xml
└── sitemap.xml.js     → /sitemap.xml

动态路由用 [参数] 命名,配合 getStaticPaths() 在构建时生成静态页面。

三、动态路由的写法

文章页是理解动态路由最好的例子:

---
import { getCollection, render } from 'astro:content';
import PostLayout from '../../layouts/PostLayout.astro';

export async function getStaticPaths() {
  const posts = await getCollection('post', ({ data }) => !data.draft);
  return posts.map((post) => ({ params: { id: post.id }, props: { post } }));
}

const { post } = Astro.props;
const { Content, headings } = await render(post);
---

<PostLayout post={post} headings={headings} prev={undefined} next={undefined}>
  <Content />
</PostLayout>

要点:

  1. getStaticPaths 返回的 props 会注入当前页面
  2. render(post) 返回 { Content, headings },前者渲染正文,后者给目录用
  3. 文章 ID 即 src/content/post/ 下的相对路径,如 hello-world

四、全局样式

src/styles/global.css 通过 BaseHead 引入。设计令牌(design tokens)集中在 :root:

:root {
  --c-bg: #ffffff;
  --c-fg: #16161a;
  --w-content: 46rem;
  --font-serif: 'Iowan Old Style', 'Palatino Linotype', Georgia, 'Noto Serif SC', serif;
}

[data-theme='dark'] {
  --c-bg: #101012;
  --c-fg: #e8e8ea;
}

深色模式通过 html[data-theme='dark'] 覆盖变量实现,BaseHead 里的内联脚本在首帧前读取 localStorage 或系统偏好,避免闪烁。

五、常用命令

命令作用
npm run dev启动开发服务器,localhost:4321
npm run build构建到 dist/,输出静态站点
npm run preview本地预览构建产物
npm run astro -- check类型与语法检查

六、部署

构建产物是纯静态文件,任何静态托管都行:Vercel、Netlify、Cloudflare Pages、GitHub Pages,甚至一个 Nginx 目录。只需注意:

  • 环境变量或配置里的 site 必须与线上域名一致
  • 如果放在子路径,需要给 astro.config.mjsbase 配置
  • 提交前跑一次 astro build,确认没有报错再推送

七、坑位提醒

  • 标题重复:headings 的 slug 由标题生成,重复标题会导致锚点冲突,文章内标题尽量唯一
  • </script> 转义:往 HTML 里内联 JSON 时,把 < 转成 \u003c,避免提前闭合脚本标签
  • 日期字段:frontmatter 里的日期要写 YYYY-MM-DD,配合 z.coerce.date() 自动转换
  • 草稿发布:draft: true 的文章不会出现在列表和 RSS 中,但本地开发时仍可见,方便预览

掌握以上内容,一个主题的骨架就完成了。剩下的,就是把你自己的审美填进去。