从代码看这个博客:项目结构与运行流程
沿 URL、Content Collections、MDX 渲染、静态生成与 GitHub Pages 发布链路,定位这个 Astro 博客的一次请求和构建。
本文目录 6 节 · 点击展开
这个博客在线上没有常驻应用服务器:页面与文章在构建阶段组合成静态文件,访问时由 GitHub Pages 直接返回结果。理解代码时,不必通读仓库;沿一条 URL 反查到页面入口,再顺着内容、渲染和构建往下走即可。
系列上一篇《这个博客是怎么搭起来的》解释仓库、内容边界、规则与发布责任;本篇只回答:一个 URL 或一次构建,究竟经过哪些文件和 Astro 能力。
- 01URL找到页面入口
- 02Content读取并校验文章
- 03Render组合 MDX 与布局
- 04Output生成静态文件
从 URL 反查:页面文件就是路由入口
src/pages 下的文件Astro 使用文件路由;静态页面直接对应文件,方括号目录或文件名表示构建时生成的动态参数路径。
/src/pages/index.astro当前转交给 home-redesign-1.astro 渲染首页。
/articles/src/pages/articles/index.astro读取公开文章,组织分类、标签、排序与文章列表。
/articles/{slug}/src/pages/articles/[...slug].astro用 getStaticPaths() 为每篇公开文章生成详情路径。
/articles/category/{category}/src/pages/articles/category/[category].astro为固定分类生成聚合页。
/articles/tag/{tag}/src/pages/articles/tag/[tag].astro从公开文章标签生成聚合路径。
/series/{series}/src/pages/series/[series].astro按 series 元数据和文章顺序生成系列页。
/rss.xmlsrc/pages/rss.xml.ts把公开文章映射为 RSS item。
文章怎样进入 Content Collection
src/content.config.ts 是文章字段的代码边界;分类与系列合法值分别来自 src/data/categories.ts 和 src/data/series.ts。
src/content/posts/**/*.{md,mdx}正文与 frontmatter 一起进入 posts collection。
defineCollection({ type: 'content' })Zod 校验字段类型、默认值、合法分类与系列 ID。
getCollection('posts')页面、布局和 RSS 从同一个集合读取文章。
!draft && !private公开入口统一排除草稿和私密文章。
title · description · date · updated?标题、摘要与时间信息。
category · tags · minutes · featured分类、检索、阅读时间与精选状态。
series? · seriesOrder?可选系列 ID 与正整数顺序。
draft · private两个字段默认都是 false;公开页面同时过滤两者。
const posts = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
category: z.enum(categories),
draft: z.boolean().default(false),
private: z.boolean().default(false),
}),
});const posts = (await getCollection('posts'))
.filter((post) => !post.data.draft && !post.data.private)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());schema 能确认字段是否合法,页面过滤决定内容是否进入公开入口。两者解决的是不同问题:前者阻止结构错误,后者实施发布边界。
一篇 MDX 详情页怎样完成渲染
详情页入口是 src/pages/articles/[...slug].astro。它既负责生成路径,也负责渲染文章与系列导航。
getStaticPaths()读取公开 posts,把每篇 post.slug 映射为静态路径和 props。
params: { slug: post.slug }render(post)返回正文组件 Content 与标题数据 headings。
const { Content, headings } = await render(post);MDX integration 让正文保留 Markdown,同时导入文章专属或现有 Astro 组件。
integrations: [mdx()]SiteLayout.astro + [...slug].astroSiteLayout 提供导航、搜索、主题与站点外壳;文章路由组织侧栏、正文和深度为 2 或 3 的目录 headings。
<Content />src/styles/global.css + article CSS全局文件控制站点外壳;单篇独有信息图用文章 class 限定,避免污染其他页面。
html[data-theme='dark']浏览器收到的是已经生成的 HTML、CSS 与必要脚本;不会在每次访问时重新查询文章数据库。
MDX 组件不是独立应用层。它们在构建时成为文章渲染树的一部分;页面外壳与全局主题仍由 SiteLayout 和 global.css 负责。
静态构建怎样把所有入口合成产物
当前 astro.config.mjs 配置站点地址并启用 MDX,没有配置 base;输出沿 Astro 当前默认静态站点方式生成。
src/pages/固定入口与参数化入口
posts collection公开文章与 frontmatter
components · layouts · styles渲染能力与主题
public/按原路径复制的公开文件
Content schema 先检查文章;页面收集路径;MDX 与 Astro 组件编译;静态入口写入产物目录。
npm run buildrss.xmldist/。本地运行和线上发布是两条不同链路
开发服务可快速反馈,但上线前仍要以测试和静态构建为准;工作流实际运行和线上结果属于外部实时状态。
package.json- Dev启动开发服务,边改边看。
- Test运行 Vitest 项目测试。
- Build执行正式静态构建。
- Preview预览已经生成的构建产物。
npm run dev
npm test
npm run build
npm run previewgit push main或 workflow_dispatch.github/workflows/deploy.yml- Checkout
actions/checkout@v6 - Build
withastro/action@v6,package manager 为 npm。 - Deploy
actions/deploy-pages@v5等待 build job。 - HostPages 返回静态站点。
出问题时按现象定位代码,不要从根目录盲找
下面不是完整目录说明,而是从现象到入口、继续追踪点和验证动作的最短排查图。
src/pages/按访问路径找到同名页面;参数路由继续看 getStaticPaths()。
检查 schema、draft、private、分类、系列与页面过滤条件。
确认 render(post)、<Content />、H2/H3 headings 和组件 import。
导航、主题和文章外壳属于全局;单篇信息图只排查文章专属 class。
验证:浅色、深色与 390px 页面沿文件和行号检查 MDX 语法、导入路径、schema 与构建期代码。
验证:npm test + npm run build确认 main 推送、build/deploy jobs、Pages Source 和实际访问结果。
状态:需运行验证需要理解这些文件为何这样分区,再回到系列上一篇的系统蓝图;需要修代码,则继续沿本篇的最短执行链定位。