diff --git a/packages/docusaurus-bundler/src/minifyHtml.ts b/packages/docusaurus-bundler/src/minifyHtml.ts index e84b03bede8d..e2897f08e224 100644 --- a/packages/docusaurus-bundler/src/minifyHtml.ts +++ b/packages/docusaurus-bundler/src/minifyHtml.ts @@ -105,7 +105,7 @@ async function getSwcMinifier(): Promise { const ignoredErrors: string[] = [ // TODO Docusaurus seems to emit NULL chars, and minifier detects it // see https://github.com/facebook/docusaurus/issues/9985 - 'Unexpected null character', + // 'Unexpected null character', ]; result.errors = result.errors.filter( (diagnostic) => !ignoredErrors.includes(diagnostic.message), diff --git a/packages/docusaurus/src/client/renderToHtml.tsx b/packages/docusaurus/src/client/renderToHtml.tsx index 0f79eb5bbe7e..7b79fe5605d8 100644 --- a/packages/docusaurus/src/client/renderToHtml.tsx +++ b/packages/docusaurus/src/client/renderToHtml.tsx @@ -6,75 +6,23 @@ */ import type {ReactNode} from 'react'; -import {renderToPipeableStream} from 'react-dom/server'; -import {Writable} from 'stream'; +// @ts-expect-error: see https://github.com/facebook/react/issues/31134 +import {renderToReadableStream as renderToReadableStreamImpl} from 'react-dom/server.browser'; +import {type renderToReadableStream as renderToReadableStreamType} from 'react-dom/server'; +import {text} from 'stream/consumers'; -export async function renderToHtml(app: ReactNode): Promise { - // Inspired from - // https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation - // https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/static-entry.js - const writableStream = new WritableAsPromise(); +const renderToReadableStream: typeof renderToReadableStreamType = + renderToReadableStreamImpl; - const {pipe} = renderToPipeableStream(app, { - onError(error) { - writableStream.destroy(error as Error); - }, - onAllReady() { - pipe(writableStream); - }, +export async function renderToHtml(app: ReactNode): Promise { + return new Promise((resolve, reject) => { + renderToReadableStream(app, { + onError: (error) => reject(error), + }).then(async (stream) => { + await stream.allReady; + // @ts-expect-error: it works fine + const html = await text(stream); + resolve(html); + }, reject); }); - - return writableStream.getPromise(); -} - -// WritableAsPromise inspired by https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/server-utils/writable-as-promise.js - -/* eslint-disable no-underscore-dangle */ -class WritableAsPromise extends Writable { - private _output: string; - private _deferred: { - promise: Promise | null; - resolve: (value: string) => void; - reject: (reason: Error) => void; - }; - - constructor() { - super(); - this._output = ``; - this._deferred = { - promise: null, - resolve: () => null, - reject: () => null, - }; - this._deferred.promise = new Promise((resolve, reject) => { - this._deferred.resolve = resolve; - this._deferred.reject = reject; - }); - } - - override _write( - chunk: {toString: () => string}, - _enc: unknown, - next: () => void, - ) { - this._output += chunk.toString(); - next(); - } - - override _destroy(error: Error | null, next: (error?: Error | null) => void) { - if (error instanceof Error) { - this._deferred.reject(error); - } else { - next(); - } - } - - override end() { - this._deferred.resolve(this._output); - return this.destroy(); - } - - getPromise(): Promise { - return this._deferred.promise!; - } } diff --git a/project-words.txt b/project-words.txt index 5c6c2590ef80..232a12a1d677 100644 --- a/project-words.txt +++ b/project-words.txt @@ -256,7 +256,6 @@ philpl photoshop Photoshop picomatch -Pipeable playbtn pluggable Pluggable