diff --git a/packages/react-server-dom-webpack/node-register.js b/packages/react-server-dom-webpack/node-register.js
index 03754438bf338..e0490f3a17686 100644
--- a/packages/react-server-dom-webpack/node-register.js
+++ b/packages/react-server-dom-webpack/node-register.js
@@ -7,4 +7,4 @@
* @flow
*/
-export * from './src/ReactFlightWebpackNodeRegister';
+module.exports = require('./src/ReactFlightWebpackNodeRegister');
diff --git a/packages/react-server-dom-webpack/package.json b/packages/react-server-dom-webpack/package.json
index 0a8c3389de711..45ba3669f90af 100644
--- a/packages/react-server-dom-webpack/package.json
+++ b/packages/react-server-dom-webpack/package.json
@@ -35,6 +35,7 @@
"./writer.browser.server": "./writer.browser.server.js",
"./node-loader": "./esm/react-server-dom-webpack-node-loader.js",
"./node-register": "./node-register.js",
+ "./src/*": "./src/*",
"./package.json": "./package.json"
},
"main": "index.js",
diff --git a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js
index a5f889d3eb15d..1b528fba43021 100644
--- a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js
+++ b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js
@@ -57,7 +57,7 @@ module.exports = function register() {
},
};
- (require: any).extensions['.client.js'] = function(module, path) {
+ Module._extensions['.client.js'] = function(module, path) {
const moduleId = url.pathToFileURL(path).href;
const moduleReference: {[string]: any} = {
$$typeof: MODULE_REFERENCE,
diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
index b68a9b28284bc..4616246bb50bc 100644
--- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
+++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
@@ -17,14 +17,9 @@ global.TextDecoder = require('util').TextDecoder;
// TODO: we can replace this with FlightServer.act().
global.setImmediate = cb => cb();
-let webpackModuleIdx = 0;
-let webpackModules = {};
-let webpackMap = {};
-global.__webpack_require__ = function(id) {
- return webpackModules[id];
-};
-
let act;
+let clientExports;
+let webpackMap;
let Stream;
let React;
let ReactDOMClient;
@@ -35,15 +30,17 @@ let Suspense;
describe('ReactFlightDOM', () => {
beforeEach(() => {
jest.resetModules();
- webpackModules = {};
- webpackMap = {};
act = require('jest-react').act;
+ const WebpackMock = require('./utils/WebpackMock');
+ clientExports = WebpackMock.clientExports;
+ webpackMap = WebpackMock.webpackMap;
+
Stream = require('stream');
React = require('react');
+ Suspense = React.Suspense;
ReactDOMClient = require('react-dom/client');
ReactServerDOMWriter = require('react-server-dom-webpack/writer.node.server');
ReactServerDOMReader = require('react-server-dom-webpack');
- Suspense = React.Suspense;
});
function getTestStream() {
@@ -64,22 +61,6 @@ describe('ReactFlightDOM', () => {
};
}
- function moduleReference(moduleExport) {
- const idx = webpackModuleIdx++;
- webpackModules[idx] = {
- d: moduleExport,
- };
- webpackMap['path/' + idx] = {
- default: {
- id: '' + idx,
- chunks: [],
- name: 'd',
- },
- };
- const MODULE_TAG = Symbol.for('react.module.reference');
- return {$$typeof: MODULE_TAG, filepath: 'path/' + idx, name: 'default'};
- }
-
async function waitForSuspense(fn) {
while (true) {
try {
@@ -345,7 +326,7 @@ describe('ReactFlightDOM', () => {
return
{games}
;
}
- const MyErrorBoundaryClient = moduleReference(MyErrorBoundary);
+ const MyErrorBoundaryClient = clientExports(MyErrorBoundary);
function ProfileContent() {
return (
@@ -470,7 +451,7 @@ describe('ReactFlightDOM', () => {
return ;
}
- const InputClient = moduleReference(Input);
+ const InputClient = clientExports(Input);
// Server
diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
index e2cc4989c8eef..43573af1df141 100644
--- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
+++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
@@ -14,13 +14,9 @@ global.ReadableStream = require('web-streams-polyfill/ponyfill/es6').ReadableStr
global.TextEncoder = require('util').TextEncoder;
global.TextDecoder = require('util').TextDecoder;
-let webpackModuleIdx = 0;
-let webpackModules = {};
-let webpackMap = {};
-global.__webpack_require__ = function(id) {
- return webpackModules[id];
-};
-
+let clientExports;
+let webpackMap;
+let webpackModules;
let act;
let React;
let ReactDOMClient;
@@ -32,9 +28,11 @@ let Suspense;
describe('ReactFlightDOMBrowser', () => {
beforeEach(() => {
jest.resetModules();
- webpackModules = {};
- webpackMap = {};
act = require('jest-react').act;
+ const WebpackMock = require('./utils/WebpackMock');
+ clientExports = WebpackMock.clientExports;
+ webpackMap = WebpackMock.webpackMap;
+ webpackModules = WebpackMock.webpackModules;
React = require('react');
ReactDOMClient = require('react-dom/client');
ReactDOMServer = require('react-dom/server.browser');
@@ -43,22 +41,6 @@ describe('ReactFlightDOMBrowser', () => {
Suspense = React.Suspense;
});
- function moduleReference(moduleExport) {
- const idx = webpackModuleIdx++;
- webpackModules[idx] = {
- d: moduleExport,
- };
- webpackMap['path/' + idx] = {
- default: {
- id: '' + idx,
- chunks: [],
- name: 'd',
- },
- };
- const MODULE_TAG = Symbol.for('react.module.reference');
- return {$$typeof: MODULE_TAG, filepath: 'path/' + idx, name: 'default'};
- }
-
async function waitForSuspense(fn) {
while (true) {
try {
@@ -249,7 +231,7 @@ describe('ReactFlightDOMBrowser', () => {
return {games}
;
}
- const MyErrorBoundaryClient = moduleReference(MyErrorBoundary);
+ const MyErrorBoundaryClient = clientExports(MyErrorBoundary);
function ProfileContent() {
return (
@@ -478,19 +460,19 @@ describe('ReactFlightDOMBrowser', () => {
}
// The Client build may not have the same IDs as the Server bundles for the same
// component.
- const ClientComponentOnTheClient = moduleReference(ClientComponent);
- const ClientComponentOnTheServer = moduleReference(ClientComponent);
+ const ClientComponentOnTheClient = clientExports(ClientComponent);
+ const ClientComponentOnTheServer = clientExports(ClientComponent);
// In the SSR bundle this module won't exist. We simulate this by deleting it.
- const clientId = webpackMap[ClientComponentOnTheClient.filepath].default.id;
+ const clientId = webpackMap[ClientComponentOnTheClient.filepath]['*'].id;
delete webpackModules[clientId];
// Instead, we have to provide a translation from the client meta data to the SSR
// meta data.
- const ssrMetaData = webpackMap[ClientComponentOnTheServer.filepath].default;
+ const ssrMetaData = webpackMap[ClientComponentOnTheServer.filepath]['*'];
const translationMap = {
[clientId]: {
- d: ssrMetaData,
+ '*': ssrMetaData,
},
};
diff --git a/packages/react-server-dom-webpack/src/__tests__/utils/WebpackMock.js b/packages/react-server-dom-webpack/src/__tests__/utils/WebpackMock.js
new file mode 100644
index 0000000000000..2cd21b0f2df14
--- /dev/null
+++ b/packages/react-server-dom-webpack/src/__tests__/utils/WebpackMock.js
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+'use strict';
+
+const url = require('url');
+const Module = require('module');
+
+let webpackModuleIdx = 0;
+const webpackModules = {};
+const webpackMap = {};
+global.__webpack_require__ = function(id) {
+ return webpackModules[id];
+};
+
+const previousLoader = Module._extensions['.client.js'];
+
+const register = require('react-server-dom-webpack/node-register');
+// Register node loader
+register();
+
+const nodeLoader = Module._extensions['.client.js'];
+
+if (previousLoader === nodeLoader) {
+ throw new Error(
+ 'Expected the Node loader to register the .client.js extension',
+ );
+}
+
+Module._extensions['.client.js'] = previousLoader;
+
+exports.webpackMap = webpackMap;
+exports.webpackModules = webpackModules;
+
+exports.clientExports = function clientExports(moduleExports) {
+ const idx = '' + webpackModuleIdx++;
+ webpackModules[idx] = moduleExports;
+ const path = url.pathToFileURL(idx).href;
+ webpackMap[path] = {
+ '': {
+ id: idx,
+ chunks: [],
+ name: '',
+ },
+ '*': {
+ id: idx,
+ chunks: [],
+ name: '*',
+ },
+ };
+ for (const name in moduleExports) {
+ webpackMap[path] = {
+ [name]: {
+ id: idx,
+ chunks: [],
+ name: name,
+ },
+ };
+ }
+ const mod = {exports: {}};
+ nodeLoader(mod, idx);
+ return mod.exports;
+};
diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js
index 68407ef01183d..f93225d9d15da 100644
--- a/scripts/rollup/bundles.js
+++ b/scripts/rollup/bundles.js
@@ -408,7 +408,8 @@ const bundles = [
{
bundleTypes: [NODE_ES2015],
moduleType: RENDERER_UTILS,
- entry: 'react-server-dom-webpack/node-register',
+ entry: 'react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js',
+ name: 'react-server-dom-webpack-node-register',
global: 'ReactFlightWebpackNodeRegister',
minifyWithProdErrorCodes: false,
wrapWithModuleBoundaries: false,