-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Server-Side Rendering (SSR) Support for Lexical Editor #4960
Comments
Can you be more specific about what you've observed here? What tools are you using, what outcome are you expecting and what is actually happening? Another option is just to traverse the parsed JSON editor state and render whatever HTML you want from it on the server. |
Can you give an example here? What exactly are you trying to do that leads to the undesirable behavior? |
Hi @acywatson, Adding details below Our tech stack includes Observations:
(before loading) What We've Tried:
Possible solutionsIt would be immensely beneficial if we could have an integrated render-only editor that is compatible with server-side rendering. Maybe by using JSDOM to render the editor when DOM API's are not available. |
Thanks! I think this makes sense.
I'm curious about the shortcomings here? You don't need to really know about the internal workings of the Lexical editor. It's completely normal to traverse a serialized JSON tree and render it to another format (HTML in this case). This effectively exactly what the "render-only editor" you're asking for would do, AFAICT. We'd just be making it easier (for you) by wrapping it all up into a Lexical package. |
@acywatson We appreciate the suggestion to parse the JSON and generate HTML, but it does introduce complexities, as it requires a good understanding of Lexical's internal logic, potentially involving reverse engineering. For instance, deciphering how JSON is generated for formatted text (e.g., bold, italic) or how list items are handled can be intricate tasks. Moreover, this approach could become obsolete if Lexical decides to change its node generation logic in the future. Having an inbuilt server-side HTML generation capability within Lexical would be advantageous, ensuring that the logic remains up-to-date with any upcoming releases. We also believe that this feature would benefit not only us but also the broader community, especially those using SSR (Server-Side Rendering) frameworks like React. The ability to render content on the server is a fundamental requirement for various applications and aligns with modern development practices and the promotion of SSR by popular frameworks. It would enhance the versatility and usability of Lexical for a wide range of use cases. |
I'll be doing something similar with SSR soon and am currently researching how I might approach this with Next JS. One thought that comes to mind as a workaround: This (in theory) would allow us to render the HTML string on server, and render the full editor on client. There are some potential implications of this with setting inner HTML via string, you'd need to ensure the exported HTML is safe and secure, and you'd need to add in relevant css for the exported HTML, but it seems like a workable alternative to me. |
If possible, I would like you to parse the JSON and create a React component in a separate project. Read Only of course. Then, we can plug in customizations for some of them. SSR as well, but when reading an article, I may want to fire React's LOGIC on the client. Most Nodes (such as TextNode) are fine with exportDOM content, so I want a common React Component |
it's the same issue than Quilljs, just came form there for this, can't believe a project from Fracebook has the same dummy issue. most of us care about this because the SEO. |
Hi guys! please check this out: https://lexical-nextjs-ssr.vercel.app/ |
What do we need to close this issue? Perhaps some documentation? |
Well, the @2wheeh example is not that complex. But I have a feeling it's complex enough that the Lexical team will have to answer several questions about bugs or implementations. Just an idea, I think the DX could be taken a little further. If window is undefined, then lexical runs that little utility with the dom instance passed to it. So that Lexical users only have to worry about one line of code. |
Let's discuss. I agree that documenting it officially is a burden on the team that requires some up front consideration and potentially mitigation (via DX, as you suggest). |
Yes, I agree that my example is not enough as is. For example, adding more plugins which return JSX element will make codes ugly easily while achieving zero layout shift. This is bad for DX.
I love this ! |
Slightly tangential to this approach. We also had a use case to render Lexical content in NextJS with SSR. We ended up doing the more hacky approach. We created a native React Server Component for each standard Lexical components. Not only it renders fast, it also comes with any NextJS' goodies (hydration, etc.), so natively supports existing client/server components. The one-time effort to create the RSC copy was 1 day ish. The only maintenance item is to sync our RSC copy with Lexical's, but we don't see a lot of changes on the presentation-side standard HTML component. The custom components are already an RSC so no additional cost. Sadly, our RSC codes are tangled with our internal tooling but let me know if any of you are interested in some pointers. 🙏 Here is a demo page: |
@jmargatan I can't see how that link fits into all this. Maybe if you could show some code to explain your approach? |
Essentially there are 2 separate experiences:
After any modification in editable state, we persist the During non-editable serving / SSR, we (built a parser that) walk through the stored Sorry, our current code is tangled with internal implementation, but here is some hacky pseudocode: const parseNode = <T extends SerializedLexicalNode>(node: T, key: string): ReactNode => {
if (node.type == 'text') {
// For a node that has children, we recursively run this `parseNode` on each children.
// For a node that refers to our custom RSC components, we just render the component.
return <NonEditableText .../>
} else if (...) {
...
}
} For actual implementation you can mimic LexicalEditor's "registerXYZPlugin" pattern instead of if-else. The result is a server-rendered RSC streamed to the browser. React Suspense, if used, within any of the node will work as expected. Jumping between the 2 experience (editable and non-editable) means replacing the RSC with Lexical editor. |
Can we simply persist the HTML version for the editor state and render it server-side? |
what if I don't use next.js, but only react, and there I send the component and its content directly to
The code entered in this way, where there is a promise, will not work for me. Is it not possible to get html from lexical json using a simple parsing function that is native in lexical? |
I am interested too in a solution for We are currently using |
You're using jsdom, which is around 593.3 kB minified and gzipped. Honestly, it's a great choice for smaller applications, and I can see the effort you've put into making it work effectively. However, for larger applications, the size can start to matter, so it's something worth keeping in mind as your project grows. Great work so far! |
Use Case:
We are currently working on a project similar to Reddit, where our users utilize the Lexical Editor to create posts and comments. These posts are then displayed on their timelines using a read-only editor. This is a fundamental use case where we believe Server-Side Rendering (SSR) support is essential. SSR would greatly benefit us by allowing us to render these posts on the server, leading to improvements in user experience and SEO.
Current Issue:
Our observation is that the Lexical Editor's rendering is currently limited exclusively to the client-side due to its reliance on client-side rendering mechanisms. Consequently, posts are only rendered on the client side, which can have some drawbacks.
Challenges:
One of the challenges we've encountered is the time it takes for the editor to process data on the client side. This processing delay leads to noticeable UI jumps after content is loaded, which is not an ideal user experience.
Proposed Solutions:
We propose exploring two potential solutions to address these challenges:
Server-Side Rendering with JSDOM:
We suggest investigating the feasibility of enabling SSR for the Lexical Editor by utilizing libraries like JSDOM. This approach would empower us to render the editor within a Node.js/server environment, thus improving initial load times and overall performance.
Render-Only Editor Mode:
Another avenue to explore is the creation of a "render-only" mode for the Lexical Editor. This mode would be optimized for server-side rendering, offering a simplified and resource-efficient way to render the lexical tree.
How This Benefits the Project:
Implementing these solutions would not only enhance the user experience but also make our platform more SEO-friendly. It would address the limitations of client-side rendering, reduce processing time, and eliminate UI jumps, resulting in a smoother and more efficient application.
The text was updated successfully, but these errors were encountered: