From 1b8bd19370973534c0be825fc8d3f5d78b9b4c75 Mon Sep 17 00:00:00 2001 From: passthem Date: Tue, 7 Apr 2026 12:57:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=9A=E5=AE=A2=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 27 +++++++++++++++++++++------ package.json | 1 + src/lib/markdoc-cache.ts | 16 ++++++++++++++++ src/lib/markdoc.ts | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 src/lib/markdoc-cache.ts diff --git a/package-lock.json b/package-lock.json index 4c63c6f..13e35ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,6 @@ "requires": true, "packages": { "": { - "name": "20260327_blog_frontend_v2", "version": "0.0.1", "dependencies": { "@astrojs/node": "^10.0.4", @@ -25,6 +24,7 @@ "astro-icon": "^1.1.5", "axios": "^1.13.6", "katex": "^0.16.43", + "keyv": "^5.6.0", "markdown-it": "^14.1.1", "react": "^19.2.4", "react-dom": "^19.2.4", @@ -1976,6 +1976,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "license": "MIT" + }, "node_modules/@markdoc/markdoc": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@markdoc/markdoc/-/markdoc-0.5.7.tgz", @@ -5143,6 +5149,16 @@ "node": ">=16" } }, + "node_modules/flat-cache/node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/flatted": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", @@ -5975,13 +5991,12 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "@keyv/serialize": "^1.1.1" } }, "node_modules/kolorist": { diff --git a/package.json b/package.json index 13448cf..e5f5114 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "astro-icon": "^1.1.5", "axios": "^1.13.6", "katex": "^0.16.43", + "keyv": "^5.6.0", "markdown-it": "^14.1.1", "react": "^19.2.4", "react-dom": "^19.2.4", diff --git a/src/lib/markdoc-cache.ts b/src/lib/markdoc-cache.ts new file mode 100644 index 0000000..e455998 --- /dev/null +++ b/src/lib/markdoc-cache.ts @@ -0,0 +1,16 @@ +import type { RenderableTreeNode } from '@markdoc/markdoc' +import KeyV from 'keyv' +import { createHash } from 'node:crypto' + +const markdocVersion = '1' + +export const markdocCache = new KeyV({ + namespace: `markdoc-cache-${markdocVersion}`, + ttl: 1000 * 60 * 60 * 24 * 7, +}) +export const generateCacheKey = (content: string) => { + return createHash('sha256') + .update(content) + .update(markdocVersion) + .digest('hex') +} diff --git a/src/lib/markdoc.ts b/src/lib/markdoc.ts index ebab6f7..f201ebe 100644 --- a/src/lib/markdoc.ts +++ b/src/lib/markdoc.ts @@ -12,6 +12,15 @@ export const markdocConfig: Config = { highlightedHtml: { type: String }, }, transform(node, config) { + /* + * 注意力!!!!!!!!!!!!!! + * 注意!!!!!!!!!!!! + * + * 如果改了这里的逻辑,记得更改 `markdoc-cache.ts` 里的版本号 + * 以让对应的缓存能够被更新 + * + **/ + const attributes = node.transformAttributes(config) const highlightedHtml = shikiRender( @@ -29,8 +38,28 @@ export const markdocConfig: Config = { }, } -export const toMarkdocTree = async (content: string) => { +const _toMarkdocTree = async (content: string) => { const ast = Markdoc.parse(content) await ensureShikiEngine() - return Markdoc.transform(ast, markdocConfig) + const tree = Markdoc.transform(ast, markdocConfig) + + return tree +} + +export const toMarkdocTree = async (content: string) => { + if (!import.meta.env.SSR) { + return await _toMarkdocTree(content) + } + + const cacheLib = await import('./markdoc-cache.ts') + const key = cacheLib.generateCacheKey(content) + const cached = await cacheLib.markdocCache.get(key) + + if (cached) { + return cached + } + + const tree = await _toMarkdocTree(content) + cacheLib.markdocCache.set(key, tree) + return tree }