Externalize using create() and drop size threshold requirement#1280
Externalize using create() and drop size threshold requirement#1280
Conversation
Implements slorber's suggestion from PR #1279 to handle externalization at the source (in create()) rather than post-processing MDX strings. Changes: - Add externalization context system to utils.ts - Modify create() to detect large JSON props and externalize inline - Remove externalizeJsonProps.ts (no longer needed) - Update index.ts to use context-based approach This is more architecturally clean as the externalization decision happens where the component is created, not via regex parsing afterward.
Always externalize eligible props (responses, parameters, body, schema) regardless of size. This simplifies the logic and provides consistent behavior - users either have externalization on or off, no edge cases.
|
Size Change: 0 B Total Size: 2.17 MB ℹ️ View Unchanged
|
|
Visit the preview URL for this PR (updated for commit bb1e3a2): https://docusaurus-openapi-36b86--pr1280-nxk0yj1l.web.app (expires Thu, 19 Feb 2026 20:24:29 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: bf293780ee827f578864d92193b8c2866acd459f |
slorber
left a comment
There was a problem hiding this comment.
Looks more robust than before 👍
| * Module-level externalization context. | ||
| * Set via setExternalizationContext() before generating MDX. | ||
| */ | ||
| let externalizationContext: ExternalizationContext | null = null; |
There was a problem hiding this comment.
Probably not a big deal in your context, but if you want to get rid of the global module state, one option could be to leverage node async local storage: https://nodejs.org/api/async_context.html#asynclocalstoragerunstore-callback-args
It's like React context but for async code, useful to pass context to a tree without having to pass explicit function attributes
There was a problem hiding this comment.
hmm, I wasn't able to get this to work as it appears to only be available in node and not the browser. The builds were failing since docusaurus builds for both client and server.
| for (const [key, value] of Object.entries(rest)) { | ||
| propString += `\n ${key}={${JSON.stringify(value)}}`; | ||
| // Check if this prop should be externalized |
There was a problem hiding this comment.
just wondering, why not create one json file per JSX tag.
Instead of handling props one by one, you could do:
<tag {...require("./myApi.props.json")}/>
You can spread children too this way, it doesn't really need special handling
Implements slorber's suggestion to externalize all props for a component
into a single JSON file and use spread syntax:
<StatusCodes {...require('./add-pet.StatusCodes.json')} />
Instead of separate files per prop:
<StatusCodes responses={require('./add-pet.responses.json')} />
Benefits:
- Cleaner file organization (one file per component vs per prop)
- Simpler logic (no need to track which props to externalize)
- All props for a component are colocated in one file
Provides a cleaner API similar to AsyncLocalStorage pattern but uses module-level state internally (AsyncLocalStorage isn't available in browser bundles that Docusaurus creates). The runWithExternalization() function wraps generation with try/finally to ensure context is always cleaned up, providing the same safety guarantees as AsyncLocalStorage.run().
9d985c9 to
bb1e3a2
Compare
Major performance improvement: The new `externalJsonProps` option (enabled by default) dramatically reduces build times and bundle sizes by externalizing large JSON props from MDX files. - New `externalJsonProps` plugin option significantly improves build performance - Sticky positioning for the API Explorer right panel improves UX on long API pages - Dynamic request body updates when switching anyOf/oneOf tabs #### 🚀 New Feature - feat(plugin): add externalJsonProps option (enabled by default) to improve build performance (#1279) - feat(theme): add sticky positioning to API Explorer right panel (#1288) - feat: dynamically update request body when anyOf/oneOf tab changes (#1287) #### 🐛 Bug Fix - fix: render inline enum values in anyOf schemas (#1286) - fix: generate correct examples for different request content types (#1284) #### 🏠 Refactoring - refactor: change plugin and theme types.ts to types.d.ts (#1281) - refactor: externalize using create() and drop size threshold requirement (#1280) #### 📝 Documentation - docs: sync README and intro.mdx with plugin docs #### 🤖 Dependencies - chore(deps): bump lodash from 4.17.21 to 4.17.23 (#1282) #### Committers: 3 - dependabot[bot] - Ollie Monk - Steven Serrata
Major performance improvement: The new `externalJsonProps` option (enabled by default) dramatically reduces build times and bundle sizes by externalizing large JSON props from MDX files. - New `externalJsonProps` plugin option significantly improves build performance - Sticky positioning for the API Explorer right panel improves UX on long API pages - Dynamic request body updates when switching anyOf/oneOf tabs #### 🚀 New Feature - feat(plugin): add externalJsonProps option (enabled by default) to improve build performance (#1279) - feat(theme): add sticky positioning to API Explorer right panel (#1288) - feat: dynamically update request body when anyOf/oneOf tab changes (#1287) #### 🐛 Bug Fix - fix: render inline enum values in anyOf schemas (#1286) - fix: generate correct examples for different request content types (#1284) #### 🏠 Refactoring - refactor: change plugin and theme types.ts to types.d.ts (#1281) - refactor: externalize using create() and drop size threshold requirement (#1280) #### 📝 Documentation - docs: sync README and intro.mdx with plugin docs #### 🤖 Dependencies - chore(deps): bump lodash from 4.17.21 to 4.17.23 (#1282) #### Committers: 3 - dependabot[bot] - Ollie Monk - Steven Serrata
Description
Implements changes suggested by @slorber in #1279
Motivation and Context
How Has This Been Tested?
This deploy preview