使用 Astro 创建博客网站





5.00/5 (2投票s)
本文将介绍如何使用开源的 Astro 包来创建一个功能齐全的博客网站。
对于我即将推出的博客,我决定不想使用传统的 CMS 平台,如 WordPress。我是一名程序员,我宁愿使用一个从源代码生成博客的工具。这些工具被称为静态网站生成器(SSG),其中知名度较高的有 Hugo、Jekyll、Gatsby 和 Astro。我选择 Astro 是因为其对 TypeScript 的支持,尽管学习它花了一些时间,但我对其灵活性和性能感到满意。
本文的目的是介绍如何使用 Astro 构建一个功能齐全的博客网站。第一部分将介绍如何创建一个示例博客项目,然后从该项目中生成博客文件。接着,我们将探讨 Astro 文件的格式以及构成 Astro 项目的文件。文章的最后部分将介绍路由和自定义。
1. 入门
Astro 的使命是将包含 Astro 文件(*.astro)的项目转换为包含网站文件(主要是 *.html)的文件夹。与其从头开始,不如创建一个 Astro 的默认博客项目并按需进行自定义。本节将介绍如何创建默认项目,将其转换为博客网站,然后在浏览器中查看该网站。
1.1 创建项目
Astro 的访问通过 Node 包管理器(npm)提供。Node 指的是Node.js,它是一个运行时环境,可以访问超过两百万个软件包。其中绝大多数包都是免费的,因此,如果您正在构建 Web 应用程序,您可能会找到几个有用的包。
在使用 npm 创建 Astro 项目之前,您需要安装 Node.js。下载页面是 https://node.org.cn,您可以点击适合您操作系统和处理器类型(可能是 64 位)的链接来下载安装程序。本文假定您运行的是 Node 22 或更高版本。
安装 Node 后,您就可以从命令行运行 npm 了。每个命令都以 npm cmd_name
开头,其中 cmd_name
标识命令。要创建新的 Astro 项目,请执行以下命令:
npm create astro@latest
在创建新项目之前,Astro 会询问六个问题。
- 应在何处创建此项目? - 输入项目文件夹的所需位置,可以是绝对路径(C:\newblog)或相对于当前目录的路径(newblog)。
- 您希望如何启动项目? - 您可以在“Empty”(空)、“Use blog template”(使用博客模板)和“Include sample files”(包含示例文件)之间进行选择。本文重点介绍博客,因此请选择“Use blog template”(使用博客模板)。
- 您是否打算编写 TypeScript? - 您可以选择编写 TypeScript 代码(Yes)或 JavaScript 代码(No)。对于本文,请选择Yes。
- TypeScript 应有多严格? - 您可以在“Relaxed”(宽松)、“Strict”(严格)和“Strictest”(最严格)之间进行选择。对于本文,Strict(严格)即可。
- 安装依赖项? 选择Yes,让 Node 安装创建 TypeScript Astro 项目所需的包。
- 初始化新的 Git 存储库? 选择Yes,让 Node 创建一个 Git 存储库以启用项目的版本控制。
回答完这些问题后,包管理器将下载 Astro 包及其依赖项,然后创建一个简单的博客网站项目。表 1 列出了项目中顶级目录的文件和文件夹。
文件名/文件夹名 | 描述 |
---|---|
.git | Git 存储库文件夹 |
.vscode | Visual Studio Code IDE 的设置 |
node_modules | Astro 所需的 Node 依赖项 |
public | 将部署到网站的静态资源 |
src | Astro 项目的源文件 |
.gitignore | 不包含在 Git 存储库中的文件列表 |
astro.config.mjs | Astro 配置设置 |
package.json | 项目配置设置 |
package-lock.json | 列出了依赖项及其依赖项 |
README.md | 项目描述 |
tsconfig.json | 包含 TypeScript 编译器设置 |
您可以保留大多数这些文件不动,但 src 文件夹值得关注。它包含 Astro 项目的源文件,本文的大部分内容都与此目录的内容有关。但在深入细节之前,最好先创建并查看博客。
1.2 构建和查看博客
创建 Astro 项目后,很容易将所有 *.astro 文件编译成 *.html 文件。在项目的顶级目录中打开命令提示符并执行以下命令:
npm run build
随着构建的进行,该工具将显示项目文件以及从中生成的 HTML 文件。以下文本是一个示例:
▶ src/pages/about.astro
└─ /about/index.html (+12ms)
▶ src/pages/blog/index.astro
└─ /blog/index.html (+13ms)
▶ src/pages/index.astro
└─ /index.html (+3ms)
构建完成后,生成的文件将存储在一个名为 dist 的新顶级目录中。您可以通过在浏览器中打开 HTML 文件来查看它们。您还可以通过执行 npm run dev
来启动本地服务器。然后,在浏览器中访问 https://:4321 来查看博客。图 1 展示了博客主页的简化图示。
默认博客中的每个页面都有一个标题和一个页脚。它们之间的内容由一个或多个 Astro 文件的模板决定。下一节将介绍模板。
2. Astro 文件格式
如果您查看项目的 src 文件夹,您会发现大多数文件都是 Astro (*.astro) 文件。在我们深入研究项目之前,了解这些文件的内容以及内容的结构非常重要。每个 Astro 文件(最多)有两个部分:
- frontmatter - 导入组件、定义变量并执行其他操作的 TypeScript
- template - 在构建过程中渲染成 HTML 的标记,可以访问 frontmatter 中的组件和变量
frontmatter 是可选的,但如果存在,它必须包含在由三个连字符组成的行之间。这些被称为代码围栏,以下文本展示了代码围栏如何分隔 frontmatter 和模板:
--- frontmatter written in TypeScript --- template written in markup
本讨论将介绍这两个部分。如果您对 TypeScript 和 HTML 有扎实的掌握,那么处理 Astro 文件将毫无问题。
2.1 Frontmatter
Astro 文件的 frontmatter 包含在模板渲染之前执行的代码。最常见的 frontmatter 操作包括导入数据结构以及声明变量和类型。
可以使用熟悉的 import
语句导入结构。这些语句可以访问 JavaScript 文件(*.js)、TypeScript 文件(*.ts)和其他 Astro 文件(*.astro)。例如,如果一个名为 XYZ
的数据结构定义在 ABC.astro 中,则可以使用以下代码导入它:
import XYZ from 'ABC.astro';
声明变量和类型同样简单。let
语句中的变量可以更新,const
语句中的变量不能更新,而 type
语句用于声明自定义类型。以下是一些典型的声明:
const today = new Date();
type Props = CollectionEntry<'blog'>['data'];
Astro 文件的 frontmatter 不仅限于导入和声明,但我遇到的代码中,这些语句占了绝大部分。
2.2 模板
每个 Astro 文件都有一个将在构建过程中转换为 HTML 的模板。这些部分以类似于 JavaScript XML (JSX) 的格式编写,而 JSX 又类似于 HTML。关于模板有两点需要了解:
- 模板可以使用常规的 HTML 标签,如
<div>
、<a>
、<head>
和<body>
。它还可以从导入的组件创建 HTML 标签,稍后章节将介绍组件。 - 模板可以包含用花括号括起来的 TypeScript 变量和表达式。例如,如果 x 是在 frontmatter 中声明的变量,那么它的值可以通过
{x}
插入到模板中。
为了演示这些要点,假设一个 Astro 文件的 frontmatter 导入了一个名为 MyComp
的组件,并声明了一个名为 compName
的变量。在模板中,以下标签创建了 MyComp
的一个实例,并将其 name 属性设置为 compName
:
<MyComp name={compName} />
当项目构建时,MyComp
的模板将被插入,其 name
属性将被设置为 compName
。
Astro 的模板语法在很多方面都类似于 JSX,但有一个主要的区别:Astro 文件的模板在构建后不会改变。也就是说,frontmatter 中的代码只会在构建期间执行,因此插入的变量只能取一个值。
3. 探索项目
此时,您应该已经熟悉 Astro 和 Astro 文件了。现在我们将深入研究项目的 src 目录。如果您打开此目录,您会发现表 2 中列出的文件夹和文件。
文件夹/文件名 | 描述 |
---|---|
pages | 表示要生成的页面的 Astro 文件(*.astro) |
components | 定义组件的 Astro 文件(*.astro) |
content | 提供博客帖子的 Markdown 文件(*.md 或 *.mdx) |
layouts | 定义页面可重用结构的 Astro 文件(*.astro) |
styles | 定义网站样式设置的 CSS 文件(*.css) |
consts.ts | 可在整个项目中访问的全局常量 |
env.d.ts | 告诉 TypeScript 编译器在哪里可以找到 Astro 的类型声明 |
本节的目标是探讨这些文件夹并解释它们的文件功能。您对项目结构的理解越深入,就越容易自定义项目以适应您的博客。
3.1 Pages 文件夹
如果您查看 src/pages 文件夹,您会找到 index.astro、about.astro 以及一个名为 blog 的文件夹,其中包含另一个 index.astro 和一个不寻常但重要的文件 [...slug].astro。在构建过程中,src/pages 中的每个文件都将转换为一个或多个 HTML 文件。
如果您查看这些文件,您会发现它们的 frontmatter 包含如下所示的 import
语句:
import Header from '../components/Header.astro';
import Layout from '../layouts/BlogPost.astro';
Header
是从 components 文件夹中的一个文件导入的,因此可以安全地假设它是一个组件。Layout
是从 layouts 文件夹中的一个文件导入的,因此它是一种特殊类型的组件,称为布局。稍后将对组件和布局进行介绍。
如果您比较 index.astro 和 about.astro,您会发现它们的模板大不相同。index.astro 像常规 HTML 文件一样包含 <head>
和 <body>
标签,但 about.astro 不包含任何这些标签。这是因为 about.astro 的页面结构是使用布局定义的,我稍后将解释什么是布局。
3.2 Components 文件夹
与许多 Web 框架一样,Astro 是一个以组件为中心的工具集。Astro 文件可以通过 import
语句访问组件,并将它们插入到模板中,就像它们是常规 HTML 元素一样。
每个组件都在一个单独的 Astro 文件中定义,包含 frontmatter 和模板部分。组件的模板可以访问两个重要功能:
- props - 可用于每个组件的全局属性
- template directives - 控制组件/元素如何行为的特殊属性
本讨论将介绍这些功能。
3.2.1 访问 Props
假设一个名为 MyComp
的组件有两个名为 attr1
和 attr2
的属性。再假设一个布局组件导入 MyComp
并将其插入到其模板中,如下所示:
<code><MyComp attr1="abc" attr2="xyz" /></code>
在其 frontmatter 中,MyComp
组件可以通过全局 Astro.props
值(无需导入)访问属性值。以下代码可以说明其工作原理:
const { attr1, attr2 } = Astro.props;
此代码声明了变量 attr1
和 attr2
,并将它们的值分别设置为组件属性的值(在此示例中为“abc”和“xyz”)。这些变量可以在模板的任何地方使用,方法是用花括号括起来:{attr1}
和 {attr2}
。
为了启用类型检查,许多组件会创建一个接口,为传入的属性分配类型。在以下代码中,接口包含 attr1
和 attr2
,并将它们都分配给 string
类型:
interface Props {
attr1: string;
attr2?: string;
}
如果任何一个属性不是字符串,Astro 将在构建过程中产生警告/错误。attr2
后面的问号告诉 Astro 该属性是可选的。
3.2.2 Template Directives
模板指令是可以在 Astro 模板中的组件或其他 HTML 元素中插入的特殊属性。每个指令名称由两个由冒号分隔的单词组成,有三个通用指令:
class:list
- 将元素数组转换为字符串set:html
- 将字符串注入元素(类似于innerHTML
)set:text
- 将文本注入元素(类似于innerText
)
模板可以包含 JavaScript,但默认情况下,组件不会在客户端进行水合。要控制何时对组件进行水合,您需要在组件中插入一个客户端指令。Astro 提供了六个客户端指令:
client:load
- 页面加载时立即对组件进行水合client:idle
- 页面加载后,在requestIdleCallback
事件触发后对组件进行水合timeout
- 在进行水合之前等待的最大时间client:visible
- 当组件进入用户视口时对其进行水合client:media
- 当满足 CSS 媒体查询时对组件进行水合client:only
- 跳过服务器渲染,仅在客户端进行渲染
如果您查看 src/components 文件夹中的 HeaderLink.astro 文件,您会发现它使用 class:list
指令来设置锚点的文本。不幸的是,没有一个组件模板演示了客户端指令的用法。
3.3 Layouts 文件夹
src/layouts 目录中的 Astro 文件定义了称为布局的特殊组件。布局的目标是指定可在整个博客中使用的页面结构。src/pages 目录中的 Astro 文件可以导入布局来定义页面的基本元素,如 <html>
、<head>
、<body>
、<style>
等。
例如,如果您查看 src/pages/about.astro,您会发现它的 frontmatter 和模板具有以下结构:
---
import Layout from '../layouts/BlogPost.astro';
---
<Layout ...>
...
</Layout>
frontmatter 导入了布局 组件,它在模板中用作顶级元素。这提供了页面的结构,如果您查看 BlogPost.astro,您会发现它的模板具有以下内容:
<html ...>
<head>
<BaseHead ... />
<style>
...
</style>
</head>
<body>
<Header />
<article>
<div class="hero-image">
...
</div>
<div class="prose">
<div class="title">
...
</div>
<slot />
</div>
</article>
<Footer />
</body>
</html>
如所示,布局包含 BaseHead
、Header
和 Footer
等组件。BaseHead
的模板由 <meta>
和 <link>
元素组成,在构建过程中,这些元素将被插入到使用此布局的每个页面的 <head>
中。
在 class 为 prose
的 <div>
元素中,有一个名为 <slot />
的重要元素。这就是布局组件中的内容将被放置的地方。回到 about.astro 中的模板,<Layout>
和 </Layout>
之间的标记将被放置在 Layout
组件模板的 <slot />
元素中。
大多数博客每页显示一篇帖子。对于 Astro 博客,这些页面的结构由一个布局组件决定。这使得正确编写布局组件变得很重要。
3.4 Content 文件夹
本质上,Astro 项目的目的是打包博客的内容以便部署。如果您查看 src/content,您会找到一个名为 blog 的文件夹和一个名为 config.ts 的文件。blog 文件夹中的文件包含博客的帖子,这些帖子使用 Markdown (*.md) 和 Markdown eXtended (*.mdx) 编写。config.ts 文件导出一个集合,允许组件访问博客的帖子。
3.4.1 Content 文件
得益于 Github,Markdown 语言在文本格式化方面已变得非常流行。如果一个内容文件的后缀是 *.md,那么它的文本可以使用 Markdown 的语法规则进行格式化。表 3 列出了九种基本规则,并对每种规则进行了描述。
格式规则 | 示例 | 描述 |
---|---|---|
标题 | # 一级标题 ## 二级标题 | # 号越多, 标题越小 |
斜体 | * 斜体文字 * | 一个星号打印斜体文字 |
粗体 | ** 粗体文字 ** | 两个星号打印粗体文字 |
无序列表 | - 无序 - 无序 | 连字符创建无序列表项 |
有序列表 | 1. 项 1 2. 项 2 | 数字-点-空格创建项目 在有序列表中 |
代码 | `代码字体` | 反引号打印代码字体文本 |
水平线 | --- | 三个连字符创建一条水平线 |
Image |  | 方括号中的替代文本, 然后是括号中的图像文件 |
超链接 | [文本](https://www.xyz.com) | 方括号中的打印文本, 然后是括号中的 URL |
除了这些规则之外,Markdown 还支持自己的 frontmatter,通常用于提供元数据。与 Astro 文件一样,Markdown 文件中的 frontmatter 也用代码围栏包围。与 Astro 文件不同,Markdown frontmatter 是用 YAML 编写的,这意味着名称和值由冒号分隔。以下文本可以说明其外观。
--- title: "Title" author: "Tom Smith" --- # This is an important heading!
如果一个文件的后缀是 *.mdx,那么它就是用 Markdown eXtended (MDX) 编写的,它将 Markup 格式的简洁性与 Astro 文件的灵活性结合起来。MDX 是 Markdown 的超集,因此它支持常规的格式规则和 frontmatter。此外,还有四点需要了解:
- TypeScript
import
/export
语句可以插入到文本的任何位置。 - 导入后,组件可以使用类似于 Astro 模板的标记插入到文本中。
- frontmatter 中的名称可以作为
frontmatter
类的属性访问。例如,如果title
在 frontmatter 中被赋值,那么它可以在文本中作为{frontmatter.value}
访问。 - MDX 可用于 src/pages 中的文件以及 src/content 中的文件。
如果您查看项目中的 src/content/blog 文件夹,您会看到一个名为 using-mdx.mdx 的文件。这演示了 MDX 如何在博客文章中使用。
3.4.2 Content Collections 和 config.ts
src/content 中的任何文件都称为内容条目,src/content 中的任何顶级文件夹都称为内容集合。每个集合包含特定类型的内容,因此如果您的站点包含博客文章和源代码文件,它们应该存储在单独的集合中。
在代码中,通过调用 astro:content
导出的 defineCollection
函数来创建内容集合。在示例项目中,这由 src/content 中的 config.ts 文件调用,其完整代码如下:
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
// Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
description: z.string(),
// Transform string to Date object
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(),
}),
});
export const collections = { blog };
在此代码中,schema
属性访问每个内容条目的 frontmatter。默认情况下,title
、description
和 pubDate
字段是必需的,而 updatedData
和 heroImage
字段是可选的。export
语句使内容集合在整个项目中可用。稍后,我将解释组件如何访问此内容并将其插入页面。
3.5 Styles
如果您打开 src/styles 目录,您会发现一个名为 global.css 的文件。此样式表中定义的规则适用于整个项目,无需导入。
您可以更改博客的字体,方法是更改 font-face
规则。body
规则的设置尤为重要,因为它们适用于网页正文中的每个组件。
4. 路由
如果您通过运行 npm run build
来构建默认项目,则生成的博客文件将存储在项目的 dist 文件夹中。此文件夹中的 HTML 文件是从项目 src/pages 和 src/content 文件夹中的文件生成的。
表 3 阐明了项目六个源文件和生成文件之间的关系。第一列列出了源文件的路径,第二列列出了生成文件的路径,第三列列出了生成文件的 URL。URL 是相对于 www.example.com 给出的,因为这是 astro.config.mjs 中指定的默认站点。
源文件 | 生成的文件 | URL |
---|---|---|
src/pages/index.astro | dist/index.html | www.example.com |
src/pages/about.astro | dist/about.html | www.example.com/about |
src/pages/blog/index.astro | dist/blog/index.html | www.example.com/blog |
src/content/blog/first-post.md | dist/blog/first-post/index.html | www.example.com/blog/first-post |
src/content/blog/second-post.md | dist/blog/second-post/index.html | www.example.com/blog/second-post |
src/content/blog/third-post.md | dist/blog/third-post/index.html | www.example.com/blog/third-post |
如所示,Astro 为 src/content/blog 中的每个 Markdown 文件(*.md)创建一个目录,每个目录都有一个 index.html 文件。如前所述,Astro 将 src/content/blog 文件夹称为内容集合,该文件夹中的每个文件都是一个内容条目。
此表具有误导性,因为 Astro 并不直接将内容条目转换为 HTML 文件。要理解转换是如何执行的,您需要了解两个主题:
- Astro 的
CollectionEntry
类型 - src/content/blog 文件夹中的 [...slug].astro 文件
一旦您理解了这两个主题,您将对 Astro 的动态路由有一个扎实的掌握,它会自动为博客文章生成 HTML 文件。
4.1 CollectionEntry 类型
如前所述,src/content/config.ts 文件调用 defineCollection
函数,并传入一个具有 type
和 schema
属性的对象。type
属性设置为 content
,schema
包含博客文章 frontmatter 的字段。该函数的返回值是一个 CollectionConfig
。
Astro 的 getCollection
函数接受一个 CollectionConfig
并返回一个 CollectionEntry
。这个重要的对象有五个属性:
id
- 对于内容条目,这是 markdown 文件(*.md 或 *.mdx)的名称- collection- 包含该条目的内容集合的名称(
blog
) - data- 包含
CollectionConfig
的schema
属性中的字段 - slug- 作为条目 URL 最后一部分的文本
- body- 内容文件中的文本
默认情况下,Astro 将 slug
属性设置为 id
属性,方法是移除文件后缀、将每个字符转换为小写,并将每个空格和下划线替换为连字符。您可以通过在博客文章文件中添加 slug
字段到 frontmatter 来为条目设置自定义 slug。
除了这些属性之外,每个 CollectionEntry
都有一个名为 render
的方法。它编译条目的内容并返回一个 Astro 组件,该组件显示编译后的结果。
4.2 [...slug].astro 文件
/src/pages/blog 文件夹中的 [...slug].astro 文件负责为 /src/content/blog 中的每个内容条目创建页面。其内容如下:
--- import { type CollectionEntry, getCollection } from 'astro:content'; import BlogPost from '../../layouts/BlogPost.astro'; export async function getStaticPaths() { const posts = await getCollection('blog'); return posts.map((post) => ({ params: { slug: post.slug }, props: post, })); } type Props = CollectionEntry<'blog'>; const post = Astro.props; const { Content } = await post.render(); --- <BlogPost {...post.data}> <Content /> </BlogPost>
frontmatter 中的代码形成一个内容条目列表,并告诉 Astro 为列表中的每个元素创建一个页面。有四点需要注意:
- 如果 Astro 文件名用方括号括起来,其 frontmatter 可以将其名称作为变量访问。
[...slug].astro
的 frontmatter 访问一个名为slug
的变量。 - frontmatter 调用
getCollection
来访问名为blog
的集合中的CollectionEntry
对象。 - frontmatter 遍历条目并创建一个元素数组。该数组的每个元素都有一个名为
params
的属性,而每个params
都有一个名为slug
的属性,其值等于CollectionEntry
的slug
属性。 - frontmatter 导出一个名为
getStaticPaths
的函数,该函数返回第 4 步中构建的数组。当 Astro 调用此函数时,它会为数组中的每个元素创建一个目录,并将其命名为params.slug
。这解释了为什么 Astro 会创建 dist/blog/first-post、dist/blog/second-post 等。
要设置这些生成页面的内容,[...slug].astro 执行四个操作:
- frontmatter 调用每个
CollectionEntry
的 render 方法。生成的组件被赋予名称Content
。 - 模板包含一个
BlogPost
组件,该组件定义了页面的布局。 - 模板将
CollectionEntry
的data
字段传递给BlogPost
,后者可以通过Astro.props
访问它。 - 模板将
Content
组件插入到BlogPost
组件内部。结果是,CollectionEntry
内容将替换布局组件模板中的<slot />
元素。
Astro 将此页面生成过程称为静态模式,因为页面是在构建过程中生成的。Astro 还支持服务器模式,在该模式下,页面由服务器渲染。这不使用 getStaticPaths
,您可以 此处 了解更多关于服务器模式的信息。
5. 自定义博客
此时,您应该对如何向 Astro 项目添加帖子以及如何将项目转换为 HTML 有了扎实的理解。本节将介绍博客作者可能想要执行的一些自定义任务。
5.1 项目配置
如果您正在创建一个新博客,第一个要更改的文件是项目顶级目录中的 astro.config.mjs。这是项目的中心配置文件,默认情况下,其内容如下:
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
// https://astro.js.cn/config
export default defineConfig({
site: 'https://example.com',
integrations: [mdx(), sitemap()],
});
至少,您应该将 site
属性更改为您的网站 URL。如果您不想包含 MDX,可以删除第二个 import 语句,并从 integrations 数组中删除 mdx()
元素。
Astro 在 astro.config.mjs 中支持许多其他配置选项。您可以在 此处 阅读完整的列表。
5.2 Header 和 Header Links
默认博客在左上角有一个标题(Astro Blog),在上中心有三个链接(Home、Blog 和 About),在右上角有社交链接(Mastodon、Twitter 和 Github)。顶部的横幅在 src/components/Header.astro 中定义,其模板标记如下:
<h2><a href="/">{SITE_TITLE}</a></h2>
<div class="internal-links">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/about">About</HeaderLink>
</div>
<div class="social-links">
...
</div>
此标记的第一行设置了左上角的博客标题,文本从项目 src 目录中的 consts.ts 导入。此文件的默认内容如下:
export const SITE_TITLE = 'Astro Blog';
export const SITE_DESCRIPTION = 'Welcome to my website!';
您可能需要更改这些常量。此外,如果您有任何字符串希望在整个网站中使用(例如版权声明),最好将其添加到 src/consts.ts。
在 Header
组件的模板中,class 为 internal-links
的 division 创建了上中心的Home、Blog 和 About 链接。这些链接被实现为 HeaderLink
组件的实例,该组件定义在 src/components/HeaderLink.astro 中。
5.3 BaseHead 组件
如果搜索引擎优化 (SEO) 是一个关注点,您可以向 src/components/BaseHead.astro 中定义的 BaseHead
组件添加关键字和其他项。BlogPost
布局将 BaseHead
插入到使用该布局的每个页面的 <head>
元素中。
Basehead
还设置了网站的图标,以下标记设置了默认图像:
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
您可能需要更改规范 URL,该 URL 在页面可通过多个 URL 访问时设置页面的首选 URL。默认规范 URL 的设置方式如下:
<link rel="canonical" href={canonicalURL} />
BaseHead
从 BlogPost
组件接收 title
和 description
属性,该组件将它们设置为 src/consts.ts 中的 SITE_TITLE
和 SITE_DESCRIPTION
常量。在 BaseHead
模板中,这些属性用于设置页面的主要元元素:
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />
如果您希望您的博客网站能在社交媒体上分享,您可以添加由 Open Graph 协议定义的元数据。为此,BaseHead 包含以下几行:
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, Astro.url)} />
在这些标签中,变量 Astro.url
始终设置为插入这些标签的页面的 URL。
5.4 Footer 组件
在博客底部,页脚显示版权声明和社交媒体链接。Footer
组件的缩写结构如下:
<footer>
© {today.getFullYear()} Your name here. All rights reserved.
<div class="social-links">
...
</div>
</footer>
<style>
...
</style>
自然,您会想在页脚中添加您的名字。您可以设置页脚的背景颜色和填充,方法是设置 <style>
...</style>
标签中的属性。
5.5 Really Simple Syndication (RSS)
RSS 允许用户在无需手动访问网站的情况下访问博客内容。要支持 RSS,博客需要提供一个符合 RSS 2.0 标准格式的文件。该格式基于 XML,并使用 <rss>
和 </rss>
作为根元素。
如果您查看 dist 文件夹,您会发现 Astro 构建生成了一个名为 rss.xml 的文件。该文件的内容由项目 src/pages 文件夹中的 rss.xml.js 文件决定。它定义了一个名为 GET
的函数,该函数如下定义:
export async function GET(context) {
const posts = await getCollection('blog');
return rss({
title: SITE_TITLE,
description: SITE_DESCRIPTION,
site: context.site,
items: posts.map((post) => ({
...post.data,
link: `/blog/${post.slug}/`,
})),
});
}
在 RSS Feed 中,<title>
元素设置为 SITE_TITLE
,<description>
元素设置为 SITE_DESCRIPTION
。Feed 还将为每个博客文章包含一个 <item>
元素。如果您想用不同的元素自定义 RSS Feed,rss.xml.js 是要修改的文件。
历史
本文最初于 2024 年 10 月 9 日提交。