logo

用next.js来实现兼容obsidian的博客系统

08:34

阅读次数: 0

最近在用nextjs实现新的博客系统。

之前一直没有找到obsidian发布笔记的合适办法。 obsidian发布笔记,一类方案是使用hexo之类的框架,手动生成,意味着发布的时候,需要手动构建一次。通过github管理的话,还需要处理各种冲突。

最终选择采用nextjscloudflare pages

为什么使用nextjs呢?因为nextjs 的笔记来源,可以直接从对象存储中获得,而对象存储可以通过我本地的obsidian来直接上传,这样,就可以使用本地obsidian来编辑博客,更新的时候,直接使用remote save插件,把本地文档上传到oss中。

下面说下几个主要的步骤

remotely save + obsidian

在obsidian中,创建一个新的仓库,安装remotely save插件。 配置remotely save插件,使得本地的内容同步到对象存储中,这里我使用的是cloudflare的对象存储R2。因为cloudflare还可以直接通过pages来访问R2 或者 KV 数据库。

具体的配置方法,参照 remotely save 插件官网的描述。

Remotely Save 官网

cloudflare pages

这里使用 cloudflare pages 创建一个nextjs项目。

pages 文档

在next项目中,使用app router 定义一个read/[slug]/page.tsx的路由。 这个页面是承载文章的。

通过路径中的slug参数,获取当前访问的文章路径。路径一定是encode的。

通过getRequestContext 函数获取R2对象存储。

const myR2 = getRequestContext().env.MY_BLOG_BUCKET;

const blogResponse = await myR2.get(decodeURIComponent(slug));

markdown

因为obsidian的笔记都是markdown格式的,可以直接使用react-markdown相关的插件,直接把对象存储中的文件渲染为html

这里,经过最终比较,我选用了react-markdown这个包,非常适配于react。

react-markdown

还可以通过自定义组件,实现更丰富的功能。

  <Markdown
	remarkPlugins={[remarkGfm]}
	components={{
	  img: ({ src, alt }) => (
		<Img src={src || ""} alt={alt || ""} />
	  ),
	  code: ({ node, className, children, ...props }) => (
		<CodeWordAI {...props}>{children}</CodeWordAI>
	  ),
	  pre: ({ node, className, children, ...props }) => (
		<Pre {...props}>{children}</Pre>
	  ),
	  a: ({ node, className, children, ...props }) => (
		<A {...props}>{children}</A>
	  ),
	}}
  >
	{finalContent}
  </Markdown>

踩坑

nextjs 的 缓存管理一直有点问题,使用unstable_cache非常容易不成功。

如果要缓存页面,其实直接使用cloudflarecache rules就行,配置缓存规则之后,当前页面下的所有内容都会被缓存到CDN

这里再次感谢cloudflare大善人

logo