summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Tony Sullivan <tony.f.sullivan@outlook.com> 2022-04-18 16:30:19 +0000
committerGravatar GitHub <noreply@github.com> 2022-04-18 16:30:19 +0000
commit394ab9054714586c1b5bb163f02fe17412527ebc (patch)
tree6090e717a49848ec501913d7d2d761248589e18b
parent9e35758ec3278083f54cf0e30d62ed48c63871e8 (diff)
downloadastro-394ab9054714586c1b5bb163f02fe17412527ebc.tar.gz
astro-394ab9054714586c1b5bb163f02fe17412527ebc.tar.zst
astro-394ab9054714586c1b5bb163f02fe17412527ebc.zip
Perf: reuse Shiki highlighters per theme/lang (#3130)
* reuse Shiki highlighters per theme/lang * chore: adding changeset
-rw-r--r--.changeset/eleven-guests-rhyme.md5
-rw-r--r--packages/astro/components/Code.astro2
-rw-r--r--packages/astro/components/Shiki.js22
3 files changed, 28 insertions, 1 deletions
diff --git a/.changeset/eleven-guests-rhyme.md b/.changeset/eleven-guests-rhyme.md
new file mode 100644
index 000000000..183f73829
--- /dev/null
+++ b/.changeset/eleven-guests-rhyme.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Updates `<Code />` component to cache and reuse Shiki highlighters
diff --git a/packages/astro/components/Code.astro b/packages/astro/components/Code.astro
index 32c441495..e829f87be 100644
--- a/packages/astro/components/Code.astro
+++ b/packages/astro/components/Code.astro
@@ -1,6 +1,6 @@
---
import type * as shiki from 'shiki';
-import { getHighlighter } from 'shiki';
+import { getHighlighter } from './Shiki.js';
export interface Props {
/** The code to highlight. Required. */
diff --git a/packages/astro/components/Shiki.js b/packages/astro/components/Shiki.js
new file mode 100644
index 000000000..9e8e60bc2
--- /dev/null
+++ b/packages/astro/components/Shiki.js
@@ -0,0 +1,22 @@
+import { getHighlighter as getShikiHighlighter } from 'shiki';
+
+// Caches Promise<Highligher> for reuse when the same theme and langs are provided
+const _resolvedHighlighters = new Map();
+
+function stringify(opts) {
+ // Always sort keys before stringifying to make sure objects match regardless of parameter ordering
+ return JSON.stringify(opts, Object.keys(opts).sort());
+}
+
+export function getHighlighter(opts) {
+ const key = stringify(opts);
+
+ // Highlighter has already been requested, reuse the same instance
+ if (_resolvedHighlighters.has(key)) { return _resolvedHighlighters.get(key) }
+
+ // Start the async getHighlighter call and cache the Promise
+ const highlighter = getShikiHighlighter(opts);
+ _resolvedHighlighters.set(key, highlighter);
+
+ return highlighter;
+} \ No newline at end of file