Skip to content

fix(markdown-remark): reuse shiki highlighter instance#15651

Merged
ematipico merged 8 commits intowithastro:mainfrom
ocavue-forks:ocavue/reuse-shiki
Feb 27, 2026
Merged

fix(markdown-remark): reuse shiki highlighter instance#15651
ematipico merged 8 commits intowithastro:mainfrom
ocavue-forks:ocavue/reuse-shiki

Conversation

@ocavue
Copy link
Contributor

@ocavue ocavue commented Feb 25, 2026

Changes

Closes #15656

I noticed the following warning in my Astro project:

[Shiki] 10 instances have been created. Shiki is supposed to be used as a singleton, consider refactoring your code to cache your highlighter instance; Or call `highlighter.dispose()` to release unused instances.
[Shiki] 20 instances have been created. Shiki is supposed to be used as a singleton, consider refactoring your code to cache your highlighter instance; Or call `highlighter.dispose()` to release unused instances.
[Shiki] 30 instances have been created. Shiki is supposed to be used as a singleton, consider refactoring your code to cache your highlighter instance; Or call `highlighter.dispose()` to release unused instances.

This is due to the fact that Astro creates a new Shiki highlighter instance for each language, and there are many different code block languages in my project.

This PR improves this by using the same highlighter across languages. This approach works because Astro already loads languages dynamically when they haven't been loaded yet (code link).

Testing

Added a new test to ensure that

  1. The same highlighter instance is used for different languages. I not only cache the Shiki highlighter instance, but I also cache the returned wrapper object (code link) for an extra tiny bit of performance improvement.
  2. This cached highlighter instance can highlight new languages.

Docs

Changeset file has been added.

@changeset-bot
Copy link

changeset-bot bot commented Feb 25, 2026

🦋 Changeset detected

Latest commit: b0e5acd

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added feat: markdown Related to Markdown (scope) 🚨 action Modifies GitHub Actions labels Feb 25, 2026
@ocavue ocavue force-pushed the ocavue/reuse-shiki branch from f8c100c to ae94c68 Compare February 25, 2026 03:42
@github-actions github-actions bot removed the 🚨 action Modifies GitHub Actions label Feb 25, 2026
@ocavue ocavue marked this pull request as ready for review February 25, 2026 03:43
@ocavue ocavue marked this pull request as draft February 25, 2026 03:56
@ocavue ocavue force-pushed the ocavue/reuse-shiki branch from ae94c68 to 555e443 Compare February 25, 2026 03:58
@ocavue ocavue marked this pull request as ready for review February 25, 2026 05:27
Comment on lines +100 to +101
Object.entries(options?.themes ?? {}).sort(),
Object.entries(options?.langAlias ?? {}).sort(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wasteful because we're polluting the key with empty objects. I suggest looking for a different approach e.g.

const keyCache = [];
if (options?.theme) { keyCache.push(options.theme) }
...

const key = keyCache.length > 0 ? JSON.stringify() : "";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@ematipico ematipico merged commit f94d3c5 into withastro:main Feb 27, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat: markdown Related to Markdown (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shiki warning: 290 instances have been created

2 participants