mdx-js/runtime: Avoid unstable element type to improve render performance
See original GitHub issueHeya! We’re using the runtime package to live-render a preview window in netlify-cms-app. Naturally, the performance of this use case is never going to be amazing, but I believe I found a way to improve it noticeably.
Subject of the feature
mdx-js/runtime currently creates and calls a function that defines and returns an <MDXContent>
component containing the desired content. I believe that, because this is a function that is defined on every render, its type is different on every render, so React’s reconciler will always tear down the DOM component tree rather than diffing the DOM elements, if mdx-js/runtime is used live.
To test this, I made this change, and it seemed in a quick test to drop our render times by 4x. (From 4000ms… don’t ask 😛)
- React.createElement(MDXContent, props)
+ React.createElement(React.Fragment, null, MDXContent(props))
I’m anything but a React DOM expert or familiar with this codebase, so I imagine there’s a much, much better way to do this.
Expected behavior
The MDX runtime creates the same component type tree when given the same input, as far as the React reconciler is concerned.
Alternatives
I can’t think of any, besides “the performance is not quite as good as it could be.”
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (4 by maintainers)
Top GitHub Comments
evaluate
is now used here too, in the RC for version 2. See: https://v2.mdxjs.com. I’ve added a note to the docs onevaluate
so other folks repeat-evaluating stuff can use it too. Thanks or reporting!Memoizing the input doesn’t have anything to do with this PR, though I have of course done that!
Right now, when the input is changed, the entire DOM is unmounted and remounted. With this proposed change, the DOM is not unmounted, and only the changes that are made are applied to the DOM (i.e. a few keystrokes). See the React documentation here: https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm.