Skip to content

Commit e7d7d4c

Browse files
authored
Move Flight Fixture to use Middleware instead of WebDevServer (#26246)
This lets us put it in the same server that would be serving this content in a more real world scenario. I also de-CRA:ified this a bit by simplifying pieces we don't need. I have more refactors coming for the SSR pieces but since many are eyeing these fixtures right now I figured I'd push earlier. The design here is that there are two servers: - Global - representing a "CDN" which will also include the SSR server. - Regional - representing something close to the data with low waterfall costs which include the RSC server. This is just an example. These are using the "unbundled" strategy for the RSC server just to show a simple case, but an implementation can use a bundled SSR server. A smart SSR bundler could also put RSC and SSR in the same server and even the same JS environment. It just need to ensure that the module graphs are kept separately - so that the `react-server` condition is respected. This include `react` itself. React will start breaking if this isn't respected because the runtime will get the wrong copy of `react`. Technically, you don't need the *entire* module graph to be separated. It just needs to be any part of the graph that depends on a fork. Like if "Client A" -> "foo" and "Server B" -> "foo", then it's ok for the module "foo" to be shared. However if "foo" -> "bar", and "bar" is forked by the "react-server" condition, then "foo" also needs to be duplicated in the module graph so that it can get two copies of "bar".
1 parent 5641660 commit e7d7d4c

File tree

15 files changed

+293
-1867
lines changed

15 files changed

+293
-1867
lines changed

fixtures/flight/config/getHttpsConfig.js

Lines changed: 0 additions & 66 deletions
This file was deleted.

fixtures/flight/config/modules.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const fs = require('fs');
44
const path = require('path');
55
const paths = require('./paths');
6-
const chalk = require('react-dev-utils/chalk');
6+
const chalk = require('chalk');
77
const resolve = require('resolve');
88

99
/**

fixtures/flight/config/paths.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ module.exports = {
6464
appJsConfig: resolveApp('jsconfig.json'),
6565
yarnLockFile: resolveApp('yarn.lock'),
6666
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
67-
proxySetup: resolveApp('src/setupProxy.js'),
6867
appNodeModules: resolveApp('node_modules'),
6968
appWebpackCache: resolveApp('node_modules/.cache'),
7069
appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'),

fixtures/flight/config/webpack.config.js

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const ReactFlightWebpackPlugin = require('react-server-dom-webpack/plugin');
55
// Fork End
66

77
const fs = require('fs');
8+
const {createHash} = require('crypto');
89
const path = require('path');
910
const webpack = require('webpack');
1011
const resolve = require('resolve');
@@ -14,9 +15,7 @@ const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
1415
const TerserPlugin = require('terser-webpack-plugin');
1516
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
1617
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
17-
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
1818
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
19-
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
2019
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
2120
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
2221
const ESLintPlugin = require('eslint-webpack-plugin');
@@ -30,7 +29,12 @@ const ForkTsCheckerWebpackPlugin =
3029
: require('react-dev-utils/ForkTsCheckerWebpackPlugin');
3130
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
3231

33-
const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash');
32+
function createEnvironmentHash(env) {
33+
const hash = createHash('md5');
34+
hash.update(JSON.stringify(env));
35+
36+
return hash.digest('hex');
37+
}
3438

3539
// Source maps are resource heavy and can cause out of memory issue for large source files.
3640
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
@@ -632,30 +636,6 @@ module.exports = function (webpackEnv) {
632636
filename: 'static/css/[name].[contenthash:8].css',
633637
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
634638
}),
635-
// Generate an asset manifest file with the following content:
636-
// - "files" key: Mapping of all asset filenames to their corresponding
637-
// output file so that tools can pick it up without having to parse
638-
// `index.html`
639-
// - "entrypoints" key: Array of files which are included in `index.html`,
640-
// can be used to reconstruct the HTML if necessary
641-
new WebpackManifestPlugin({
642-
fileName: 'asset-manifest.json',
643-
publicPath: paths.publicUrlOrPath,
644-
generate: (seed, files, entrypoints) => {
645-
const manifestFiles = files.reduce((manifest, file) => {
646-
manifest[file.name] = file.path;
647-
return manifest;
648-
}, seed);
649-
const entrypointFiles = entrypoints.main.filter(
650-
fileName => !fileName.endsWith('.map')
651-
);
652-
653-
return {
654-
files: manifestFiles,
655-
entrypoints: entrypointFiles,
656-
};
657-
},
658-
}),
659639
// Moment.js is an extremely popular library that bundles large locale files
660640
// by default due to how webpack interprets its code. This is a practical
661641
// solution that requires the user to opt into importing specific locales.
@@ -665,19 +645,6 @@ module.exports = function (webpackEnv) {
665645
resourceRegExp: /^\.\/locale$/,
666646
contextRegExp: /moment$/,
667647
}),
668-
// Generate a service worker script that will precache, and keep up to date,
669-
// the HTML & assets that are part of the webpack build.
670-
isEnvProduction &&
671-
fs.existsSync(swSrc) &&
672-
new WorkboxWebpackPlugin.InjectManifest({
673-
swSrc,
674-
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
675-
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
676-
// Bump up the default maximum size (2mb) that's precached,
677-
// to make lazy-loading failure scenarios less likely.
678-
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
679-
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
680-
}),
681648
// TypeScript type checking
682649
useTypeScript &&
683650
new ForkTsCheckerWebpackPlugin({

fixtures/flight/config/webpack/persistentCache/createEnvironmentHash.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

fixtures/flight/config/webpackDevServer.config.js

Lines changed: 0 additions & 133 deletions
This file was deleted.

fixtures/flight/package.json

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
"babel-loader": "^8.2.3",
1616
"babel-plugin-named-asset-import": "^0.3.8",
1717
"babel-preset-react-app": "^10.0.1",
18-
"bfj": "^7.0.2",
1918
"body-parser": "^1.20.1",
2019
"browserslist": "^4.18.1",
2120
"camelcase": "^6.2.1",
2221
"case-sensitive-paths-webpack-plugin": "^2.4.0",
22+
"compression": "^1.7.4",
2323
"concurrently": "^7.3.0",
2424
"css-loader": "^6.5.1",
2525
"css-minimizer-webpack-plugin": "^3.2.0",
@@ -56,21 +56,18 @@
5656
"style-loader": "^3.3.1",
5757
"tailwindcss": "^3.0.2",
5858
"terser-webpack-plugin": "^5.2.5",
59-
"web-vitals": "^2.1.0",
6059
"webpack": "^5.64.4",
61-
"webpack-dev-server": "^4.6.0",
62-
"webpack-manifest-plugin": "^4.0.2",
63-
"workbox-webpack-plugin": "^6.4.1"
60+
"webpack-dev-middleware": "^5.3.1"
6461
},
6562
"scripts": {
6663
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
6764
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
68-
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
69-
"dev:client": "NODE_ENV=development BUILD_PATH=dist node scripts/start.js",
70-
"dev:server": "NODE_ENV=development BUILD_PATH=dist nodemon -- --experimental-loader ./loader/index.js --conditions=react-server server",
71-
"start": "node scripts/build.js && concurrently \"npm run start:server\" \"npm run start:client\"",
72-
"start:client": "cd ./build && python3 -m http.server 3000",
73-
"start:server": "NODE_ENV=production node --experimental-loader ./loader/index.js --conditions=react-server server",
65+
"dev": "concurrently \"npm run dev:region\" \"npm run dev:global\"",
66+
"dev:global": "NODE_ENV=development BUILD_PATH=dist node server/global",
67+
"dev:region": "NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --experimental-loader ./loader/index.js --conditions=react-server server/region",
68+
"start": "node scripts/build.js && concurrently \"npm run start:region\" \"npm run start:global\"",
69+
"start:global": "NODE_ENV=production node server/global",
70+
"start:region": "NODE_ENV=production node --experimental-loader ./loader/index.js --conditions=react-server server/region",
7471
"build": "node scripts/build.js",
7572
"test": "node scripts/test.js --env=jsdom"
7673
},

fixtures/flight/scripts/build.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ process.on('unhandledRejection', err => {
1515
require('../config/env');
1616

1717
const path = require('path');
18-
const chalk = require('react-dev-utils/chalk');
18+
const chalk = require('chalk');
1919
const fs = require('fs-extra');
20-
const bfj = require('bfj');
2120
const webpack = require('webpack');
2221
const configFactory = require('../config/webpack.config');
2322
const paths = require('../config/paths');
@@ -197,20 +196,13 @@ function build(previousFileSizes) {
197196
warnings: messages.warnings,
198197
};
199198

200-
if (writeStatsJson) {
201-
return bfj
202-
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
203-
.then(() => resolve(resolveArgs))
204-
.catch(error => reject(new Error(error)));
205-
}
206-
207199
return resolve(resolveArgs);
208200
});
209201
});
210202
}
211203

212204
function copyPublicFolder() {
213-
fs.copySync(paths.appPublic, paths.appBuild, {
205+
fs.copySync('public', 'build', {
214206
dereference: true,
215207
filter: file => file !== paths.appHtml,
216208
});

0 commit comments

Comments
 (0)