summaryrefslogtreecommitdiff
path: root/packages/integrations/react/server.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/react/server.js')
-rw-r--r--packages/integrations/react/server.js76
1 files changed, 72 insertions, 4 deletions
diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js
index 6ae49e7bc..b41492a7a 100644
--- a/packages/integrations/react/server.js
+++ b/packages/integrations/react/server.js
@@ -12,7 +12,7 @@ function errorIsComingFromPreactComponent(err) {
);
}
-function check(Component, props, children) {
+async function check(Component, props, children) {
// Note: there are packages that do some unholy things to create "components".
// Checking the $$typeof property catches most of these patterns.
if (typeof Component === 'object') {
@@ -42,7 +42,7 @@ function check(Component, props, children) {
return React.createElement('div');
}
- renderToStaticMarkup(Tester, props, children, {});
+ await renderToStaticMarkup(Tester, props, children, {});
if (error) {
throw error;
@@ -50,7 +50,13 @@ function check(Component, props, children) {
return isReactComponent;
}
-function renderToStaticMarkup(Component, props, children, metadata) {
+async function getNodeWritable() {
+ let nodeStreamBuiltinModuleName = 'stream';
+ let { Writable } = await import(nodeStreamBuiltinModuleName);
+ return Writable;
+}
+
+async function renderToStaticMarkup(Component, props, children, metadata) {
delete props['class'];
const vnode = React.createElement(Component, {
...props,
@@ -59,12 +65,74 @@ function renderToStaticMarkup(Component, props, children, metadata) {
let html;
if (metadata && metadata.hydrate) {
html = ReactDOM.renderToString(vnode);
+ if('renderToReadableStream' in ReactDOM) {
+ html = await renderToReadableStreamAsync(vnode);
+ } else {
+ html = await renderToPipeableStreamAsync(vnode);
+ }
} else {
- html = ReactDOM.renderToStaticMarkup(vnode);
+ if('renderToReadableStream' in ReactDOM) {
+ html = await renderToReadableStreamAsync(vnode);
+ } else {
+ html = await renderToStaticNodeStreamAsync(vnode);
+ }
+
}
return { html };
}
+async function renderToPipeableStreamAsync(vnode) {
+ const Writable = await getNodeWritable();
+ let html = '';
+ return new Promise((resolve, reject) => {
+ let error = undefined;
+ let stream = ReactDOM.renderToPipeableStream(vnode, {
+ onError(err) {
+ error = err;
+ reject(error);
+ },
+ onAllReady() {
+ stream.pipe(new Writable({
+ write(chunk, _encoding, callback) {
+ html += chunk.toString('utf-8');
+ callback();
+ },
+ destroy() {
+ resolve(html);
+ }
+ }));
+ }
+ });
+ });
+}
+
+async function renderToStaticNodeStreamAsync(vnode) {
+ const Writable = await getNodeWritable();
+ let html = '';
+ return new Promise((resolve) => {
+ let stream = ReactDOM.renderToStaticNodeStream(vnode);
+ stream.pipe(new Writable({
+ write(chunk, _encoding, callback) {
+ html += chunk.toString('utf-8');
+ callback();
+ },
+ destroy() {
+ resolve(html);
+ }
+ }));
+ });
+}
+
+async function renderToReadableStreamAsync(vnode) {
+ const decoder = new TextDecoder();
+ const stream = await ReactDOM.renderToReadableStream(vnode);
+ let html = '';
+ for await(const chunk of stream) {
+ html += decoder.decode(chunk);
+ }
+ return html;
+}
+
export default {
check,
renderToStaticMarkup,