Download Latest Version v0.51.0 source code.zip (8.7 MB) Google Add to Preferred Sources
Home / v0.51.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-09-17 15.4 kB
v0.51.0 source code.tar.gz 2026-09-17 7.3 MB
v0.51.0 source code.zip 2026-09-17 8.7 MB
Totals: 3 Items   16.1 MB 3

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 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 (#9127)
  • 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)
  • @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 (#9141)

Deprecations

  • @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, React extensions guide)

New APIs & Features

  • 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, serialization docs).
  • 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)
  • @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)
  • @lexical/fast-check — New package deriving fast-check 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)
  • @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). 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), 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); extension editors build under loose-mode transpilation (#9134)
  • Flow: defineExtension was uncallable, making the extension types unusable (#9132); declarations can now express an extension with dependencies (#9176); modern variance keywords survive into the www stubs (#9154)

Selection & editing

  • No redundant selection-change command on Safari link selection (#9163); TextNode.setMode, setTextContent and isSimpleText read the latest state (#9162); $removeTextFromCaretRange no longer leaves a childless list or table as the root's only child (#9116); a text entity keeps the style and detail of the text it replaces (#9130); selection overlay listeners are notified when rectangles are removed (#9117)

Lists, tables & Markdown

  • Indenting between two nested lists no longer converts the second list's type (#9118); $mergeCells no longer keeps the empty paragraph of the target cell (#9122); text left outside a Markdown link keeps its format (#9131)

Playground & docs

  • Card/Review CSS placeholders are cleared reliably on paste in Safari (#9129) and releasing a CardNode drag no longer selects the node (#9135); new docs on Lexical being a singleton per app, and why a library must declare it as a peer dependency (#9125)

Plus the usual dependency updates across the rollup, shikijs, vitest, docusaurus/typedoc and flow/hermes groups.

What's Changed

New Contributors

Full Changelog: https://github.com/facebook/lexical/compare/v0.50.0...v0.51.0

Source: README.md, updated 2026-09-17