diff options
author | 2022-03-24 09:49:54 -0700 | |
---|---|---|
committer | 2022-03-24 09:49:54 -0700 | |
commit | d763ec183ea391ad79ca16bf2b2e76848fc1180c (patch) | |
tree | ac55f6912ee92efd1bf916e6b60303236f845832 | |
parent | 098f6f6b06396441c576dc689d8552629ef260e1 (diff) | |
download | astro-d763ec183ea391ad79ca16bf2b2e76848fc1180c.tar.gz astro-d763ec183ea391ad79ca16bf2b2e76848fc1180c.tar.zst astro-d763ec183ea391ad79ca16bf2b2e76848fc1180c.zip |
fix shiki perf issue (#2870)
-rw-r--r-- | .changeset/silly-sloths-hammer.md | 5 | ||||
-rw-r--r-- | packages/markdown/remark/src/remark-shiki.ts | 16 |
2 files changed, 16 insertions, 5 deletions
diff --git a/.changeset/silly-sloths-hammer.md b/.changeset/silly-sloths-hammer.md new file mode 100644 index 000000000..38084452d --- /dev/null +++ b/.changeset/silly-sloths-hammer.md @@ -0,0 +1,5 @@ +--- +'@astrojs/markdown-remark': patch +--- + +Fix a shiki performance issue affecting large sites diff --git a/packages/markdown/remark/src/remark-shiki.ts b/packages/markdown/remark/src/remark-shiki.ts index ebbe4032c..f34fa26ef 100644 --- a/packages/markdown/remark/src/remark-shiki.ts +++ b/packages/markdown/remark/src/remark-shiki.ts @@ -33,19 +33,25 @@ export interface ShikiConfig { /** * getHighlighter() is the most expensive step of Shiki. Instead of calling it on every page, * cache it here as much as possible. Make sure that your highlighters can be cached, state-free. + * We make this async, so that multiple calls to parse markdown still share the same highlighter. */ -const highlighterCache = new Map<string, shiki.Highlighter>(); +const highlighterCacheAsync = new Map<string, Promise<shiki.Highlighter>>(); const remarkShiki = async ({ langs = [], theme = 'github-dark', wrap = false }: ShikiConfig, scopedClassName?: string | null) => { const cacheID: string = typeof theme === 'string' ? theme : theme.name; - let highlighter = highlighterCache.get(cacheID); - if (!highlighter) { - highlighter = await getHighlighter({ theme }); - highlighterCache.set(cacheID, highlighter); + let highlighterAsync = highlighterCacheAsync.get(cacheID); + if (!highlighterAsync) { + highlighterAsync = getHighlighter({ theme }); + highlighterCacheAsync.set(cacheID, highlighterAsync); } + const highlighter = await highlighterAsync; + + // NOTE: There may be a performance issue here for large sites that use `lang`. + // Since this will be called on every page load. Unclear how to fix this. for (const lang of langs) { await highlighter.loadLanguage(lang); } + return () => (tree: any) => { visit(tree, 'code', (node) => { let html = highlighter!.codeToHtml(node.value, { lang: node.lang ?? 'plaintext' }); |