Commit cc67ee1

HPCesia <me@hpcesia.com>
2025-02-10 09:26:28
refactor: cache post render result
1 parent 853a8ce
Changed files (2)
src/pages/posts/[article].astro
@@ -7,7 +7,8 @@ import Markdown from '@components/utils/Markdown.astro';
 import ProfileCard from '@components/widgets/ProfileCard.astro';
 import TOC from '@components/widgets/TOC.astro';
 import GridLayout from '@layouts/GridLayout.astro';
-import { getCollection, render } from 'astro:content';
+import { getOrCreateRenderResult } from '@utils/component-utils';
+import { getCollection } from 'astro:content';
 
 export async function getStaticPaths() {
   const articles = await getCollection('posts');
@@ -18,7 +19,7 @@ export async function getStaticPaths() {
 }
 
 const { article } = Astro.props;
-const { Content, headings, remarkPluginFrontmatter } = await render(article);
+const { Content, headings, remarkPluginFrontmatter } = await getOrCreateRenderResult(article);
 
 const description = article.data.description || remarkPluginFrontmatter.excerpt;
 ---
src/utils/component-utils.ts
@@ -1,4 +1,6 @@
-import type { AstroGlobal } from 'astro';
+import type { AstroGlobal, MarkdownHeading } from 'astro';
+import type { AstroComponentFactory } from 'astro/runtime/server/index.js';
+import { type CollectionEntry, render } from 'astro:content';
 
 const renderedInstance = new Set<string>();
 
@@ -10,3 +12,25 @@ export function isFirstInstance(id: string, url: AstroGlobal['url']): boolean {
   renderedInstance.add(key);
   return true;
 }
+
+interface RenderResult {
+  Content: AstroComponentFactory;
+  headings: MarkdownHeading[];
+  remarkPluginFrontmatter: Record<string, unknown>;
+}
+
+const renderCache = new Map<string, RenderResult>();
+
+export async function getOrCreateRenderResult(article: CollectionEntry<'posts'>) {
+  const cacheKey = article.id;
+
+  if (renderCache.has(cacheKey)) {
+    return renderCache.get(cacheKey)!;
+  }
+
+  const { Content, headings, remarkPluginFrontmatter } = await render(article);
+  const result = { Content, headings, remarkPluginFrontmatter };
+
+  renderCache.set(cacheKey, result);
+  return result;
+}