想着去把文章系统也重构到flask上,让数据和博客本身彻底解耦,但是没能成功,astro本身的渲染逻辑就没把api请求放在心上。 我这写一点给后后来的人铺铺路吧,目前来说想要完美的解耦前后端分离,不影响代码高亮,数学公式啥的几乎不可能。这条文档终于把念想彻底堵死了:链接。
内容集合
如果想要对astro项目的markdown进行管理必须通过,框架指定的defineCollection这个astrocontent.config.ts放在/src下面是和之前的作用相同的,
import { defineCollection } from "astro:content";import { glob } from 'astro/loaders';
const postsCollection = defineCollection({ loader: glob({ pattern: "**/*.md", base: "src/content/posts" }),});
export const collections = { posts: postsCollection,
};并且显式指定内容集合的目录,这个config文件不需要被你显式指定导入,astro会自动检查到,把他放到astrosrc/utils/content-utils.ts,在刚刚我们怕配置了一个数据集合,被astro自动扫描到,不需要你显式指定,你直接在别的地方就可以导入,
import { type CollectionEntry, getCollection } from "astro:content";和名字一样,getCollention是从内容集合里获取数据的,CollectionEntry是数据类型。这个Entry对象有3个主要的键值对:
{ id : "", //一般是根据文件名,如果是通过api传递的需要必须要手动传 data : { //这个是通过schema验证的元数据,在文章的front Matter里 title : "", pulished : "" }, body : "" //这个是文章的正文内容,被astro:contetnt自动从markdown放到该对象的body里,在后面可以使用render函数把entry实体渲染成markdown。}src/utils/content-utils.ts里放了挺多格式化,处理文章的函数的,但是说实话看着挺难受的2个函数:getSortedPostsList()、getSortedPosts()在处理相同的事情之后可以重构一下这里,
getSortedPosts()比较好我感觉,page/[...page].astro和page/posts/[...slug].astro都用的这个,getSortedPostsList()这个只有archive.astro在用,说实话有点冗余了。
之后就可以看具体的page了。
pages
[…page].astro
动态路由需要去看文档,记得区分[page]和[…page]的两种动态路由的区别,…page能够使用undefined的占用网页根目录
还有getStaticPaths,这个对动态路由非常重要。
export const getStaticPaths = (async ({ paginate }) => { const allBlogPosts = await getSortedPosts(); return paginate(allBlogPosts, { pageSize: PAGE_SIZE });}) satisfies GetStaticPaths;const { page } = Astro.props;对分页感兴趣的看paginate,相当于分页器返回的
[ { params: undefined, props: page//带有第一页PAGE_SIZE数量的文章数量 }, { params: 2, props: page//带有第二页PAGE_SIZE数量的文章数量 }]之后可以自己去看fuwari的组件流一个个跟着这个组件查怎么渲染的就行了
/posts/[…slug].astro
新的语法不是entry实体里的render()方法了,astro把render()分离出来了,应该使用render(entry)来渲染。
export async function getStaticPaths() { const blogEntries = await getSortedPosts(); return blogEntries.map((entry) => ({ params: { slug: entry.slug }, props: { entry }, }));}
const { entry } = Astro.props;//根据路由把文章对象拿回来const { Content, headings } = await entry.render();//把文章对象从markdown变成content
const { remarkPluginFrontmatter } = await entry.render();//astro内置的用来预估阅读时间的插件带的字段文章CMS化出现的问题
主要出在做内容集合的时候能够调用api,但是无法把把请求来的mark数据,放到数据集合里的body字段里,没法接入astro自带的markdown解析器和渲染,导致元数据可以成功渲染,但是文章正文始终无法渲染,官方推荐使用marked来第三方插件解析,官方链接,但是对各种代码高亮、latex公式的支持不是很好,所以这条路不通,之后可能会通过ci/cd来让文章和git仓库解耦,这下白折腾了哈哈哈。