Hugo 是非常棒的开源静态网站生成器,使用它可以非常简单的去搭建个人 Blog 网站。
我之前一直在使用它,直到遇到 Astro。于是我花了一天的时间,将个人 Blog 从 Hugo 转到 Astro。
为什么我要转到 astro 呢?
- Hugo 的模板开发起来不够方便,虽然有很多开源的模板可以供你使用,但如果你要自己调整,就有点困难了。 反观 astro 的模板自定义调整就很容易,完全是现代前端开发的思路。
- astro 支持使用多种前端框架,如 React、Vue 等。
这里记录一下我的搭建过程:
初始化 Astro 项目
# 根据 astro 模板生成项目
npm create astro@latest -- --template <example-name>
我使用了 https://github.com/saicaca/fuwari
模板,所以这里的命令为:
# myblogs 是自己起的项目名称,你可以改成你自己喜欢的名字
npm create astro@latest myblogs -- --template saicaca/fuwari
过程如下,
配置
自定义一个新的路由。
src/pages
下新建apps
文件夹- 复制
src/pages/posts
下文件:[...slug].astro
至apps
文件夹下 - 修改
src/pages/apps
下的[...slug].astro
文件内容。
...
# 将 posts 改为 apps
const blogEntries = await getCollection('apps', ({ data }) => {
return import.meta.env.PROD ? data.draft !== true : true;
});
...
- 在
src/content
文件夹下,新建apps
目录。
这样一个新的 /apps
路由就可以使用了。
TIP
新增 Head 导航链接
IMPORTANT以下导航是根据主题:saicaca/fuwari 所做的调整,其他主题,调整方式可能不一样。
在 src/config.ts
中,由 navBarConfig
参数控制 head 导航。所以我们可以在这里添加想要新增的导航。
已我为例,我需要增加一个应用
的导航,我们看到 navBarConfig
子项中,LinkPreset
是 enum 类型,所以我们这里新增一个类型。
export enum LinkPreset {
Home = 0,
Archive = 1,
Apps = 2, // 新增类型 apps
About = 3,
}
// 然后在 src/config.ts 的 navBarConfig 选项中引用新增类型
export const navBarConfig: NavBarConfig = {
links: [
LinkPreset.Home,
LinkPreset.Apps, // 引用新增 apps 类型
LinkPreset.Archive,
],
};
// 修改 src/constants/link-presets.ts 中配置
export const LinkPresets: { [key in LinkPreset]: NavBarLink } = {
[LinkPreset.Home]: {
name: i18n(I18nKey.home),
url: "/",
},
[LinkPreset.Apps]: { // 添加新增 apps 导航对应的路由
name: i18n(I18nKey.apps),
url: "/apps/",
},
[LinkPreset.About]: {
name: i18n(I18nKey.about),
url: "/about/",
},
[LinkPreset.Archive]: {
name: i18n(I18nKey.archive),
url: "/archive/",
},
};
// 修改 src/i18n/languages/en.ts,添加英文下 apps 对应的国际化
...
[Key.apps]: "Apps",
...
// 修改 src/i18n/languages/zh_CN.ts,添加中文下 apps 对应的国际化
...
[Key.apps]: "应用",
...
运行,点击新增「应用」会报错,404,这是因为我们新增的 /apps/
还没有对应的页面。
我们参考 about
的设置,将 src/pages/about.astro
复制 src/pages/apps.astro
,内容调整如下:
---
import MainGridLayout from "../layouts/MainGridLayout.astro";
import Markdown from "@components/misc/Markdown.astro";
import { getEntry } from 'astro:content';
import I18nKey from "../i18n/i18nKey";
import { i18n } from "../i18n/translation";
// 重要的是这两句
const appsPost = await getEntry('spec', 'apps')
const { Content } = await appsPost.render()
---
<MainGridLayout title={i18n(I18nKey.about)} description={i18n(I18nKey.about)}>
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative min-h-32">
<div class="card-base z-10 px-9 py-6 relative w-full ">
<Markdown class="mt-2">
<Content />
</Markdown>
</div>
</div>
</MainGridLayout>
上面的意思是从 src/content/spec/apps.md
读取 Content 并渲染。所以我们需要在新建 src/content/spec/apps.md
文件,里面编写 /apps/
路径下对应的内容。
新增 footer 备案说明
模板中的 footer 的内容对应 src/components/Footer.astro
,我们可以看到里面没有针对 IPC 备案的相关显示参数,这里我们新增一个 icp
参数。
修改 src/config.ts
文件中的 profileConfig
参数,新增一个 icp
字段,字段内容可以为备案的 html 内容。因为是 TS 文件,所以我们还需要修改 profileConfig
对应的 ProfileConfig
类型声明,添加 icp: string;
字段的声明。
调整好后,我们修改 src/components/Footer.astro
, 将新增的 icp
参数内容引用到网页中。调整如下:
<div class="card-base max-w-[var(--page-width)] min-h-[4.5rem] rounded-b-none mx-auto flex items-center px-6">
<div class="transition text-50 text-sm">
© 2024 {profileConfig.name}. All Rights Reserved. <span set:html={profileConfig.icp} />
</div>
</div>
注意,这里通过 set:html
去引用 html 内容。