辛宝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,後續無論我是使用何種渲染環境,都可以使用這個方法。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。