v0.51.0
apify/crawleev0.51.0Sep 17, 2026by etrepum
Upgrading?
AI Summary
This release introduces declarative JSON serialization schemas via `$config` for nodes, enabling faster and safer serialization. It also moves npm packages to ESM-only and deprecates the `LexicalComposer` in favor of `LexicalExtensionComposer`.
Key Highlights
- Declarative serialization schemas for nodes
- Compact JSON export option
- Generated serialization code via compiler
- New `@lexical/fast-check` package
- ESM-only npm packages
Breaking Changes
- npm packages are ESM only
- `exportJSON` may serialize the instance as-is
- Deprecated Prism re-exports removed from `@lexical/code`
New Features
- Declarative serialization schemas
- Compact JSON export
- Generated serialization code
- Fast-check property-based testing
- Subpath exports for extensions
Full Release Notes
v0.51.0 is a monthly release with one large new feature: nodes can now declare their JSON serialization as a schema on `$config`. This declarative schema is faster, safer, and more flexible than the hand-written methods. The metadata it provides enables a compact export option with all default values elided, the code generator that provides faster import and export for every node that lexical ships, a new [`@lexical/fast-check`](https://lexical.dev/docs/api/modules/lexical_fast-check) package for property-based tests, and it provides a path to future features that rely on knowing the structure of the nodes (e.g. additional codecs and dev tools). This is a big step towards Lexical 1.0, the next few releases are expected to be focused on moving everything (including docs and examples) to the latest Extension and `$config` APIs and removing deprecated functionality. Two related changes in this release are that we are publishing ESM-only to npm now (cjs builds are still supported in the source tree), and `LexicalComposer` is deprecated for `LexicalExtensionComposer`. Expect anything `@deprecated` to be removed soon. ### Breaking Changes * **npm packages are ESM only.** Every package declares `"type": "module"` and its `exports` map offers `development` / `production` / `default` conditions with no `require` branch; the CommonJS build remains in-tree only for Meta's www. Bundlers are unaffected. CommonJS code can `require()` the packages on Node.js 20.19+ (the builds have no top-level `await`), and older Node.js must use `await import(...)` — but a dependency the app also loads through `require()` can then exist twice, which breaks handing its objects to Lexical (`yjs` docs to `@lexical/yjs`, `@preact/signals-core` signals from `@lexical/extension`), so load those as ESM too. Metro bundles both builds unless you add the condition for Lexical's packages; see the [module formats FAQ](https://lexical.dev/docs/faq) ([#9127](https://github.com/facebook/lexical/pull/9127)) * [`lexical`](https://lexical.dev/docs/api/modules/lexical) — **`exportJSON` may serialize the instance as-is.** A property declared with `withField` is read straight off the node instead of through its accessor, so `exportJSON` no longer resolves `getLatest()` for you and a stale reference can write stale values (and a property whose accessor a subclass overrode still resolves, so one object can mix the two). Nothing inside Lexical is affected — the walk, the clipboard selection export and `editorState.toJSON()` all start from the node map — but call `getLatest()` yourself on a reference you kept across a mutation ([#8602](https://github.com/facebook/lexical/pull/8602)) * [`@lexical/code`](https://lexical.dev/docs/api/modules/lexical_code) — the deprecated Prism re-exports are gone, along with the `@lexical/code-prism` dependency (so Prism no longer lands in a bundle that only imports `@lexical/code`). Import `CODE_LANGUAGE_FRIENDLY_NAME_MAP`, `CODE_LANGUAGE_MAP`, `getCodeLanguageOptions`, `getCodeLanguages`, `getCodeThemeOptions`, `getLanguageFriendlyName`, `normalizeCodeLanguage` (formerly also `normalizeCodeLang`), `PrismTokenizer` and `registerCodeHighlighting` from [`@lexical/code-prism`](https://lexical.dev/docs/api/modules/lexical_code_prism) ([#9141](https://github.com/facebook/lexical/pull/9141)) ### Deprecations * [`@lexical/react`](https://lexical.dev/docs/api/modules/lexical_react) — `LexicalComposer` is deprecated in favor of `LexicalExtensionComposer` and is expected to be removed in a future major. `LexicalComposer` cannot accept extensions, so any feature shipped as one is unreachable from an editor it builds; the migration is usually a two-line change ([#9168](https://github.com/facebook/lexical/pull/9168), [React extensions guide](https://lexical.dev/docs/extensions/react)) ### New APIs & Features * [`lexical`](https://lexical.dev/docs/api/modules/lexical) — **Declarative serialization schemas** (experimental). A node that uses `$config` declares its serialized properties once in the new `json` property, and that single declaration drives `importJSON`, `updateFromJSON` and `exportJSON`: `nodeSchema`, `withField` / `withAccessors`, and the value combinators (`stringValue`, `numberValue`, `booleanValue`, `enumValue`, `arrayValue`, `objectValue`, `unionValue`, `rawValue`, `transformValue`, `nullable`, `optional`, …). Every built-in node declares one, and most custom nodes now need no JSON serialization code at all. Output is unchanged by default ([#8602](https://github.com/facebook/lexical/pull/8602), [serialization docs](https://lexical.dev/docs/serialization/serialization)). * [`lexical`](https://lexical.dev/docs/api/modules/lexical) — **Compact JSON export**, opt-in via `editorState.toJSON(true)` or `$withCompactExport(true, cb)` (with `$isCompactExport()` for schema getters, plus `$exportNodeJSON` and the `CompactSerializedEditorState` / `ParsableSerializedEditorState` / `LexicalParseJSON` / `SerializedPartial` types). It omits properties equal to their schema default, properties the parser derives, and the deprecated `version`. The raw objects are well under half the legacy size — which matters for structured clones and worker messages — but after gzip the two are a wash. Both forms parse back to the same document; only a Lexical new enough to know the schemas can read the compact one, so keep writing the legacy form until every reader is upgraded ([#8602](https://github.com/facebook/lexical/pull/8602)) * [`@lexical/compiler`](https://lexical.dev/docs/api/modules/lexical_compiler) — **Generated serialization code.** Every built-in node class ships straight-line serialization generated from its own schema at build time, producing byte-identical JSON to the schema-driven path that continues to serve custom nodes ([#8602](https://github.com/facebook/lexical/pull/8602)) * [`@lexical/fast-check`](https://lexical.dev/docs/api/modules/lexical_fast-check) — New package deriving [fast-check](https://fast-check.dev) arbitraries from those schemas: `nodeArbitrary(NodeClass)` generates exactly the serialized JSON a node's parser accepts, each property independently present or absent. Useful for the bugs fixtures hide, such as a property `afterCloneFrom` forgot to copy. `fast-check` is a peer dependency; `getComposedSchemaFields` in core inspects a class's schema without generating anything ([#8602](https://github.com/facebook/lexical/pull/8602)) * [`@lexical/extension`](https://lexical.dev/docs/api/modules/lexical_extension) — Published as subpath exports, one entry per extension (`@lexical/extension/AutoFocusExtension`, …), with compiler and lint enforcement of the source import convention. The barrel import is unchanged, and shared modules such as signals keep a single instance ([#9161](https://github.com/facebook/lexical/pull/9161)). This is primarily only useful as a consumer if you are not using tree-shaking. ### Notable Fixes **Bundling, tree-shaking & types** * A production import of only `createCommand` no longer retains the editor ([#9121](https://github.com/facebook/lexical/pull/9121)), and the remaining module-scope side effects that defeated tree-shaking are gone, with a bare-import residue check now run over every entry ([#9124](https://github.com/facebook/lexical/pull/9124)); extension editors build under loose-mode transpilation ([#9134](https://github.com/facebook/lexical/pull/9134)) * Flow: `defineExtension` was uncallable, making the extension types unusable ([#9132](https://github.com/facebook/lexical/pull/9132)); declarations can now express an extension with dependencies ([#9176](https://github.com/facebook/lexical/pull/9176)); modern variance keywords survive into the www stubs ([#9154](https://github.com/facebook/lexical/pull/9154)) **Selection & editing** * No redundant selection-change command on Safari link selection ([#9163](https://github.com/facebook/lexical/pull/9163)); `TextNode.setMode`, `setTextContent` and `isSimpleText` read the latest state ([#9162](https://github.com/facebook/lexical/pull/9162)); `$removeTextFromCaretRange` no longer leaves a childless list or table as the root's only child ([#9116](https://github.com/facebook/lexical/pull/9116)); a text entity keeps the style and detail of the text it replaces ([#9130](https://github.com/facebook/lexical/pull/9130)); selection overlay listeners are notified when rectangles are removed ([#9117](https://github.com/facebook/lexical/pull/9117)) **Lists, tables & Markdown** * Indenting between two nested lists no longer converts the second list's type ([#9118](https://github.com/facebook/lexical/pull/9118)); `$mergeCells` no longer keeps the empty paragraph of the target cell ([#9122](https://github.com/facebook/lexical/pull/9122)); text left outside a Markdown link keeps its format ([#9131](https://github.com/facebook/lexical/pull/9131)) **Playground & docs** * Card/Review CSS placeholders are cleared reliably on paste in Safari ([#9129](https://github.com/facebook/lexical/pull/9129)) and releasing a CardNode drag no longer selects the node ([#9135](https://github.com/facebook/lexical/pull/9135)); new docs on Lexical being a singleton per app, and why a library must declare it as a peer dependency ([#9125](https://github.com/facebook/lexical/pull/9125)) Plus the usual dependency updates across the rollup, shikijs, vitest, docusaurus/typedoc and flow/hermes groups. ## What's Changed * v0.50.0 by @etrepum in https://github.com/facebook/lexical/pull/9110 * [lexical][lexical-compiler] Bug Fix: Let esbuild drop the editor from a createCommand-only production import by @zurfyx in https://github.com/facebook/lexical/pull/9121 * [*] Bug Fix: Remove the remaining module-scope side effects that defeat tree-shaking by @etrepum in https://github.com/facebook/lexical/pull/9124 * [lexical-playground] Bug Fix: clear Card/Review CSS placeholders reliably on paste in Safari by @sahiee-dev in https://github.com/facebook/lexical/pull/9129 * [lexical-website] Documentation Update: document that Lexical is a singleton per app and libraries must declare it as a peer dependency by @potatowagon in https://github.com/facebook/lexical/pull/9125 * [lexical-markdown] Bug Fix: text left outside a markdown link keeps its format by @Om-singhaI in https://github.com/facebook/lexical/pull/9131 * [lexical] Fix: make the extension Flow types usable (defineExtension was uncallable) by @potatowagon in https://github.com/facebook/lexical/pull/9132 * build(deps-dev): bump esbuild from 0.27.7 to 0.28.1 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9123 * [lexical-table] Bug Fix: $mergeCells no longer keeps the empty paragraph of the target cell by @Om-singhaI in https://github.com/facebook/lexical/pull/9122 * [lexical-utils] Bug Fix: notify when selection overlay rectangles are removed by @mehuljariwala in https://github.com/facebook/lexical/pull/9117 * [lexical] Bug Fix: $removeTextFromCaretRange no longer leaves a childless list or table as the root's only child by @Om-singhaI in https://github.com/facebook/lexical/pull/9116 * [lexical-playground] Bug Fix: avoid node selection on CardNode drag release by @kavyansh18 in https://github.com/facebook/lexical/pull/9135 * [lexical-extension] Fix: use Array.from over iterable spread so extension editors build under loose-mode transpilation by @potatowagon in https://github.com/facebook/lexical/pull/9134 * [lexical-text] Bug Fix: a text entity keeps the style and detail of the text it replaces by @Om-singhaI in https://github.com/facebook/lexical/pull/9130 * [*] Breaking change: Publish ESM only to npm and keep the CommonJS build for www by @etrepum in https://github.com/facebook/lexical/pull/9127 * [lexical-code] Breaking change: drop the deprecated prism re-exports and the @lexical/code-prism dependency by @etrepum in https://github.com/facebook/lexical/pull/9141 * build(deps-dev): bump vitest from 4.1.8 to 4.1.11 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9140 * build(deps): bump the docusaurus-and-typedoc group with 13 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9142 * build(deps-dev): bump the flow-and-hermes group with 4 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9143 * build(deps-dev): bump baseline-browser-mapping from 2.10.33 to 2.11.0 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9139 * build(deps): bump the shikijs group with 6 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9145 * build(deps): bump the rollup group across 1 directory with 5 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9144 * [lexical-list] Bug Fix: indenting between two nested lists no longer converts the second list's type by @Om-singhaI in https://github.com/facebook/lexical/pull/9118 * [*] Bug Fix: Keep modern Flow variance keywords in the www Flow stubs by @potatowagon in https://github.com/facebook/lexical/pull/9154 * build(deps-dev): bump the dev-dependencies group across 1 directory with 26 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9150 * build(deps-dev): bump flow-bin from 0.330.0 to 0.331.0 in the flow-and-hermes group by @dependabot[bot] in https://github.com/facebook/lexical/pull/9156 * [lexical-extension][*] Refactor: publish @lexical/extension as subpath exports with compiler+lint enforcement by @etrepum in https://github.com/facebook/lexical/pull/9161 * [lexical] Bug Fix: Avoid redundant selection change command by @levensta in https://github.com/facebook/lexical/pull/9163 * [lexical] Bug Fix: TextNode setMode, setTextContent and isSimpleText read the latest state by @Dev-next-gen in https://github.com/facebook/lexical/pull/9162 * [lexical-react] Chore: Deprecate LexicalComposer in favor of LexicalExtensionComposer by @potatowagon in https://github.com/facebook/lexical/pull/9168 * build(deps-dev): bump eslint from 10.9.1 to 10.10.0 in the dev-dependencies group across 1 directory by @dependabot[bot] in https://github.com/facebook/lexical/pull/9158 * build(deps): bump date-fns from 4.1.0 to 4.4.0 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9159 * [lexical][*] Feature: node JSON serialization schemas, with compact export by @etrepum in https://github.com/facebook/lexical/pull/8602 * build(deps): bump @babel/parser from 8.0.0 to 8.0.4 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9160 * build(deps): bump immutable from 4.3.8 to 4.3.9 by @dependabot[bot] in https://github.com/facebook/lexical/pull/9175 * build(deps-dev): bump the vitest group across 1 directory with 2 updates by @dependabot[bot] in https://github.com/facebook/lexical/pull/9157 * [lexical] Fix: Flow declarations cannot express an extension with dependencies by @potatowagon in https://github.com/facebook/lexical/pull/9176 ## New Contributors * @mehuljariwala made their first contribution in https://github.com/facebook/lexical/pull/9117 * @kavyansh18 made their first contribution in https://github.com/facebook/lexical/pull/9135 * @Dev-next-gen made their first contribution in https://github.com/facebook/lexical/pull/9162 **Full Changelog**: https://github.com/facebook/lexical/compare/v0.50.0...v0.51.0
Related Repositories
openclaw/openclaw★ 392,695
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
nilbuild/developer-roadmap★ 370,066
Interactive roadmaps, guides and other educational content to help developers grow in their careers.
morluto/rea★ 357,576
Reverse engineer anything with agents, from app behavior down to native binaries.
anomalyco/opencode★ 219,661
The open source coding agent.
n8n-io/n8n★ 208,248
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.