diff --git a/fixtures/flight/.gitignore b/fixtures/flight/.gitignore
index 4d29575de8048..800f3a80c3481 100644
--- a/fixtures/flight/.gitignore
+++ b/fixtures/flight/.gitignore
@@ -10,6 +10,7 @@
# production
/build
+/dist
# misc
.DS_Store
diff --git a/fixtures/flight/server/handler.server.js b/fixtures/flight/server/handler.server.js
index 86476bb2c2d71..cb9bcbf306e1d 100644
--- a/fixtures/flight/server/handler.server.js
+++ b/fixtures/flight/server/handler.server.js
@@ -1,51 +1,20 @@
'use strict';
import {pipeToNodeWritable} from 'react-transport-dom-webpack/server';
+import {readFileSync} from 'fs';
+import {resolve} from 'path';
import * as React from 'react';
-import url from 'url';
-
-function resolve(path) {
- return url.pathToFileURL(require.resolve(path)).href;
-}
-
module.exports = async function(req, res) {
- res.setHeader('Access-Control-Allow-Origin', '*');
const m = await import('../src/App.server.js');
// const m = require('../src/App.server.js');
const App = m.default.default || m.default;
- pipeToNodeWritable(, res, {
- // TODO: Read from a map on the disk.
- [resolve('../src/Counter.client.js')]: {
- Counter: {
- id: './src/Counter.client.js',
- chunks: ['2'],
- name: 'Counter',
- },
- },
- [resolve('../src/Counter2.client.js')]: {
- Counter: {
- id: './src/Counter2.client.js',
- chunks: ['1'],
- name: 'Counter',
- },
- },
- [resolve('../src/ShowMore.client.js')]: {
- default: {
- id: './src/ShowMore.client.js',
- chunks: ['3'],
- name: 'default',
- },
- '': {
- id: './src/ShowMore.client.js',
- chunks: ['3'],
- name: '',
- },
- '*': {
- id: './src/ShowMore.client.js',
- chunks: ['3'],
- name: '*',
- },
- },
- });
+ res.setHeader('Access-Control-Allow-Origin', '*');
+ const moduleMap = JSON.parse(
+ readFileSync(
+ resolve(__dirname, '../dist/react-transport-manifest.json'),
+ 'utf8'
+ )
+ );
+ pipeToNodeWritable(, res, moduleMap);
};
diff --git a/fixtures/flight/src/index.js b/fixtures/flight/src/index.js
index ce9595dbe5482..9fc13a76aa892 100644
--- a/fixtures/flight/src/index.js
+++ b/fixtures/flight/src/index.js
@@ -19,5 +19,5 @@ ReactDOM.render(
);
// Create entry points for Client Components.
-// TODO: Webpack plugin should do this and write a map to disk.
+// TODO: Webpack plugin should do this.
require.context('./', true, /\.client\.js$/, 'lazy');
diff --git a/packages/react-transport-dom-webpack/src/ReactFlightWebpackPlugin.js b/packages/react-transport-dom-webpack/src/ReactFlightWebpackPlugin.js
index 3b55509170174..c94426ff61e7a 100644
--- a/packages/react-transport-dom-webpack/src/ReactFlightWebpackPlugin.js
+++ b/packages/react-transport-dom-webpack/src/ReactFlightWebpackPlugin.js
@@ -7,7 +7,39 @@
* @flow
*/
+import {mkdirSync, writeFileSync} from 'fs';
+import {dirname, resolve} from 'path';
+import {pathToFileURL} from 'url';
+
export default class ReactFlightWebpackPlugin {
constructor(options: {isServer: boolean}) {}
- apply(compiler: any) {}
+
+ apply(compiler: any) {
+ compiler.hooks.emit.tap('React Transport Plugin', compilation => {
+ const json = {};
+ compilation.chunks.forEach(chunk => {
+ chunk.getModules().forEach(mod => {
+ if (!/\.client\.js$/.test(mod.resource)) {
+ return;
+ }
+ let moduleExports = {};
+ ['', '*'].concat(mod.buildMeta.providedExports).forEach(name => {
+ moduleExports[name] = {
+ id: mod.id,
+ chunks: chunk.ids,
+ name: name,
+ };
+ });
+ json[pathToFileURL(mod.resource).href] = moduleExports;
+ });
+ });
+ const output = JSON.stringify(json, null, 2);
+ const filename = resolve(
+ compiler.options.output.path,
+ 'react-transport-manifest.json',
+ );
+ mkdirSync(dirname(filename), {recursive: true});
+ writeFileSync(filename, output);
+ });
+ }
}
diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js
index db8a8b8002cfb..37fdafa3408a1 100644
--- a/scripts/rollup/bundles.js
+++ b/scripts/rollup/bundles.js
@@ -283,7 +283,7 @@ const bundles = [
moduleType: RENDERER_UTILS,
entry: 'react-transport-dom-webpack/plugin',
global: 'ReactFlightWebpackPlugin',
- externals: [],
+ externals: ['fs', 'path', 'url'],
},
/******* React Transport DOM Webpack Node.js Loader *******/
diff --git a/scripts/rollup/modules.js b/scripts/rollup/modules.js
index e89b12f7dbc0e..226ea5be5b77c 100644
--- a/scripts/rollup/modules.js
+++ b/scripts/rollup/modules.js
@@ -9,6 +9,8 @@ const {UMD_DEV, UMD_PROD, UMD_PROFILING} = require('./bundles').bundleTypes;
const HAS_NO_SIDE_EFFECTS_ON_IMPORT = false;
// const HAS_SIDE_EFFECTS_ON_IMPORT = true;
const importSideEffects = Object.freeze({
+ fs: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
+ path: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'prop-types/checkPropTypes': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
scheduler: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
@@ -17,6 +19,7 @@ const importSideEffects = Object.freeze({
'react/jsx-dev-runtime': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'react-fetch/node': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
'react-dom': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
+ url: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
});
// Bundles exporting globals that other modules rely on.