Lexical contributor here. I love what you've build here! A full-fledged collaborative rich text editor. I'm glad that Lexical worked well for you, we'd be happy to take your feedback throughout the development process, you can reach out to me over Discord by the same username or on our server.
I had to take a second pass on it. I thought I was maybe onto something when I wrote that originally. Is it a V8 perf hack? Nope, just my brain not functioning correctly at the time :P
Mostly referring to high-traffic surfaces here, like Facebook Feed or Messenger. The % varies depending on the environment and the previous Draft.js implementation (and their plugins) but overall it's been very positive, especially with low-end devices that went way over 16ms response time per keypress.
This is my point. Facebook surfaces include stuff like editing a post, sending a message. All of these have relatively small character limits versus a text editor that handles millions of lines with tens of millions of characters.
In the case of text editors, 1 object node per line implementations work fine for small files. They'll even edge out the overhead of more esoteric implementations requiring trees. Lookups are O(1) versus O(log n) in the depth of trees, but insertions get slow as you have to shift all the array elements. Again for few number of lines, that's fine. For small data ( tens of thousands of characters), even a giant string will do fine and within tens of milliseconds, too.
Facebook Blog / Article posts may get relatively long, but still not in the Megabytes ( metadata, not images ).
My point of contention is the claim and marketing that the library is suitable as a high performance text editor implementation. Depends on what the constraints and use case is. For Facebook posts and small editor widgets, I'll believe that. There is a hint that it can serve as the foundation for an IDE, but likely only a small snippet editor or a toy IDE implementation. The devil is in the details for a "serious" IDE / text editor like VSCode / Ace. It's an apple to bananas performance claim.
> low-end devices that went way over 16ms response time per keypress
Shaving milliseconds of keypresses for users on low end devices is msotly a Facebook and FANG concern. This performance concern is invisible and not important for someone looking to build an IDE where the users are accessing from a powerful device. For people editing huge files, the bottleneck are caused by data structures choices which I don't think will be mitigated by having a high level and convenient programming paradigm in the case of Lexical.
Sure, just submitted a new issue. Included in the issue, but I think there might be a more general problem with how block conversion is handled (at least for quote and code block types). On firefox at least, it's pretty easy to crash this by messing with block type dropdown.
We listen to a few typing related events and do some computation from here: keydown, input, beforeinput. Android, contrary to any other device, mostly relies on composition so Lexical makes sure to handle and flush these events accordingly.
We already provide most common plugins out of the box (inc. lists and tables) but if you're planning to build a feature rich interface with many custom plugins it may take somewhat longer.
3. Lexical is not strictly tied to collaboration but its plugin system was built to be extensible enough to cater all developers needs. Collaboration is just another plugin (@lexical/yjs) and does listen and perform the conversion every time there's changes in the EditorState.
This model of independent plugins that can be plugged-and-played without further ado also simplifies devX as collaboration can be added later when the application is mature without the need to rethink any of the plugins that were originally created for non-collab plain/rich text.
4. Lexical Web is just the first of many. We want to port the API and fundamentals to various others platforms, including iOS for which we are already performing the initial set of testing. Cross-platform means the API, including Node's will look alike and EditorState and node's properties will be compatible even if behind the scenes the reconciler is constrained by the toolkit available on each platform (and doesn't render or behave 100% like Web's).
Thanks for the pointer. His comparison of Draft vs Lexical makes a lot of sense. I'm keener to understand the different between Prosemirror vs Lexical. He mentions that he pulled the best ideas from libs like Prosemirror.
I'm curious how Lexical is an improvement over Prosemirror's approach. As to my current knowledge,
1. Prosemirror considers state as the source of truth and syncs to subsequent states using deltas. The state keeps in sync with view allowing us to directly modify states to bring effect in the view. I hope this is the core of Lexical as well. One thing that isn't to my satisfaction is syncing ad-hoc view changes to reverse update the state. Is it better in Lexical? basically can plugins like Grammarly not screw-up Lexical's internal state?
2. ProseMirror does take a modular approach. It has zero dependencies and allows us to pull in only the necessary parts needed for our feature-set. How similar or different is Lexical in this aspect?
3. Prosemirror has a rich plugin system. Everything is a plugin - even the keyboard shortcuts. Very similar to Lexical I hope?
4. ProseMirror has a concept of Decorators i.e if you want to decorate your views without reflecting those decorations on the model. For example, if we want to underline spelling errors, but not include spelling error boundaries in the rich text's core data model. How is this dealt with in Lexical?
Essentially, I'm curious as to what areas Prosemirror could have taken a better approach!
I don't think ProseMirror has taken a bad approach. I think we've just taken a different approach when it comes to the design of things. In Lexical, you rarely concern yourself with the DOM – and typically you deal with Lexical's node API directly and that's really all you touch.
Lexical also treat its own EditorState as the source of truth. We use DOM MutationObservers to ensure the DOM matches the EditorState at all times. We do allow external mutations from things like spellcheckers update Lexical – otherwise people wouldn't be able to use Grammarly and other tools with Lexical. However, that's really constrained so that they don't overreach.
Lexical also has the notion of double-buffering. When you update Lexical, or use a node transform, you're actually mutating the "work in progress" EditorState. Once Lexical feels that the EditorState is ready, it will commit it to the DOM, and that EditorState will become immutable and will reflect what you see on the page.
quick question: I assume it ships(or supports a plugin) with a serializer to convert an editor state JSON to HTML. Does it depend on browser APIs to do so? Can it be somehow liberated out of native DOM APIs and language bindings for JSON-2-HTML in common languages like Java & Rust.
This could be a huge win for simple multi-platform rendering.
The EditorState is fully JSON serializable. You can use JSON.stringify in the browser, or an alternative on other platforms. You can then pass the stringified values around and parse them using `editor.parseEditorState()`
But, let's say I'd like to parse this stored state and send an email (as HTML) on the server?
My best guess is to use a NodeJS/V8 instance on the server to somehow transform JSON to HTML using Lexical's serializer (if something like that exists). Even this is tricky because it might depend on browser DOM apis for the conversion.
A better solution would be support language specific bindings to get HTML from JSON with zero dependecies.
"Of all the ways of doing concurrency, callbacks are by far the worst,"
Why? Working with callbacks on a solo thread has proved to be more performant I/O wise than threads.
"for any other problem anything else will be much better than Node.js, even PHP."
Why?
While it might be true to certain extend (i.e. Node not being the right solution for many cases), this article is just filled with baseless arguments.