Repository navigation
perf(editor): memoize the markdown preview render pipeline - #9843
Merged
Merged
Conversation
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
react-markdown's <Markdown> has no internal memoization: it rebuilds the whole unified remark->rehype->highlight->katex processor and re-parses the document on every render. MarkdownPreview re-renders on internal state that does not affect the rendered output — most visibly, every keystroke in Find (query/match-index state) — so a large doc re-ran the full parse + syntax-highlight + KaTeX pass per keypress, making Find laggy. Hoist the two fully-static plugin arrays to module scope (a fresh array identity per render would defeat the memo) and render the body through a React.memo'd MarkdownBody keyed on content + components. The pipeline now re-runs only when the rendered content or the components map actually changes; Find/review-pulse/copied- note re-renders skip it. The components map was already memoized, so its identity is stable across those re-renders. Behavior unchanged: 106 existing MarkdownPreview tests pass. Co-authored-by: Orca <help@stably.ai>
nwparker
force-pushed
the
nwparker/perf-9-markdown-preview-memo
branch
from
July 22, 2026 21:15
a6d3e6a to
d4d0d75
Compare
This was referenced Jul 27, 2026
enrick-dev
pushed a commit
to enrick-dev/orca
that referenced
this pull request
Oct 15, 2026
…9843) react-markdown's <Markdown> has no internal memoization: it rebuilds the whole unified remark->rehype->highlight->katex processor and re-parses the document on every render. MarkdownPreview re-renders on internal state that does not affect the rendered output — most visibly, every keystroke in Find (query/match-index state) — so a large doc re-ran the full parse + syntax-highlight + KaTeX pass per keypress, making Find laggy. Hoist the two fully-static plugin arrays to module scope (a fresh array identity per render would defeat the memo) and render the body through a React.memo'd MarkdownBody keyed on content + components. The pipeline now re-runs only when the rendered content or the components map actually changes; Find/review-pulse/copied- note re-renders skip it. The components map was already memoized, so its identity is stable across those re-renders. Behavior unchanged: 106 existing MarkdownPreview tests pass. Co-authored-by: Orca <help@stably.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
react-markdown's<Markdown>has no internal memoization: every render rebuilds the wholeunifiedremark→rehype→highlight→katex processor and re-parses the document (react-markdown v10lib/index.jsrunscreateProcessor+parse+runSyncper render).MarkdownPreviewre-renders on internal state that doesn't affect the rendered output — most visibly, every keystroke in Find (query / match-index state) — so a large doc with code blocks + math re-ran the full parse + syntax-highlight + KaTeX pass on each keypress, making Find laggy.This:
React.memo'dMarkdownBodykeyed oncontent+components.The pipeline now re-runs only when the rendered content or the
componentsmap actually changes. Thecomponentsmap was already memoized, so its identity is stable across Find/body-unrelated re-renders. (Inline-annotation/review state deliberately rebuildscomponentsand thus still re-runs the pipeline — required to keep the live annotation markup correct.)ELI5
Every time you typed a letter in the preview's Find box, Orca re-cooked the entire markdown document from scratch — re-parsing it, re-syntax-highlighting every code block, re-rendering every math formula — just to draw a search highlight that doesn't change the document at all. On a big doc that made Find stutter. Now the cooked document is remembered and only re-cooked when the document actually changes, so Find (and other unrelated UI blips) are smooth.
Proof of zero regression
componentsmemo and its deps are untouched, so inline annotation cards / review-note highlights stay live (they intentionally rebuildcomponents).renderedContentis primitive string state;Object.iscompares by value, so equal text safely skips and any real content change re-renders — no stale preview.MarkdownBodyadds no host DOM node and stays the same child under thetranslate="no"bodyRefcontainer, so the OS-page-translation crash guard (fix(markdown-preview): paint Find matches without mutating react DOM (crash 237acef1) #8678) and the Find CSS-Custom-Highlight painting (which readsbodyRef) are unaffected — in fact the body DOM is now more stable during search.Proof of perf improvement
The triage confirmed by reading
node_modules/react-markdown/lib/index.jsthat the syncMarkdown()has no memoization and rebuilds the processor + re-parses on every render. With the memoized body, Find keystrokes (and review-pulse/store re-renders that don't touchcontent/components) no longer trigger that O(document-size) parse + highlight + KaTeX pass — each avoided pass is the full pipeline over the whole document. The win scales with document size and the number of code/math blocks.Made with Orca 🐋