前言
搭建博客的方式有很多种,比如hexo, vuepress, vitepress等等,之前用过hexo搭建了一次博客,效果还不错,唯一的缺点就是推上去的代码不是源代码,要是换电脑这些,我就得备份一次,显得极为麻烦。后面了解到了Astro,看了看文档,这简直是我心中最完美的方案了,而且官方也表示,Astro 是以内容为中心的网站的完美选择:博客、营销网站、作品集等!
快速搭建
Astro官方文档就有一个搭建博客的教程,对于初学者也是极为友好,可以照着搭建一个自己的第一个astro版本的博客。
过了一段时间~~~ , 你照着官方教程敲了一遍,成功搭建出来。
当然也可以跟着我来一起搭建。
创建项目
npm create astro@latest
在创建工程的时候选择use blog templat 这个选项,此时也就搭建好了一个简易的博客了,搭建好的目录如下所示。
- components 文件夹存放自定义的相关组件。
- content 文件夹存放所有的文章。
- layouts 文件夹存放一个或多个共享的 UI 结构的 Astro 组件。
- pages 文件夹就存放视图展示的页面。
我们来梳理一下一遍博客的展示流程:
- 在content/blog文件夹下建立一个md/mdx文件,定义元数据,元数据的key与config.ts的数据定义一致,元数据定义如下:
title: 'First post'
description: 'Lorem ipsum dolor sit amet'
pubDate: 'Jul 08 2022'
heroImage: '/blog-placeholder-3.jpg'
- 在/pages/blog下的[...slug].astro中展示自己的博客,[...slug]的意思的动态路由,则pages/blog/[...slug].astro的意思就是动态展示路由blog下的文件。
export async function getStaticPaths() { // 处理动态路由 [`getStaticPaths()`] 函数返回类型的类型。
const posts = await getCollection('blog'); // 获取content/blog文件夹夹的文章集合
return posts.map((post) => ({
params: { slug: post.slug },
props: post,
}));
}
可看下图更加直观
- 通过Astro.props.post获取每一篇博客,然后再去render()渲染。博客的样式便在BlogPost这个组件中渲染。
主题切换
创建一个主题切换的组件 ThemeIcon.astro ,这个不必多说,直接贴代码
<button id="themeToggle">
<svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path class="sun" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/>
<path class="moon" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/>
</svg>
</button>
<style>
.sun { fill: black; }
.moon { fill: transparent; }
:global(.dark) .sun { fill: transparent; }
:global(.dark) .moon { fill: white; }
#themeToggle {
bottom: 1rem;
right: 1rem;
background: none;
border: none;
cursor: pointer;
}
</style>
<script is:inline>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
})();
if (theme === 'light') {
document.documentElement.classList.remove('dark');
} else {
document.documentElement.classList.add('dark');
}
window.localStorage.setItem('theme', theme);
const handleToggleClick = () => {
const element = document.documentElement;
element.classList.toggle("dark");
const isDark = element.classList.contains("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
}
document.getElementById("themeToggle").addEventListener("click", handleToggleClick);
</script>
值得注意的是:
- 在script中,有一个
is:inline属性,它可以让 Astro 将<script>或<style>标签原封不动地留在最终输出的 HTML 中。这些内容将不会被处理、压缩或打包。 - 在
theme这个方法中,首先是判断了localStorage是否存在,因为Astro是服务端渲染,需要将客户端的代码进行水合,在服务端中不存在localStorage这个属性,直接展示的话会报错。
最后将ThemeIcon.astro放在Header.astro组件中,然后在global.css中,注释掉background-color和color的代码(Header.astro Footer.astro组件中也存在),并添加以下代码
html.dark {
background-color: black;
color: #fff;
}
展示效果如下
部署
部署的方式有很多种,我觉得最简单的方式还是使用vercel进行部署,首先将代码推上Github,登录vercel,点击下面的project关联自己的github导入这个博客项目就可以直接部署了。
值得数一的是,vercel自动部署会给我们一个域名,但是这个域名在国内被污染了,要想在国内访问的话,需要自备一个域名,然后在vercel这里添加上去,解析一哈就可以访问了。
结束
这样,我们就搭建好了一个astro的博客了ヾ(✿゚▽゚)ノ。