· AstroWind 中文站 · 文档 · 4 分钟阅读
模板原理拆解:从配置到静态 HTML
看懂 AstroWind 内部:config.yaml 如何变成虚拟模块、路由与固定链接怎么生成、文章如何被读取、图片与元信息如何处理。
平时你只需要碰 src/pages/、src/data/post/ 和 src/config.yaml。但当你想调试一个奇怪的 URL、接入新的内容源,或者决定要不要把这个模板当作长期底座时,就该知道它为什么这样工作。本文沿着「配置 → 构建 → HTML」走一遍。
配置不是被 import 的,而是被编译成虚拟模块
src/config.yaml 并不会被组件直接读取。vendor/integration/ 里有一个自研 Astro integration,它在构建启动时读取 YAML、做类型校验,然后暴露成 Vite 虚拟模块 astrowind:config,导出 SITE、I18N、METADATA、APP_BLOG、UI、ANALYTICS。
import { SITE } from 'astrowind:config';这么做的好处是:配置只在构建期存在,不会作为 JSON 打进客户端;同时所有组件共享同一份强类型配置。想加一个配置项,需要同时改 YAML 和 integration 里的类型定义。
路由与固定链接
src/pages/下的.astro/.md文件按文件名生成路由。[...blog]/是博客的动态路由:index.astro渲染单篇文章,[...page].astro渲染列表分页,[category]/与[tag]/分别渲染分类和标签。src/utils/permalinks.ts负责拼 URL:POST_PERMALINK_PATTERN来自apps.blog.post.permalink,支持%slug%、%category%、%year%等变量;SITE.base用于子路径部署,trailingSlash决定末尾斜杠。- 中文分类与标签通过
limax生成 slug,所以cleanSlug('教程')得到的是可安全放进 URL 的字符串。
output: 'static' 意味着所有页面都在构建期生成;博客相关路由显式声明 prerender = true,即使将来切到按需渲染也能正常工作。
内容集合与文章流水线
src/content.config.ts 用 Astro Content Layer 的 glob() 加载器读取 src/data/post/*.md|mdx,并用 zod 校验 frontmatter。src/utils/blog.ts 把每条记录规范化成统一的 Post 类型:补齐 slug、permalink、分类与标签的 slug、阅读时长,按发布日期倒序排序并过滤草稿。
首页的 BlogHighlightedPosts、文章底部的相关文章、RSS 与分页,全部复用这一份 fetchPosts() 结果,所以新增一篇 .md 文件会自动出现在所有位置。
图片与元信息
- 本地图片走
astro:assets/ Sharp,构建时生成多尺寸 WebP。 - 远程 CDN 图片交给
unpic改写 URL,由 CDN 直接提供;只有 Unpic 识别不了的域名(如 Pixabay)才在astro.config.ts的image.domains里授权,交给 Sharp 下载处理。 Metadata.astro把config.yaml的默认 SEO 与页面传入的metadata合并,输出 title、description、robots、OG / Twitter 卡片与 canonical。@astrojs/sitemap按路由生成 sitemap,astro-compress在构建末尾压缩 HTML / CSS / JS。
构建时还发生了什么
prefetch 与 <ClientRouter /> 一起提供视口内预取和无刷新导航;astro-icon 把用到的图标内联成 SVG sprite;Astro Fonts API 自托管字体;Partytown 默认关闭,只有把 hasExternalScripts 设为 true 才会把第三方脚本挪进 Web Worker。原生 CSP 在这个版本也刻意未启用,因为它与视图过渡冲突。
一个实用结论:想改行为,先找
src/config.yaml和astro.config.ts;想改内容,去src/pages/与src/data/post/;只有当这两层都不够时,才动src/components/与vendor/integration/。