Feature: Scaling Lexical for large documents using chunked multi-editor architecture
- Dominant language
- TypeScript
- Stars
- 23.9k
- Forks
- 2.2k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 61
Description
## Description
I’m building a large document editor (Word/Google Docs-like) using Lexical.
Problem
I need to support:
~300–1000 page documents
lossless import/export (HTML/structured docs)
smooth editing on low-end machines
A single Lexical editor becomes heavy at this scale due to large EditorState and DOM size.
Proposed architecture (summary)
I’m considering:
A canonical document model as source of truth
Chunk engine to split document into block-based units
Viewport-based virtualization
Multiple LexicalComposer instances mounted only for visible chunks
Separate layout engine for page view rendering
### Full design reference:
---
**Word-Class Document Editor Architecture**
This document describes the architecture of a scalable, Word-class document editor designed for large documents, lossless imports, and high-performance editing on low-end machines.
---
**1. Core Principle**
> **The Document Model is the only source of truth.**
Everything else in the system is a projection:
* Lexical ? editing layer
* Chunk Engine ? performance partitioning
* Layout Engine ? page/web rendering
* UI ? visual representation
No other layer owns canonical data.
**2. High-Level Architecture**
Document Model (Source of Truth)
?
Chunk Engine (Storage Partitioning)
?
Viewport Virtualization (Performance Control)
?
Mounted Lexical Editors (Editing Runtime)
?
Layout Engine (Page/Web Rendering)
?
UI Renderer
---
3. Document Model (Core Layer)
Purpose
The Document Model is the canonical representation of all content.
Structure
Syntax:
Document {
blocks: Block[]
}
Block {
id: string
type: "paragraph" | "heading" | "table"
text: string
styles: StyleSpan[]
}
**Responsibilities**
* Store all document content
* Maintain stable IDs
* Track structure and formatting
* Remain independent of UI and rendering
**Rules**
* No page information
* No chunk information
* No DOM / Lexical dependency
# 4. Chunk Engine (Storage Layer)
## Purpose
The Chunk Engine divides large documents into manageable units for performance optimization.
## Structure
syntax
Chunk {
id: string
blockIds: string[]
dirty: boolean
version: number
}
## Responsibilities
* Partition document into chunks (e.g., 50–200 blocks per chunk)
* Track dirty state for updates
* Enable lazy loading and unloading
* Improve performance for large documents
## Rules
* NOT related to pages
* NOT related to layout
* NOT tied to Lexical or UI
---
# 5. Viewport Virtualization Layer
## Purpose
Controls which chunks are actively mounted in the editor.
## Behavior
Only chunks in or near the viewport are active:
Visible:
Chunk 48
Chunk 49
Chunk 50
Mounted:
3–5 Lexical editors
Unloaded:
Remaining chunks
## Responsibilities
* Mount/unmount Lexical editors dynamically
* Manage scroll-based loading
* Maintain constant memory usage
---
# 6. Lexical Layer (Editing Runtime)
## Purpose
Lexical is the interactive editing surface.
## Key Concept
Lexical is NOT the document. It is a projection.
## Structure
Each mounted chunk becomes a Lexical instance:
## Responsibilities
* Handle typing and input
* Manage cursor and selection
* Process IME input
* Maintain local editing state
## Output
Lexical emits commands:
UpdateBlockText(blockId, newText)
InsertBlock(...)
DeleteBlock(...)
---
# 7. Layout Engine (Page/Web Rendering)
## Purpose
Computes visual representation of the document.
## Key Concept
> Pages are computed, not stored.
## Structure
PageMap {
blockId ? pageIndexes[]
}
## Responsibilities
* Line breaking
* Page breaking
* Pagination rules
* Reflow calculations
* Rendering layout updates
## Example
Before edit:
Page 5:
Paragraph B
Page 6:
Paragraph C
After edit:
Page 5:
Paragraph B (partial)
Page 6:
remainder of B
Paragraph C
---
# 8. System Flow (Write Operation)
When a user types:
## Step 1: Input in Lexical
User modifies text inside active chunk.
## Step 2: Lexical updates local state
Chunk-level editor updates.
## Step 3: Command emitted
UpdateBlockText(blockId, newText)
## Step 4: Document Model update
Canonical state is updated.
## Step 5: Chunk marked dirty
Affected chunk flagged for recomputation.
## Step 6: Layout recalculation
Only affected region is recomputed.
## Step 7: UI updates
Pages and visible content are re-rendered.
---
# 9. Page View System
## Key Principle
> Pages are a visual projection, not stored data.
## Flow
Document Model
?
Layout Engine
?
Page Mapping
?
UI Renderer
## Behavior
Typing can move content across pages without modifying:
* chunk structure
* document model
* Lexical structure
Only layout mapping changes.
---
# 10. Design Rules
## Rule 1
Chunks ? Pages
## Rule 2
Lexical ? Source of Truth
## Rule 3
Pages are computed, not stored
## Rule 4
Only Document Model is permanent state
## Rule 5
Chunking is a performance optimization, not a structural model
---
# 11. Architecture Diagram
```text
+--------------------+
¦ Document Model ¦
¦ (Source of Truth) ¦
+--------------------+
¦
+-------------------------------+
¦ ¦
+------?------+ +-------?-------+
¦ Chunk Engine ¦ ¦ Layout Engine ¦
¦ (Storage) ¦ ¦ (Pagination) ¦
+--------------+ +---------------+
¦ ¦
? ?
+--------------+ +----------------+
¦ Lexical Pool ¦ ¦ Page Renderer ¦
¦ (Mounted) ¦ ¦ (Virtual UI) ¦
+--------------+ +----------------+
```
---
# 12. System Goals
This architecture enables:
* High-performance editing of large documents
* Constant memory usage under load
* Lossless import/export pipelines
* Page + web view rendering
* Future support for collaboration and track changes
---
# 13. Summary
This system separates concerns into four independent layers:
* **Document Model** ? truth
* **Chunk Engine** ? scalability
* **Lexical Layer** ? editing
* **Layout Engine** ? rendering
This separation ensures long-term scalability and maintainability for enterprise-grade document editing systems.
---
Additional question
If anyone has tried similar approaches, what were the biggest issues (selection sync, undo consistency, performance, etc.)?
Contributor guide
Research direction
The issue names no repository files, tests, or entry points. Start by evaluating the proposed canonical model, chunk engine, virtualization, and multiple LexicalComposer instances against the questions about synchronization, selection, undo consistency, and performance. A completed outcome is not defined beyond determining whether this architecture is viable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100