Astro搭建自己的博客教学
📅发布日期:7/13/2025
第1课 astro-01-project-init.md
# 第 1 课:Astro 项目初始化 + 原理与结构
## 🚀 什么是 Astro?
Astro 是一个现代静态网站生成器(SSG),支持多框架集成(React、Vue、Svelte 等),以构建高性能、极简的静态网站和博客为目标。它默认生成纯静态页面,页面加载快、SEO 友好,且支持按需加载 JavaScript,避免不必要的前端负担。
相较于 Next.js、Nuxt 等,Astro 更专注静态内容生成,适合博客、文档和个人主页。
---
## 🚀 创建项目
打开终端,运行:
```bash
npm create astro@latest
选择模板时:
- blog:带有博客示例页面、文章内容等,适合直接开始写博客
- minimal:极简模板,适合完全自定义
完成后进入项目目录:
cd my-blog
npm install
npm run dev
🧠 项目结构解读
my-blog/
├── public/ # 静态资源(图片、图标),直接拷贝到构建后的根目录
├── src/
│ ├── pages/ # 页面文件夹,文件名对应网站路由(URL路径)
│ ├── layouts/ # 页面模板,复用相同的页眉页脚等结构
│ ├── components/ # 组件,封装可复用的小模块,如按钮、Callout等
├── astro.config.mjs # Astro 配置文件,定义构建、集成、路径等设置
目录说明
- pages/ 里的
.astro或.md文件会自动映射成网站页面,例如pages/index.astro对应/首页。 - layouts/ 用来定义页面共用结构。单独写一个
Layout.astro,各页面通过包裹实现布局复用。 - components/ 里放功能性组件,方便在多页面调用,提升代码复用率。
- public/ 放静态资源,不经过编译,直接拷贝到最终网站目录。
小结
本课你学会了:
- Astro 是什么,它适合什么场景
- 如何用
npm create astro快速创建项目 - 项目目录结构及功能划分
- Astro 页面基于文件路由自动映射原理
进阶阅读
- Astro 官方文档
- 文件路由机制介绍:页面文件名如何映射 URL
---
# 第2课 astro-02-content-collections.md
```md
# 第 2 课:写博客文章 + 内容集合原理
---
## 📁 什么是内容集合(Content Collections)?
Astro 通过内容集合管理博客文章、页面等内容,结合 [Zod](https://zod.dev) 进行数据结构验证,确保内容格式正确。
---
## 📁 创建内容集合目录
```bash
mkdir -p src/content/blog
创建示例文章 src/content/blog/2025-07-08.md:
---
title: 我的第一篇博客
description: 从零开始学 Astro
pubDate: 2025-07-08
tags: ["astro"]
---
欢迎来到 Astro 博客!
注意:
---中为 Frontmatter,定义元数据pubDate最好是 ISO 格式或YYYY-MM-DD
🧪 配置内容集合 Schema(验证规则)
src/content/config.ts:
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { blog };
为什么要 Schema?
- 规范内容格式,减少写错字段的风险
- Astro 运行时会根据 Schema 验证内容,报错提醒你修正
📄 创建博客列表页 /blog
src/pages/blog.astro:
---
import { getCollection } from "astro:content";
const posts = await getCollection("blog");
---
<ul>
{posts.map(post => (
<li><a href={`/blog/${post.slug}/`}>{post.data.title}</a></li>
))}
</ul>
原理说明
getCollection("blog")获取src/content/blog下所有文章,返回包含slug、data(frontmatter)和body内容post.slug是文件路径生成的 URL 片段,作为链接路径- 通过循环渲染动态生成列表
🧭 创建博客详情页 [...slug].astro
---
import { getCollection, getEntryBySlug } from "astro:content";
import { Markdown } from "astro/components";
import Layout from "../../layouts/Layout.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map(post => ({ params: { slug: post.slug.split("/") } }));
}
const slug = Astro.params.slug.join("/");
const post = await getEntryBySlug("blog", slug);
if (!post) throw new Error("文章不存在");
---
<Layout>
<h1>{post.data.title}</h1>
<Markdown content={post.body} />
</Layout>
原理说明
[...slug].astro是捕获路由,支持多层路径,如/blog/2025/07/08getStaticPaths生成所有文章的路由路径,确保静态生成getEntryBySlug根据 URL 参数获取对应文章数据和内容- 使用
Markdown组件渲染文章正文
小结
本课你学会了:
- 内容集合的概念及 Schema 验证
- 动态获取文章列表及渲染
- 捕获路由及详情页静态生成原理
进阶阅读
---
# 第3课 astro-03-notion-style-ui.md
```md
# 第 3 课:构建 Notion 风格博客 UI
---
## 🎨 设置全局样式
`src/styles/global.css`:
```css
:root {
--bg: #fff;
--fg: #111;
--font-body: 'Noto Sans SC', sans-serif;
}
:root[data-theme="dark"] {
--bg: #1e1e1e;
--fg: #fff;
}
body {
background: var(--bg);
color: var(--fg);
font-family: var(--font-body);
padding: 2rem;
max-width: 720px;
margin: auto;
}
原理解释
- CSS 变量(Custom Properties)定义颜色、字体,方便主题切换
- 通过
data-theme="dark"选择器重写变量实现暗黑模式 max-width设定页面宽度,内容居中,模仿 Notion 简洁排版
💬 Callout 组件
src/components/Callout.astro:
---
const { type = "info", icon = "💡" } = Astro.props;
---
<div class="callout {type}">
<strong>{icon}</strong>
<div><slot /></div>
</div>
<style>
.callout {
padding: 1rem;
border-left: 4px solid var(--fg);
background: #f9f9f9;
margin: 1.5rem 0;
border-radius: 6px;
display: flex;
gap: 1rem;
}
</style>
原理解释
- 组件接受
type和icon参数,自定义显示风格 - 通过
<slot />插槽显示调用时包裹的内容,提升复用性 border-left和背景色模仿 Notion 风格强调提示块
小结
本课你学会了:
- CSS 变量管理全局主题色
- Astro 组件参数传递及插槽机制
- 如何用组件封装样式,提升 UI 可复用性
进阶阅读
---
# 第4课 astro-04-dark-mode.md
```md
# 第 4 课:夜间模式实现 + 原理详解
---
## 🌙 CSS 变量控制颜色
```css
:root {
--bg: #fff;
--fg: #111;
}
:root[data-theme="dark"] {
--bg: #1e1e1e;
--fg: #fff;
}
原理说明
- 利用 CSS 自定义属性定义颜色变量,方便动态切换
- 给
<html>标签添加data-theme="dark"属性时,CSS 变量被覆盖,页面自动变暗
🌓 加入切换按钮
Layout.astro 中添加:
<button id="theme-toggle">🌓</button>
<script>
const html = document.documentElement;
// 页面加载时读取本地存储的主题设置,避免闪白
const theme = localStorage.getItem("theme");
if (theme === "dark") html.setAttribute("data-theme", "dark");
// 点击切换按钮,切换主题,写入本地存储,保证刷新后保持
document.getElementById("theme-toggle")?.addEventListener("click", () => {
const isDark = html.getAttribute("data-theme") === "dark";
if (isDark) {
html.removeAttribute("data-theme");
localStorage.setItem("theme", "light");
} else {
html.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
}
});
</script>
原理说明
localStorage用于在浏览器存储用户偏好,页面刷新也能记住设置- 通过
data-theme属性控制 CSS 变量,简洁高效 - 按钮监听点击事件,动态更新属性,实现实时切换
小结
本课你学会了:
- CSS 变量动态主题切换的机制
- 利用
localStorage实现主题持久化 - 如何通过操作 DOM 属性,实现亮暗主题的切换
进阶阅读
---
以上4个文件,内容细化并且涵盖你提到“写错”的地方也已修正。
你需要我帮你生成这些文件的真实文件到你的项目目录?还是导出为 ZIP 下载包?