辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

技术折腾 xLog 4 用 unStorage 封装 xLogDriver

技术折腾 xLog 4 用 unStorage 封装 xLogDriver

内部链接

  • [[技术折腾 xLog 1 可行性探索]]
  • [[技术折腾 xLog 2 深入理解 xlog 的鉴权]]
  • [[技术折腾 xLog 3 实现一个 obsidian 插件]]
  • [[技术折腾 xLog 4 用 unStorage 封装 xLogDriver]]
  • [[速通 - xLog 背后的 CrossBell SDK]]
  • [[从官方 XLOG Obsidian 插件中能学到什么]]
  • [[开发 Obsidian Sync To Xlog 插件之 处理 obsidian 的图片]]
  • [[速通 - CrossBell 的开源作品]]
  • [[速通 Obsidian Docs - 侧重插件开发]]

关联

  • [[unjs_unstorage]]

背景#

承接前三篇内容,前三篇我们认为 xlog 的雄心应该不满足目前的网页版 blog,应该是更好的 headlessCMS ,为了更流畅地发表文章,我们开发了 sync-to-xlog 插件,让同步过程更轻松。

如果继续展望,要拓展 xlog 的展示场景,我能不能用 nuxt 制作一个自己的 blog?顺着这个思路,我意识到,目前获取 xlog 的方案还可以更简单,顺便给自己增加一点难度,试试 unjs/unstorage

简单介绍 unstorage ,可以理解一个通用插件,提供统一的接口,使用不同的 driver 适配器,就能磨平细节差异。

用法其实特别简单,一看就会,和 localstorage 用法一样

import { createStorage } from "unstorage";
const storage = createStorage(/* opts */);
await storage.getItem("foo:bar");
await storage.hasItem()
// getItem getItems
// getItemRaw
// setItem setItems setItemRaw
// getMeta setMeta removeMeta
// getKeys

技术设计#

看着不复杂。

首先自定义 xLogDriver

实现对应 api

  • 定义 getItem ('site')
  • 定义 getKeys () - 返回 list
  • 定义 getItem (‘slugOrID')
const storage = createStorage({
  driver: xLogStorageDriver({
    token: "", // 可选
    charactorID: "", // 必选
  }),
});

// console.log("list", list);

const list = await storage.getKesy();
console.log("list", list);

代码实现#

似乎不难,后面实现。有进展我会更新到这里。

这一次我们不实用 restful api 请求了,使用 crossbell.js SDK 来完成所有操作。

实际写了写,不舒服,主要是在 getKeys 的返回值只能是 string[],放弃了。等到几个大版本再回来看吧。

好像只实现 getItems 也可以?

犹豫了一阵,还是实现了 源码开源在这里 https://github.com/Otto-J/unstorage-xlog-driver

你可以这样使用

/* eslint-disable unicorn/prefer-top-level-await */
import { createStorage } from "unstorage";

import { xLogStorageDriver } from "unstorage-xlog-driver";

const OTTO_ID = 53_709;

async function main() {
  const storage = createStorage({
    driver: xLogStorageDriver({
      characterId: OTTO_ID,
      ttl: 60 * 60,
    }),
  });

  // const keys = await storage.getKeys();
  // console.log(keys);

  const info = await storage.getItem("72.md");
  // const info = await storage.getMeta("72.md");
  console.log(info);
}
main();

踩坑经验#

不需要全部实现 api#

一开始我对 unstorage 认识不清,我以为所有的功能都要实现,后来只需要实现几个主要的方法就行。

getKeys 返回什么合适?#

getKeys 返回的必须是 string[] ,通过实践发现,这里返回 ${noteID}.md 比较好,因为 nuxt-content 模块里可以这样配置,生成虚拟文件,加上 md 和本地文件差不多,更一致。

export default defineNuxtConfig({
  content: {
    sources: {
       driver: path.resolve(
          __dirname,
          "node_modules/unstorage-xlog-driver/dist/index.mjs",
        ),
        characterId: 53709,
        prefix: "/blogs",
    }
  }
})

有了这个神奇的 sources 配置,可以把远程的数据拉取到本地 ls .nuxt/content-cache/parsed/xLog/blogs 既可以看到这些理论上的虚拟文件了。

这里有一张截图比较好,想了想还是不放了,都是乱码不美观。

getItem 怎么设计比较好#

getItem('72.md') 返回的只有 markdown 纯文本。这样我就丢失了一些信息,比如 slug/update_time 等等。

我想了个比较适合我的方案,那就是拦截纯文本,先把想填补的信息放入 frontmatter 里。

怎么理解,请看代码 https://github.com/Otto-J/unstorage-xlog-driver/blob/main/src/index.ts#L124

我先解析 front-matter,和原始 markdown 进行合并再返回。这样远程数据不动,自己处理就好。

必须要加的缓存#

我当初打了 log,特别惊讶地发现触发了无数次请求,特别奇怪,我去看了 github-driver 的实现,才知道可以自己加缓存。自己维护一个 object 映射表,缓存有效内读取缓存,这样一段时间内就不用重新请求远程数据了。

触发了无数次,有点像攻击,扶额哭笑。

使用 unjs 的 unbuild 模板#

本来我是想用 tsup 搞一个流水线,后来发现 unjs 有个 unbuild 项目提供了模板。自带 vitest/jiti 等东西,用起来挺顺手的。

模板地址 https://github.com/unjs/template

咱也写了一把 vitest 单元测试。

如果能重来#

如果能重来,写的就不会这么犹豫了,犹豫了两周要不要写。本来写了,后来觉得放弃好了,就把代码删除了,虽然没多少东西,但是删除了就没了,只能重新写,所以还是尊重自己的代码。真不想留着,把代码放博客里也行。

展望#

至此,我们实现了 unstorage 的 xLogDriver,后续无论我是使用何种渲染环境,都可以使用这个方法。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。