We have a writing application that has things split up into acts, chapters and scenes (like sub-chapters, or partial chapters).
Currently, acts and chapters are simple rows with input boxes for their name/number, scenes have a summary as well as their content. Which means we got 2 editor instances per scene.
The whole manuscript view as such creates a view that can be described as follows:
[act]
[chapter]
[scene with [content] and [summary] boxes next to each other]
Some of our users have started to create a high amount of scenes (e.g. over 500, in some cases even more than 800), which have to be initialized, layouted and rendered whenever opening the Manuscript.
We have modes where you can only show a single act or chapter, but sometimes (especially when revising a draft) this becomes a bit cumbersome.
Sadly, due to the nature of how the system works I don’t think I can virtualize any of this as we need the full editor contents rendered (for other bits and pieces). I also tried some browser hints via CSS to basically don’t do layouting until an element goes into the viewport - which also failed.
Is there a good way to properly handle this internally?
One idea I had, but not sure if it would even work, or is the right one, is to have ONE big editor instance with “virtual” nested documents. However, some of our users have novels that span multiple millions of words.
Any tips and tricks and further ideas would be appreciated. Thanks!
ProseMirror doesn’t provide any virtualization and, indeed, as you found, at some point page performance gets bad just due to the size of the content. In situations where we’ve profiled this, this turned out to be mostly due to the performance of browser layout and editing handling, rather than performance issues in ProseMirror itself. So probably, your only option is going to be to find a way to not render some of those editors—by virtualizing or by dividing them across pages somehow.
Hm. I mean, i know how virtualization works - I have implemented it on lists, tables and whatnot, but a full-blown text editor seems quite daunting.
Users kind of expect it to “just work” but that’s always easier said than done. I don’t think I can recycle ProseMirror instances that easily?
If this were a “simple” monospaced text editor, like VSCode, it would make a lot of things easier, but I don’t know how to pre-calculate element lengths in a context like ProseMirror (especially with custom nodes, CSS styling that can change paragraph spacing, indents, nested lists and tables and whatnot).
For example: we have a feature where a user can highlight some text (like a text marker), and we show these highlights as a little minimap right next to the scrollbar - similar to the one in VSCode. For this, we go over all highlight elements in the DOM, which requires them to be there in the first place. If I were to virtualize this, I would have to know whereabout this highlight would sit on screen (which can move around if you’re rescaling your window/browser).