facebook / lexical

Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.
https://lexical.dev
MIT License
17.92k stars 1.5k forks source link

Feature: perf: reduce listeners by current selection path #6101

Open 1yasa opened 1 month ago

1yasa commented 1 month ago

In a text content exceeding 10M, it contains hundreds of thousands of blocks, with each block monitoring a series of events in real time (which can lead to excessive memory and CPU usage). However, there is actually room for optimization.

That is, by monitoring changes in selection to obtain the node path where the selection is located, only the blocks on the free node path execute some monitoring events.

Here is my solution:

export default class Index {
    editor = null as LexicalEditor
    path = []

    constructor() {}

    init(editor: Index['editor']) {
        this.editor = editor
    }

    watcher() {
        const selection = $getSelection()

        if (!$isRangeSelection(selection)) return

        const anchor = selection.anchor
        const focus = selection.focus

        if (anchor.offset !== focus.offset) return

        const parents = anchor.getNode().getParents()
        const path = parents.map(item => ({ type: item.getType(), key: item.getKey() }))

        if (path === this.path) return

        this.editor.dispatchCommand(SELECTION_ELEMENTS_CHANGE, path)

        console.log(path)
    }

    register() {
        return mergeRegister(
            this.editor.registerCommand(
                SELECTION_CHANGE_COMMAND,
                this.watcher.bind(this),
                COMMAND_PRIORITY_CRITICAL
            )
        )
    }
}