
Astro 添加预计阅读时间实践
为你的 Astro 博客添加阅读时间估算。本文将分享我在实现这个功能时的思路和代码,手把手带你搞定它。
不知道你有没有在别的 Blog 中看到过类似「预计阅读时间:3 分钟」这样的提示?这种功能在很多博客平台上都很常见,它可以帮助读者快速评估阅读一篇文章所需的时间,进而帮助读者更好地安排时间。
在本文中,我们将从最基础的需求出发,一步步在 Astro 中完成这个功能的开发,相信你能从中获得一些启发。
需求分析
首先我们整理一下我们要实现什么功能:首先我们要提取文章中所有文字内容,然后根据文字内容的长度,计算出一个预计阅读时间。最后我们要将这个预计阅读时间展示在页面上。
动手实现
Astro 的 Markdown 处理底层使用了 remark,所以我们当然可以自定义一个 remark 插件1来分析文章内容。
mdast-util-to-string 可用于从 Markdown AST(mdast)中提取纯文本的文章内容,而我们还可以使用 reading-time-estimator 来计算预计阅读时间。
在项目根目录下新建以下文件:
// remark-reading-time.js
import { toString } from 'mdast-util-to-string'
import { readingTime } from 'reading-time-estimator'
/** @import { RemarkPlugin } from '@astrojs/markdown-remark' */
/** @type {RemarkPlugin} */
export const remarkReadingTime = () => {
return (tree, { data }) => {
const textOnPage = toString(tree)
const t = readingTime(textOnPage, 300, 'cn')
data.astro.frontmatter.minutesRead = '预计 ' + t.text
}
}
同时修改 Astro 的配置文件,添加我们自定义的这个 remark 插件:
// astro.config.js
import { defineConfig } from 'astro/config'
import { remarkReadingTime } from './remark-reading-time.js'
export default defineConfig({
// ...
markdown: {
// ...
remarkPlugins: [/* ..., */ remarkReadingTime],
// ...
},
// ...
})
这样,我们就可以对每篇文章的 frontmatter 添加一个 minutesRead
字段,用于存储预计阅读时间。
同时,我们需要在 Astro 的页面组件中,通过渲染对应 Content 的方式,同时“渲染”出存放在 frontmatter 中的 minutesRead
字段。
具体的代码实现参考如下:
---
// src/pages/[slug].astro
import { type CollectionEntry, getCollection, render } from 'astro:content'
import BlogPage from '@/layouts/Page.astro'
export async function getStaticPaths() {
const pages = await getCollection('page')
return pages.map((page) => ({
params: { slug: page.id },
props: page,
}))
}
type Props = CollectionEntry<'page'>
const page = Astro.props
const { Content, headings, remarkPluginFrontmatter } = await render(page)
// 重点在于这里,minutesRead 就是我们通过 remark 插件添加的表示预计阅读时间的字段
const minutesRead = (remarkPluginFrontmatter.minutesRead as string | undefined) ?? ''
---
<BlogPage slug={page.id} {headings} {minutesRead} {...page.data}>
<Content />
</BlogPage>
完整代码可参考 :sparkles: add reading time gadget · ShellWen/shellwens-things@4fdda0d。
Footnotes
本页面内容,除特别声明外,均采用 CC BY-NC-SA 4.0 Deed 协议授权。