Improve rendering and schema loading performance#1690
Open
DCkQ6 wants to merge 1 commit into
Open
Conversation
- Build editor tree off-screen to avoid per-element reflows; re-attach
in a single DOM operation. Suppress onChange during build via a
building flag. Wrap in try/finally to guarantee cleanup on error.
- Parallelize external ref loading with Promise.all; split loader into
helper methods. Move onAllSchemasLoaded() to load() so it fires once.
Memoize expandSchema/expandRefs by schema object identity.
- Pre-bucket validation errors by child key/index in ObjectEditor and
ArrayEditor before passing down, avoiding full-list scans per child.
- Lazy-init Validator instances in MultipleEditor; extract _getTypeSchema
helper; add getDefault() override for oneOf/anyOf per-type defaults.
- Add onContainerAttached() hook to AbstractEditor; use it in
ObjectEditor (re-run grid layout) and SignatureEditor (resize canvas)
after the container is in the live DOM.
- Replace extend({}, ...) with spread/Object.assign throughout; add
null-guard to overwriteExistingProperties; update docker compose CLI.
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.
Hello, we are using this library to render a fairly large schema, and in our case it became quite painful to wait until it finished loading. I used Claude Opus to optimize it and ran a few review loops. It significantly decreased the loading time (1.5s vs 13s on my machine in the Chrome browser). All tests pass, and our large schema renders correctly. I hope these improvements will be useful to you.
Below Summary of changes from my fellow friend Opus-4.6
This PR reduces initial render time and schema loading overhead through several targeted optimizations.
Off-screen DOM build (core.js, editor.js)
The editor tree is now built while root_container is detached from the live DOM and re-attached in a single appendChild call. This eliminates per-element reflows during construction. A building flag suppresses onChange() calls for the duration. The build block is wrapped in try/finally to guarantee root_container is always re-attached and building is always cleared, even if a build step throws.
A new onContainerAttached() lifecycle hook (empty stub on AbstractEditor) is called on all editors after re-attachment, allowing editors to perform layout-dependent initialization that requires a live DOM.
Schema loading (schemaloader.js)
External ref loading is parallelized using Promise.all instead of sequential await per URI. The monolithic _asyncloadExternalRefs loop is split into _loadSingleRef, _loadUrnRef, and _loadAjaxRef helpers to improve readability and testability. onAllSchemasLoaded() is moved to the top-level load() method so it fires exactly once after the full ref graph resolves, restoring the pre-existing single-fire guarantee.
expandSchema() and expandRefs() results are memoized by schema object identity (Map) to avoid re-expanding the same schema repeatedly. The oneOf handler is fixed to use map() instead of reduce() and to avoid clobbering the parent schema's default when merging.
Validation error dispatch (object.js, array.js)
showValidationErrors() in both ObjectEditor and ArrayEditor now pre-buckets errors by direct child key/index before passing them down. Previously the full error array was passed to every child, causing O(n×m) path comparisons. Each child now only receives errors that belong to it.
MultipleEditor lazy validators (multiple.js)
Validator instances are now created lazily via _getValidator(i) instead of being eagerly instantiated for all types at build time. _getTypeSchema(i) is extracted as a shared helper used by both _getValidator and buildChildEditor. A getDefault() override checks per-type default values in oneOf/anyOf schemas before falling back to the parent default.
SignatureEditor off-screen fix (signature.js)
The canvas reference is stored on this.signatureCanvas and initial CSS sizing (width: 100%) is applied at build time. A onContainerAttached() override reads the real container width after the DOM is live and updates canvas.width accordingly, fixing the canvas sizing regression caused by off-screen construction.
Grid layout fix (object.js)
ObjectEditor adds an onContainerAttached() override that re-runs layoutEditors() for grid-format objects after the container is in the live DOM. The existing diff-check inside layoutEditors() makes the second call a no-op when heights do not affect the computed layout.
Misc