TypeCellOS / BlockNote

A React Rich Text Editor that's block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.
https://www.blocknotejs.org/
Mozilla Public License 2.0
6.35k stars 433 forks source link

Investigate server-util package usage for Next.js SSR and other environments #942

Open YousefED opened 2 months ago

YousefED commented 2 months ago

@blocknote/server-util has been designed / tested for usage in node.js based environments.

However, some users want to use it in Next.js server side actions or Partykit functions (see https://github.com/TypeCellOS/BlockNote/pull/451). These functions probably run in different environments, so we'll need to investigate compatibility with this

leo-paz commented 1 month ago

hey @YousefED sorry to bug but any updates on this?

still getting the error in my server action or /api/route.ts:

createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component
And it doesn't change if it's in an api route vs a server action
linhtrinh18 commented 1 month ago

@YousefED Same here, using nextjs 14 and the error pops up:

Server Error Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component

This error happened while generating the page. Any console logs will be displayed in the terminal window.

import { ServerBlockNoteEditor } from "@blocknote/server-util";

export const Introduction = async ({ text }: { text: any }) => { const editor = ServerBlockNoteEditor.create(); const html = await editor.blocksToFullHTML(text);

return ( <div dangerouslySetInnerHTML={{ __html: html }} /> ); };

Syammed2429 commented 1 month ago

Yep, I'm also getting the same error as @linhtrinh18 , please help to fix it @YousefED and @matthewlipski

'use server'

import { ServerBlockNoteEditor } from "@blocknote/server-util";

export const blockToYDoc= async ( blocks: any ) => {
const editor = ServerBlockNoteEditor.create();
const blocksToYDocs = await editor.blocksToYDoc (blocks);

return blocksToYDocs
}

error

Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more:
YousefED commented 1 month ago

I've done some further investigation into this. I want to split my findings into two parts:

NextJS (SSR etc) Because BlockNote blocks are defined using React, we need to access certain react functionality on the server to call BlockNote APIs. For example, we need to render certain components to get their HTML version (for Blocks To HTML / Blocks To Markdown, etc). This is different than most React apps, because BlockNote uses React internally as a framework. However, next.js seems to block various React calls. This means certain React APIs are not available for BlockNote to use when evaluating calls like "Blocks to HTML". I tried some workarounds but could not find an easy way to call React APIs not affected / blocked by the Next bundler.

It would be interesting to explore what a "next.js-first" architecture for BlockNote could look like (e.g.: with native support for SSR, etc). However, I think this would be several weeks of work at a minimum so it would require a corporate sponsor (I don't have a need for this feature myself at this moment).

A workaround for now is to run a regular Node server somewhere and use server-util from there, and then expose an API.

Non-node runtimes (bun, deno, etc) There also was a report that JSDom doesn't work in non-node environments like Bun (https://discord.com/channels/928190961455087667/1015169282444894219/1269960495264305153). I think this should be fixable by making the DOM shim pluggable, and make it possible to use something like happy-dom instead of jsdom. Would gladly accept any PRs for this / will consider adding this option if there are more requests for this coming in