Skip to content

perf(rehype): skip twoslash on unflagged blocks and load grammars lazily - #59

Draft
lucaspunz wants to merge 6 commits into
mainfrom
lucas/skip-twoslash-transformer
Draft

lucaspunz wants to merge 6 commits into
mainfrom
lucas/skip-twoslash-transformer

Conversation

@lucaspunz

@lucaspunz lucaspunz commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Two changes to rehypeSyntaxHighlighting, output verified byte-identical against the published build on a set of real pages and on a twoslash block.

  • twoslash transformer only for flagged blocks. transformerTwoslash() builds a TypeScript virtual filesystem on construction and was constructed once per code block; with explicitTrigger it is a no-op unless the block carries the twoslash meta flag. On a page with several hundred code blocks this was about a quarter of compile time.
  • load on first use. createHighlighter compiled all 30 default grammars up front, and the twoslash renderer pulled in typescript at module load. Both now load on demand; twoslash blocks preload the default grammar set because their popups render arbitrary snippets through shiki. Local cold path (import + first compile) drops from ~1370ms to ~610ms.

An in-process cache of highlighted blocks was tried and reverted in this branch; it only pays on warm long-lived instances and its memory bound needs more thought, so it will come as its own change if at all.

Test Plan

  • adds vitest with 8 tests for the plugin that pass on main and on this branch: default and lazily loaded grammars, unknown-language fallback, twoslash gating by the meta flag, theme-dependent output, and repeated blocks yielding equal but independent trees; they caught that twoslash relied on eagerly loaded grammars
  • yarn type and yarn build clean (eslint could not run locally: @mintlify/eslint-config-typescript is not resolvable in this checkout)
  • built plugin swapped into the consuming app: compiled output hashes identical on 18 pages; a ts twoslash block produces the same hash and popup count as the published build
  • the consuming app needs a @mintlify/mdx bump once this is released

…slash flag

transformerTwoslash builds a typescript virtual filesystem on construction
and was constructed once per code block; with explicitTrigger it is a no-op
unless the block carries the twoslash meta flag
createHighlighter compiled all 30 default grammars before the first block was
highlighted, and the twoslash renderer pulled in typescript at module load.
both now load on demand, which halves cold-start cost for the compile route
highlighted output is a pure function of code, language and themes for bundled
grammars, and localized docs repeat nearly every block across locales. keep an
lru of recent results and hand out clones, since later plugins mutate the tree
adds vitest and tests that pass on main and on this branch: default and
lazily loaded grammars, unknown-language fallback, twoslash gating by the
meta flag, and repeated blocks yielding equal but independent trees
twoslash highlights popup snippets through shiki with whatever language the
docs contain and relied on the eager highlighter having every default grammar
loaded; caught by the new tests. also trims comments to one line
This reverts commit 669bf62.

# Conflicts:
#	packages/mdx/src/plugins/rehype/rehypeSyntaxHighlighting.ts
@lucaspunz lucaspunz changed the title perf(rehype): lazy twoslash and grammars, cache highlighted blocks perf(rehype): skip twoslash on unflagged blocks and load grammars lazily Sep 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant