From e26202a3e2567006f790cb01425c1e83651e8fa3 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 3 Nov 2026 21:50:40 +0100 Subject: [PATCH] perf(editor): only serialize markdown on update when it is read CollaborativeEditor serialized the whole document to markdown on every editor update to emit `update:content`, even when no listener uses the result. On large documents this blocks every keystroke, especially in Chromium where prosemirror-markdown's serializer is quadratic in the output size. Emit the markdown as a getter so it is only serialized when a listener reads it. Benchmark on a 500 kB markdown document (headings, paragraphs, lists with marks), headless browsers against a local instance, median per step, before -> after: Chromium: - typing (cursor at start): 981 ms -> 67 ms - typing (cursor at end): 933 ms -> 34 ms - toggle bold on a word: 930 ms -> 50 ms - editor update handlers: ~870 ms -> <1 ms Firefox: - typing (cursor at start): 125 ms -> 76 ms - typing (cursor at end): 55 ms -> 47 ms - toggle bold on a word: 67 ms -> 88 ms (within noise) - editor update handlers: ~9 ms -> 1 ms Large tables are not affected by this change; their cost lies elsewhere. Related to #908 Signed-off-by: Jonas Assisted-by: ClaudeCode:claude-opus-5-5 --- src/components/CollaborativeEditor.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/CollaborativeEditor.vue b/src/components/CollaborativeEditor.vue index a798161e27f..9d583a2ef24 100644 --- a/src/components/CollaborativeEditor.vue +++ b/src/components/CollaborativeEditor.vue @@ -680,9 +680,11 @@ export default defineComponent({ if (window.OCA.Text.logEditorUpdates) { this.debugContent(editor) } - const proseMirrorMarkdown = this.serialize() + const serialize = this.serialize this.$emit('update:content', { - markdown: proseMirrorMarkdown, + get markdown() { + return serialize() + }, }) },