fix shiki perf issue (#2870)
This commit is contained in:
parent
098f6f6b06
commit
d763ec183e
2 changed files with 16 additions and 5 deletions
5
.changeset/silly-sloths-hammer.md
Normal file
5
.changeset/silly-sloths-hammer.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/markdown-remark': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix a shiki performance issue affecting large sites
|
|
@ -33,19 +33,25 @@ export interface ShikiConfig {
|
||||||
/**
|
/**
|
||||||
* getHighlighter() is the most expensive step of Shiki. Instead of calling it on every page,
|
* 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.
|
* 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 remarkShiki = async ({ langs = [], theme = 'github-dark', wrap = false }: ShikiConfig, scopedClassName?: string | null) => {
|
||||||
const cacheID: string = typeof theme === 'string' ? theme : theme.name;
|
const cacheID: string = typeof theme === 'string' ? theme : theme.name;
|
||||||
let highlighter = highlighterCache.get(cacheID);
|
let highlighterAsync = highlighterCacheAsync.get(cacheID);
|
||||||
if (!highlighter) {
|
if (!highlighterAsync) {
|
||||||
highlighter = await getHighlighter({ theme });
|
highlighterAsync = getHighlighter({ theme });
|
||||||
highlighterCache.set(cacheID, highlighter);
|
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) {
|
for (const lang of langs) {
|
||||||
await highlighter.loadLanguage(lang);
|
await highlighter.loadLanguage(lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => (tree: any) => {
|
return () => (tree: any) => {
|
||||||
visit(tree, 'code', (node) => {
|
visit(tree, 'code', (node) => {
|
||||||
let html = highlighter!.codeToHtml(node.value, { lang: node.lang ?? 'plaintext' });
|
let html = highlighter!.codeToHtml(node.value, { lang: node.lang ?? 'plaintext' });
|
||||||
|
|
Loading…
Reference in a new issue