Skip to content
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

[Flight Fixture] Proxy requests through the global server instead of directly #26257

Merged
merged 4 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion fixtures/flight/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,13 @@ module.exports = function (webpackEnv) {
: isEnvDevelopment && 'cheap-module-source-map',
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
entry: paths.appIndexJs,
entry: isEnvProduction
? [paths.appIndexJs]
: [
paths.appIndexJs,
// HMR client
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
],
output: {
// The build folder.
path: paths.appBuild,
Expand Down Expand Up @@ -571,6 +577,7 @@ module.exports = function (webpackEnv) {
].filter(Boolean),
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is needed or not and what it does.

// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
Expand Down
4 changes: 3 additions & 1 deletion fixtures/flight/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5",
"undici": "^5.20.0",
"webpack": "^5.64.4",
"webpack-dev-middleware": "^5.3.1"
"webpack-dev-middleware": "^5.3.1",
"webpack-hot-middleware": "^2.25.3"
},
"scripts": {
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
Expand Down
79 changes: 72 additions & 7 deletions fixtures/flight/server/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,69 @@ const chalk = require('chalk');
const express = require('express');
const app = express();

const http = require('http');

app.use(compress());

function request(options, body) {
return new Promise((resolve, reject) => {
const req = http.request(options, res => {
resolve(res);
});
req.on('error', e => {
reject(e);
});
body.pipe(req);
});
}

app.all('/', async function (req, res, next) {
if (req.accepts('text/html')) {
// Pass-through to the html file
next();
return;
}

// Proxy the request to the regional server.
const proxiedHeaders = {
'X-Forwarded-Host': req.hostname,
'X-Forwarded-For': req.ips,
'X-Forwarded-Port': 3000,
'X-Forwarded-Proto': req.protocol,
};
// Proxy other headers as desired.
if (req.get('rsc-action')) {
proxiedHeaders['Content-type'] = req.get('Content-type');
proxiedHeaders['rsc-action'] = req.get('rsc-action');
}

const promiseForData = request(
{
host: '127.0.0.1',
port: 3001,
method: req.method,
path: '/',
headers: proxiedHeaders,
},
req
);

try {
const rscResponse = await promiseForData;
res.set('Content-type', 'text/x-component');
rscResponse.pipe(res);
} catch (e) {
console.error(`Failed to proxy request: ${e.stack}`);
res.statusCode = 500;
res.end();
}
});

if (process.env.NODE_ENV === 'development') {
// In development we host the Webpack server for live bundling.
const webpack = require('webpack');
const webpackMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const getClientEnvironment = require('../config/env');
Expand All @@ -59,13 +116,21 @@ if (process.env.NODE_ENV === 'development') {

// Create a webpack compiler that is configured with custom messages.
const compiler = webpack(config);
const devMiddleware = {
writeToDisk: filePath => {
return /(react-client-manifest|react-ssr-manifest)\.json$/.test(filePath);
},
publicPath: paths.publicUrlOrPath.slice(0, -1),
};
app.use(webpackMiddleware(compiler, devMiddleware));
app.use(
webpackMiddleware(compiler, {
writeToDisk: filePath => {
return /(react-client-manifest|react-ssr-manifest)\.json$/.test(
filePath
);
},
publicPath: paths.publicUrlOrPath.slice(0, -1),
})
);
app.use(
webpackHotMiddleware(compiler, {
/* Options */
})
);
app.use(express.static('public'));
} else {
// In production we host the static build output.
Expand Down
15 changes: 5 additions & 10 deletions fixtures/flight/server/region.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ babelRegister({
plugins: ['@babel/transform-modules-commonjs'],
});

if (typeof fetch === 'undefined') {
// Patch fetch for earlier Node versions.
global.fetch = require('undici').fetch;
}

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
Expand All @@ -51,19 +56,11 @@ app.get('/', async function (req, res) {
'utf8'
);
const App = m.default.default || m.default;
res.setHeader('Access-Control-Allow-Origin', '*');
const moduleMap = JSON.parse(data);
const {pipe} = renderToPipeableStream(React.createElement(App), moduleMap);
pipe(res);
});

app.options('/', function (req, res) {
res.setHeader('Allow', 'Allow: GET,HEAD,POST');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'rsc-action');
res.end();
});

app.post('/', bodyParser.text(), async function (req, res) {
const {renderToPipeableStream} = await import(
'react-server-dom-webpack/server'
Expand All @@ -81,13 +78,11 @@ app.post('/', bodyParser.text(), async function (req, res) {
const args = JSON.parse(req.body);
const result = action.apply(null, args);

res.setHeader('Access-Control-Allow-Origin', '*');
const {pipe} = renderToPipeableStream(result, {});
pipe(res);
});

app.get('/todos', function (req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.json([
{
id: 1,
Expand Down
10 changes: 7 additions & 3 deletions fixtures/flight/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import ReactDOM from 'react-dom/client';
import ReactServerDOMReader from 'react-server-dom-webpack/client';

let data = ReactServerDOMReader.createFromFetch(
fetch('http://localhost:3001'),
fetch('/', {
headers: {
Accept: 'text/x-component',
},
}),
{
callServer(id, args) {
const response = fetch('http://localhost:3001', {
const response = fetch('/', {
method: 'POST',
cors: 'cors',
headers: {
Accept: 'text/x-component',
'rsc-action': JSON.stringify({filepath: id.id, name: id.name}),
},
body: JSON.stringify(args),
Expand Down
30 changes: 29 additions & 1 deletion fixtures/flight/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2651,7 +2651,7 @@ ansi-escapes@^4.3.1:
dependencies:
type-fest "^0.11.0"

ansi-html-community@^0.0.8:
ansi-html-community@0.0.8, ansi-html-community@^0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
Expand Down Expand Up @@ -3061,6 +3061,13 @@ buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"

busboy@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"

bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
Expand Down Expand Up @@ -7903,6 +7910,11 @@ statuses@2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==

streamsearch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==

string-length@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1"
Expand Down Expand Up @@ -8388,6 +8400,13 @@ undefsafe@^2.0.5:
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==

undici@^5.20.0:
version "5.20.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.20.0.tgz#6327462f5ce1d3646bcdac99da7317f455bcc263"
integrity sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==
dependencies:
busboy "^1.6.0"

unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
Expand Down Expand Up @@ -8548,6 +8567,15 @@ webpack-dev-middleware@^5.3.1:
range-parser "^1.2.1"
schema-utils "^4.0.0"

webpack-hot-middleware@^2.25.3:
version "2.25.3"
resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.25.3.tgz#be343ce2848022cfd854dd82820cd730998c6794"
integrity sha512-IK/0WAHs7MTu1tzLTjio73LjS3Ov+VvBKQmE8WPlJutgG5zT6Urgq/BbAdRrHTRpyzK0dvAvFh1Qg98akxgZpA==
dependencies:
ansi-html-community "0.0.8"
html-entities "^2.1.0"
strip-ansi "^6.0.0"

webpack-sources@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,17 @@ async function parseExportNamesInto(
if (typeof source !== 'string') {
throw new Error('Expected the transformed source to be a string.');
}
const {body: childBody} = acorn.parse(source, {
ecmaVersion: '2019',
sourceType: 'module',
});
let childBody;
try {
childBody = acorn.parse(source, {
ecmaVersion: '2024',
sourceType: 'module',
}).body;
} catch (x) {
// eslint-disable-next-line react-internal/no-production-logging
console.error('Error parsing %s %s', url, x.message);
continue;
}
await parseExportNamesInto(childBody, names, url, loader);
continue;
}
Expand Down Expand Up @@ -381,10 +388,17 @@ async function transformModuleIfNeeded(
return source;
}

const {body} = acorn.parse(source, {
ecmaVersion: '2019',
sourceType: 'module',
});
let body;
try {
body = acorn.parse(source, {
ecmaVersion: '2024',
sourceType: 'module',
}).body;
} catch (x) {
// eslint-disable-next-line react-internal/no-production-logging
console.error('Error parsing %s %s', url, x.message);
return source;
}

let useClient = false;
let useServer = false;
Expand Down Expand Up @@ -450,8 +464,8 @@ export async function load(
context: LoadContext,
defaultLoad: LoadFunction,
): Promise<{format: string, shortCircuit?: boolean, source: Source}> {
if (context.format === 'module') {
const result = await defaultLoad(url, context, defaultLoad);
const result = await defaultLoad(url, context, defaultLoad);
if (result.format === 'module') {
if (typeof result.source !== 'string') {
throw new Error('Expected source to have been loaded into a string.');
}
Expand All @@ -462,5 +476,5 @@ export async function load(
);
return {format: 'module', source: newSrc};
}
return defaultLoad(url, context, defaultLoad);
return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,17 @@ module.exports = function register() {
return originalCompile.apply(this, arguments);
}

const {body} = acorn.parse(content, {
ecmaVersion: '2019',
sourceType: 'source',
});
let body;
try {
body = acorn.parse(content, {
ecmaVersion: '2024',
sourceType: 'source',
}).body;
} catch (x) {
// eslint-disable-next-line react-internal/no-production-logging
console.error('Error parsing %s %s', url, x.message);
return originalCompile.apply(this, arguments);
}

let useClient = false;
let useServer = false;
Expand Down