summaryrefslogtreecommitdiff
path: root/packages/integrations
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2022-04-21 12:10:06 -0400
committerGravatar GitHub <noreply@github.com> 2022-04-21 12:10:06 -0400
commitae9ac5cbdceba0687d83d56d9d5f80479ab88710 (patch)
tree26fc15585e7ed77fd47607f5e7211050813fa642 /packages/integrations
parent3cdc5f1bfb7801be93c1df582b2ec1484566759b (diff)
downloadastro-ae9ac5cbdceba0687d83d56d9d5f80479ab88710.tar.gz
astro-ae9ac5cbdceba0687d83d56d9d5f80479ab88710.tar.zst
astro-ae9ac5cbdceba0687d83d56d9d5f80479ab88710.zip
Fixes using React.lazy and Suspense (#3160)
* Revert "Revert "Fixes using React.lazy and Suspense"" This reverts commit e621c2f7d3844e950168f4198e4dd1c6f43031d0. * Adds a changeset * Fix ts errors * Remove netlify metadata folder
Diffstat (limited to 'packages/integrations')
-rw-r--r--packages/integrations/deno/src/index.ts4
-rw-r--r--packages/integrations/deno/test/basics.test.js3
-rw-r--r--packages/integrations/deno/test/fixtures/basics/astro.config.mjs2
-rw-r--r--packages/integrations/deno/test/fixtures/basics/package.json3
-rw-r--r--packages/integrations/deno/test/fixtures/basics/src/components/React.jsx7
-rw-r--r--packages/integrations/deno/test/fixtures/basics/src/pages/index.astro3
-rw-r--r--packages/integrations/netlify/src/integration-edge-functions.ts4
-rw-r--r--packages/integrations/netlify/test/edge-functions/deps.ts1
-rw-r--r--packages/integrations/netlify/test/edge-functions/edge-basic.test.ts9
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs2
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json1
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/components/React.jsx7
-rw-r--r--packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro4
-rw-r--r--packages/integrations/react/server.js76
14 files changed, 118 insertions, 8 deletions
diff --git a/packages/integrations/deno/src/index.ts b/packages/integrations/deno/src/index.ts
index d1b3b14ba..f0658f2c8 100644
--- a/packages/integrations/deno/src/index.ts
+++ b/packages/integrations/deno/src/index.ts
@@ -23,6 +23,10 @@ export default function createIntegration(args?: Options): AstroIntegration {
},
'astro:build:setup': ({ vite, target }) => {
if (target === 'server') {
+ vite.resolve = vite.resolve || {};
+ vite.resolve.alias = vite.resolve.alias || {};
+ const alias = vite.resolve.alias as Record<string, string>;
+ alias['react-dom/server'] = 'react-dom/server.browser'
vite.ssr = {
noExternal: true,
};
diff --git a/packages/integrations/deno/test/basics.test.js b/packages/integrations/deno/test/basics.test.js
index 115883466..42efc87d9 100644
--- a/packages/integrations/deno/test/basics.test.js
+++ b/packages/integrations/deno/test/basics.test.js
@@ -13,6 +13,9 @@ Deno.test({
assertEquals(resp.status, 200);
const html = await resp.text();
assert(html);
+ const doc = new DOMParser().parseFromString(html, `text/html`);
+ const div = doc.querySelector("#react");
+ assert(div, 'div exists');
});
},
});
diff --git a/packages/integrations/deno/test/fixtures/basics/astro.config.mjs b/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
index e56fe2e98..af5f1aa6b 100644
--- a/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
+++ b/packages/integrations/deno/test/fixtures/basics/astro.config.mjs
@@ -1,8 +1,10 @@
import { defineConfig } from 'astro/config';
import deno from '@astrojs/deno';
+import react from '@astrojs/react';
export default defineConfig({
adapter: deno(),
+ integrations: [react()],
experimental: {
ssr: true
}
diff --git a/packages/integrations/deno/test/fixtures/basics/package.json b/packages/integrations/deno/test/fixtures/basics/package.json
index a623de766..7800873f7 100644
--- a/packages/integrations/deno/test/fixtures/basics/package.json
+++ b/packages/integrations/deno/test/fixtures/basics/package.json
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"astro": "workspace:*",
- "@astrojs/deno": "workspace:*"
+ "@astrojs/deno": "workspace:*",
+ "@astrojs/react": "workspace:*"
}
}
diff --git a/packages/integrations/deno/test/fixtures/basics/src/components/React.jsx b/packages/integrations/deno/test/fixtures/basics/src/components/React.jsx
new file mode 100644
index 000000000..42c74a7aa
--- /dev/null
+++ b/packages/integrations/deno/test/fixtures/basics/src/components/React.jsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+export default function() {
+ return (
+ <div id="react">testing</div>
+ );
+}
diff --git a/packages/integrations/deno/test/fixtures/basics/src/pages/index.astro b/packages/integrations/deno/test/fixtures/basics/src/pages/index.astro
index 9a37d684b..4eb15f2f0 100644
--- a/packages/integrations/deno/test/fixtures/basics/src/pages/index.astro
+++ b/packages/integrations/deno/test/fixtures/basics/src/pages/index.astro
@@ -1,5 +1,5 @@
---
-
+import ReactComponent from '../components/React.jsx';
---
<html>
<head>
@@ -8,5 +8,6 @@
</head>
<body>
<h1>Basic App on Deno</h1>
+ <ReactComponent />
</body>
</html>
diff --git a/packages/integrations/netlify/src/integration-edge-functions.ts b/packages/integrations/netlify/src/integration-edge-functions.ts
index 0165c7831..b76617f1e 100644
--- a/packages/integrations/netlify/src/integration-edge-functions.ts
+++ b/packages/integrations/netlify/src/integration-edge-functions.ts
@@ -86,6 +86,10 @@ export function netlifyEdgeFunctions({ dist }: NetlifyEdgeFunctionsOptions = {})
},
'astro:build:setup': ({ vite, target }) => {
if (target === 'server') {
+ vite.resolve = vite.resolve || {};
+ vite.resolve.alias = vite.resolve.alias || {};
+ const alias = vite.resolve.alias as Record<string, string>;
+ alias['react-dom/server'] = 'react-dom/server.browser'
vite.ssr = {
noExternal: true,
};
diff --git a/packages/integrations/netlify/test/edge-functions/deps.ts b/packages/integrations/netlify/test/edge-functions/deps.ts
index f3e46181a..1b23a94f7 100644
--- a/packages/integrations/netlify/test/edge-functions/deps.ts
+++ b/packages/integrations/netlify/test/edge-functions/deps.ts
@@ -1,3 +1,4 @@
// @ts-nocheck
export { fromFileUrl } from 'https://deno.land/std@0.110.0/path/mod.ts';
export { assertEquals, assert } from 'https://deno.land/std@0.132.0/testing/asserts.ts';
+export * from 'https://deno.land/x/deno_dom/deno-dom-wasm.ts';
diff --git a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts b/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts
index 7fc8877bd..0b29fc1a9 100644
--- a/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts
+++ b/packages/integrations/netlify/test/edge-functions/edge-basic.test.ts
@@ -1,7 +1,7 @@
// @ts-ignore
import { runBuild } from './test-utils.ts';
// @ts-ignore
-import { assertEquals, assert } from './deps.ts';
+import { assertEquals, assert, DOMParser } from './deps.ts';
// @ts-ignore
Deno.test({
@@ -9,12 +9,17 @@ Deno.test({
async fn() {
let close = await runBuild('./fixtures/edge-basic/');
const { default: handler } = await import(
- './fixtures/edge-basic/dist/edge-functions/entry.mjs'
+ './fixtures/edge-basic/dist/edge-functions/entry.js'
);
const response = await handler(new Request('http://example.com/'));
assertEquals(response.status, 200);
const html = await response.text();
assert(html, 'got some html');
+
+ const doc = new DOMParser().parseFromString(html, `text/html`)!;
+ const div = doc.querySelector('#react');
+ assert(div, 'div exists');
+
await close();
},
});
diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs
index c55135e43..d7c899264 100644
--- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/astro.config.mjs
@@ -1,10 +1,12 @@
import { defineConfig } from 'astro/config';
import { netlifyEdgeFunctions } from '@astrojs/netlify';
+import react from "@astrojs/react";
export default defineConfig({
adapter: netlifyEdgeFunctions({
dist: new URL('./dist/', import.meta.url),
}),
+ integrations: [react()],
experimental: {
ssr: true
}
diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json
index bbda2476b..16ff30088 100644
--- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/package.json
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"astro": "workspace:*",
+ "@astrojs/react": "workspace:*",
"@astrojs/netlify": "workspace:*"
}
}
diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/components/React.jsx b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/components/React.jsx
new file mode 100644
index 000000000..c6cf39aa5
--- /dev/null
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/components/React.jsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+export default function() {
+ return (
+ <div id="react">testing</div>
+ )
+}
diff --git a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro
index a87de65db..80d2eed75 100644
--- a/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro
+++ b/packages/integrations/netlify/test/edge-functions/fixtures/edge-basic/src/pages/index.astro
@@ -1,3 +1,6 @@
+---
+import ReactComponent from '../components/React.jsx';
+---
<html>
<head><title>Testing</title></head>
<body>
@@ -6,5 +9,6 @@
<ul>
<li><a href="/two/">Two</a></li>
</ul>
+ <ReactComponent />
</body>
</html>
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,