mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
f181ba8aa6
This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
1059 lines
28 KiB
JavaScript
1059 lines
28 KiB
JavaScript
'use strict';
|
|
|
|
const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
|
|
|
|
const __EXPERIMENTAL__ =
|
|
typeof RELEASE_CHANNEL === 'string'
|
|
? RELEASE_CHANNEL === 'experimental'
|
|
: true;
|
|
|
|
const bundleTypes = {
|
|
NODE_ES2015: 'NODE_ES2015',
|
|
ESM_DEV: 'ESM_DEV',
|
|
ESM_PROD: 'ESM_PROD',
|
|
UMD_DEV: 'UMD_DEV',
|
|
UMD_PROD: 'UMD_PROD',
|
|
UMD_PROFILING: 'UMD_PROFILING',
|
|
NODE_DEV: 'NODE_DEV',
|
|
NODE_PROD: 'NODE_PROD',
|
|
NODE_PROFILING: 'NODE_PROFILING',
|
|
BUN_DEV: 'BUN_DEV',
|
|
BUN_PROD: 'BUN_PROD',
|
|
FB_WWW_DEV: 'FB_WWW_DEV',
|
|
FB_WWW_PROD: 'FB_WWW_PROD',
|
|
FB_WWW_PROFILING: 'FB_WWW_PROFILING',
|
|
RN_OSS_DEV: 'RN_OSS_DEV',
|
|
RN_OSS_PROD: 'RN_OSS_PROD',
|
|
RN_OSS_PROFILING: 'RN_OSS_PROFILING',
|
|
RN_FB_DEV: 'RN_FB_DEV',
|
|
RN_FB_PROD: 'RN_FB_PROD',
|
|
RN_FB_PROFILING: 'RN_FB_PROFILING',
|
|
BROWSER_SCRIPT: 'BROWSER_SCRIPT',
|
|
};
|
|
|
|
const {
|
|
NODE_ES2015,
|
|
ESM_DEV,
|
|
ESM_PROD,
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
UMD_PROFILING,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
NODE_PROFILING,
|
|
BUN_DEV,
|
|
BUN_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
RN_OSS_DEV,
|
|
RN_OSS_PROD,
|
|
RN_OSS_PROFILING,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
BROWSER_SCRIPT,
|
|
} = bundleTypes;
|
|
|
|
const moduleTypes = {
|
|
// React
|
|
ISOMORPHIC: 'ISOMORPHIC',
|
|
// Individual renderers. They bundle the reconciler. (e.g. ReactDOM)
|
|
RENDERER: 'RENDERER',
|
|
// Helper packages that access specific renderer's internals. (e.g. TestUtils)
|
|
RENDERER_UTILS: 'RENDERER_UTILS',
|
|
// Standalone reconciler for third-party renderers.
|
|
RECONCILER: 'RECONCILER',
|
|
};
|
|
|
|
const {ISOMORPHIC, RENDERER, RENDERER_UTILS, RECONCILER} = moduleTypes;
|
|
|
|
const bundles = [
|
|
/******* Isomorphic *******/
|
|
{
|
|
bundleTypes: [
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
UMD_PROFILING,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react',
|
|
global: 'React',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* Isomorphic Shared Subset *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react/src/ReactSharedSubset.js',
|
|
name: 'react.shared-subset',
|
|
global: 'React',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* React JSX Runtime *******/
|
|
{
|
|
bundleTypes: [
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
NODE_PROFILING,
|
|
// TODO: use on WWW.
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react/jsx-runtime',
|
|
global: 'JSXRuntime',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React JSX DEV Runtime *******/
|
|
{
|
|
bundleTypes: [
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
NODE_PROFILING,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react/jsx-dev-runtime',
|
|
global: 'JSXDEVRuntime',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React DOM *******/
|
|
{
|
|
bundleTypes: [
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
UMD_PROFILING,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
NODE_PROFILING,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom',
|
|
global: 'ReactDOM',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* Test Utils *******/
|
|
{
|
|
moduleType: RENDERER_UTILS,
|
|
bundleTypes: [FB_WWW_DEV, NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
|
entry: 'react-dom/test-utils',
|
|
global: 'ReactTestUtils',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React DOM - www - Testing *******/
|
|
{
|
|
moduleType: RENDERER,
|
|
bundleTypes: __EXPERIMENTAL__
|
|
? [FB_WWW_DEV, FB_WWW_PROD, NODE_DEV, NODE_PROD]
|
|
: [FB_WWW_DEV, FB_WWW_PROD],
|
|
entry: 'react-dom/unstable_testing',
|
|
global: 'ReactDOMTesting',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React DOM Server *******/
|
|
{
|
|
bundleTypes: [
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMLegacyServerBrowser.js',
|
|
name: 'react-dom-server-legacy.browser',
|
|
global: 'ReactDOMServer',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMLegacyServerNode.js',
|
|
name: 'react-dom-server-legacy.node',
|
|
externals: ['react', 'stream', 'react-dom'],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
|
|
/******* React DOM Fizz Server *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMFizzServerBrowser.js',
|
|
name: 'react-dom-server.browser',
|
|
global: 'ReactDOMServer',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMFizzServerNode.js',
|
|
name: 'react-dom-server.node',
|
|
global: 'ReactDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__ ? [FB_WWW_DEV, FB_WWW_PROD] : [],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-fb/src/ReactDOMServerFB.js',
|
|
global: 'ReactDOMServerStreaming',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React DOM Fizz Server Edge *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMFizzServerEdge.js',
|
|
name: 'react-dom-server.edge', // 'node_modules/react/*.js',
|
|
|
|
global: 'ReactDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React DOM Fizz Server Bun *******/
|
|
{
|
|
bundleTypes: [BUN_DEV, BUN_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/src/server/ReactDOMFizzServerBun.js',
|
|
name: 'react-dom-server.bun', // 'node_modules/react/*.js',
|
|
|
|
global: 'ReactDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React DOM Fizz Static *******/
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/static.browser',
|
|
global: 'ReactDOMStatic',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/static.node',
|
|
name: 'react-dom-static.node',
|
|
global: 'ReactDOMStatic',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'stream', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__ ? [NODE_DEV, NODE_PROD] : [],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/static.edge',
|
|
global: 'ReactDOMStatic',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React DOM Fizz Server External Runtime *******/
|
|
{
|
|
bundleTypes: [BROWSER_SCRIPT],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/unstable_server-external-runtime',
|
|
outputPath: 'unstable_server-external-runtime.js',
|
|
global: 'ReactDOMServerExternalRuntime',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* React DOM Server Render Stub *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-dom/server-rendering-stub',
|
|
name: 'react-dom-server-rendering-stub',
|
|
global: 'ReactDOMServerRenderingStub',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React Server DOM Webpack Server *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/server.browser',
|
|
global: 'ReactServerDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/server.node',
|
|
global: 'ReactServerDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/server.node.unbundled',
|
|
global: 'ReactServerDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/server.edge',
|
|
global: 'ReactServerDOMServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'react-dom'],
|
|
},
|
|
|
|
/******* React Server DOM Webpack Client *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/client.browser',
|
|
global: 'ReactServerDOMClient',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/client.node',
|
|
global: 'ReactServerDOMClient',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom', 'util'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/client.node.unbundled',
|
|
global: 'ReactServerDOMClient',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom', 'util'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-webpack/client.edge',
|
|
global: 'ReactServerDOMClient',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
|
|
/******* React Server DOM Webpack Plugin *******/
|
|
{
|
|
bundleTypes: [NODE_ES2015],
|
|
moduleType: RENDERER_UTILS,
|
|
entry: 'react-server-dom-webpack/plugin',
|
|
global: 'ReactServerWebpackPlugin',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['fs', 'path', 'url', 'neo-async'],
|
|
},
|
|
|
|
/******* React Server DOM Webpack Node.js Loader *******/
|
|
{
|
|
bundleTypes: [ESM_PROD],
|
|
moduleType: RENDERER_UTILS,
|
|
entry: 'react-server-dom-webpack/node-loader',
|
|
global: 'ReactServerWebpackNodeLoader',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['acorn'],
|
|
},
|
|
|
|
/******* React Server DOM Webpack Node.js CommonJS Loader *******/
|
|
{
|
|
bundleTypes: [NODE_ES2015],
|
|
moduleType: RENDERER_UTILS,
|
|
entry: 'react-server-dom-webpack/src/ReactFlightWebpackNodeRegister',
|
|
name: 'react-server-dom-webpack-node-register',
|
|
global: 'ReactFlightWebpackNodeRegister',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['url', 'module'],
|
|
},
|
|
|
|
/******* React Server DOM ESM Server *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-esm/server.node',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'util', 'async_hooks', 'react-dom'],
|
|
},
|
|
|
|
/******* React Server DOM ESM Client *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, ESM_DEV, ESM_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-esm/client.browser',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom'],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-server-dom-esm/client.node',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'react-dom', 'util'],
|
|
},
|
|
|
|
/******* React Server DOM ESM Node.js Loader *******/
|
|
{
|
|
bundleTypes: [ESM_PROD],
|
|
moduleType: RENDERER_UTILS,
|
|
entry: 'react-server-dom-esm/node-loader',
|
|
global: 'ReactServerESMNodeLoader',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['acorn'],
|
|
},
|
|
|
|
/******* React Suspense Test Utils *******/
|
|
{
|
|
bundleTypes: [NODE_ES2015],
|
|
moduleType: RENDERER_UTILS,
|
|
entry: 'react-suspense-test-utils',
|
|
global: 'ReactSuspenseTestUtils',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React ART *******/
|
|
{
|
|
bundleTypes: [
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
],
|
|
moduleType: RENDERER,
|
|
entry: 'react-art',
|
|
global: 'ReactART',
|
|
externals: ['react'],
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: true,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
// Include JSX
|
|
presets: opts.presets.concat([
|
|
require.resolve('@babel/preset-react'),
|
|
require.resolve('@babel/preset-flow'),
|
|
]),
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
|
|
/******* React Native *******/
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__
|
|
? []
|
|
: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],
|
|
moduleType: RENDERER,
|
|
entry: 'react-native-renderer',
|
|
global: 'ReactNativeRenderer',
|
|
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
{
|
|
bundleTypes: [RN_OSS_DEV, RN_OSS_PROD, RN_OSS_PROFILING],
|
|
moduleType: RENDERER,
|
|
entry: 'react-native-renderer',
|
|
global: 'ReactNativeRenderer',
|
|
externals: ['react-native'],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
|
|
/******* React Native Fabric *******/
|
|
{
|
|
bundleTypes: __EXPERIMENTAL__
|
|
? []
|
|
: [RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING],
|
|
moduleType: RENDERER,
|
|
entry: 'react-native-renderer/fabric',
|
|
global: 'ReactFabric',
|
|
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
{
|
|
bundleTypes: [RN_OSS_DEV, RN_OSS_PROD, RN_OSS_PROFILING],
|
|
moduleType: RENDERER,
|
|
entry: 'react-native-renderer/fabric',
|
|
global: 'ReactFabric',
|
|
externals: ['react-native'],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
|
|
/******* React Test Renderer *******/
|
|
{
|
|
bundleTypes: [
|
|
FB_WWW_DEV,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: RENDERER,
|
|
entry: 'react-test-renderer',
|
|
global: 'ReactTestRenderer',
|
|
externals: [
|
|
'react',
|
|
'scheduler',
|
|
'scheduler/unstable_mock',
|
|
'ReactNativeInternalFeatureFlags',
|
|
],
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
babel: opts =>
|
|
Object.assign({}, opts, {
|
|
plugins: opts.plugins.concat([
|
|
[require.resolve('@babel/plugin-transform-classes'), {loose: true}],
|
|
]),
|
|
}),
|
|
},
|
|
|
|
/******* React Noop Renderer (used for tests) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-noop-renderer',
|
|
global: 'ReactNoopRenderer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'scheduler', 'scheduler/unstable_mock', 'expect'],
|
|
},
|
|
|
|
/******* React Noop Persistent Renderer (used for tests) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-noop-renderer/persistent',
|
|
global: 'ReactNoopRendererPersistent',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'scheduler', 'expect'],
|
|
},
|
|
|
|
/******* React Noop Server Renderer (used for tests) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-noop-renderer/server',
|
|
global: 'ReactNoopRendererServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'scheduler', 'expect'],
|
|
},
|
|
|
|
/******* React Noop Flight Server (used for tests) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-noop-renderer/flight-server',
|
|
global: 'ReactNoopFlightServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [
|
|
'react',
|
|
'scheduler',
|
|
'expect',
|
|
'react-noop-renderer/flight-modules',
|
|
],
|
|
},
|
|
|
|
/******* React Noop Flight Client (used for tests) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RENDERER,
|
|
entry: 'react-noop-renderer/flight-client',
|
|
global: 'ReactNoopFlightClient',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [
|
|
'react',
|
|
'scheduler',
|
|
'expect',
|
|
'react-noop-renderer/flight-modules',
|
|
],
|
|
},
|
|
|
|
/******* React Reconciler *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, NODE_PROFILING],
|
|
moduleType: RECONCILER,
|
|
entry: 'react-reconciler',
|
|
global: 'ReactReconciler',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React Server *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RECONCILER,
|
|
entry: 'react-server',
|
|
global: 'ReactServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React Flight Server *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RECONCILER,
|
|
entry: 'react-server/flight',
|
|
global: 'ReactFlightServer',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* React Flight Client *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: RECONCILER,
|
|
entry: 'react-client/flight',
|
|
global: 'ReactFlightClient',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* Reconciler Reflection *******/
|
|
{
|
|
moduleType: RENDERER_UTILS,
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
entry: 'react-reconciler/reflection',
|
|
global: 'ReactFiberTreeReflection',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* Reconciler Constants *******/
|
|
{
|
|
moduleType: RENDERER_UTILS,
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
entry: 'react-reconciler/constants',
|
|
global: 'ReactReconcilerConstants',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* React Is *******/
|
|
{
|
|
bundleTypes: [
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react-is',
|
|
global: 'ReactIs',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React Debug Tools *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react-debug-tools',
|
|
global: 'ReactDebugTools',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* React Cache (experimental, old) *******/
|
|
{
|
|
// This is only used by our own tests.
|
|
// We can delete it later.
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react-cache',
|
|
global: 'ReactCacheOld',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'scheduler'],
|
|
},
|
|
|
|
/******* Hook for managing subscriptions safely *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-subscription',
|
|
global: 'useSubscription',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* useSyncExternalStore *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-sync-external-store',
|
|
global: 'useSyncExternalStore',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* useSyncExternalStore (shim) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-sync-external-store/shim',
|
|
global: 'useSyncExternalStore',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* useSyncExternalStore (shim, native) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-sync-external-store/shim/index.native',
|
|
global: 'useSyncExternalStore',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* useSyncExternalStoreWithSelector *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-sync-external-store/with-selector',
|
|
global: 'useSyncExternalStoreWithSelector',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react'],
|
|
},
|
|
|
|
/******* useSyncExternalStoreWithSelector (shim) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'use-sync-external-store/shim/with-selector',
|
|
global: 'useSyncExternalStoreWithSelector',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['react', 'use-sync-external-store/shim'],
|
|
},
|
|
|
|
/******* React Scheduler (experimental) *******/
|
|
{
|
|
bundleTypes: [
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
RN_FB_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'scheduler',
|
|
global: 'Scheduler',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: true,
|
|
externals: ['ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React Scheduler Mock (experimental) *******/
|
|
{
|
|
bundleTypes: [
|
|
UMD_DEV,
|
|
UMD_PROD,
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
RN_FB_DEV,
|
|
RN_FB_PROD,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'scheduler/unstable_mock',
|
|
global: 'SchedulerMock',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React Scheduler Native *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'scheduler/index.native',
|
|
global: 'SchedulerNative',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['ReactNativeInternalFeatureFlags'],
|
|
},
|
|
|
|
/******* React Scheduler Post Task (experimental) *******/
|
|
{
|
|
bundleTypes: [
|
|
NODE_DEV,
|
|
NODE_PROD,
|
|
FB_WWW_DEV,
|
|
FB_WWW_PROD,
|
|
FB_WWW_PROFILING,
|
|
],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'scheduler/unstable_post_task',
|
|
global: 'SchedulerPostTask',
|
|
minifyWithProdErrorCodes: true,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* Jest React (experimental) *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'jest-react',
|
|
global: 'JestReact',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: ['react', 'scheduler', 'scheduler/unstable_mock'],
|
|
},
|
|
|
|
/******* ESLint Plugin for Hooks *******/
|
|
{
|
|
// TODO: it's awkward to create a bundle for this but if we don't, the package
|
|
// won't get copied. We also can't create just DEV bundle because it contains a
|
|
// NODE_ENV check inside. We should probably tweak our build process to allow
|
|
// "raw" packages that don't get bundled.
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'eslint-plugin-react-hooks',
|
|
global: 'ESLintPluginReactHooks',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
|
|
/******* React Fresh *******/
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react-refresh/babel',
|
|
global: 'ReactFreshBabelPlugin',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
{
|
|
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV],
|
|
moduleType: ISOMORPHIC,
|
|
entry: 'react-refresh/runtime',
|
|
global: 'ReactFreshRuntime',
|
|
minifyWithProdErrorCodes: false,
|
|
wrapWithModuleBoundaries: false,
|
|
externals: [],
|
|
},
|
|
];
|
|
|
|
// Based on deep-freeze by substack (public domain)
|
|
function deepFreeze(o) {
|
|
Object.freeze(o);
|
|
Object.getOwnPropertyNames(o).forEach(function (prop) {
|
|
if (
|
|
o[prop] !== null &&
|
|
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
|
|
!Object.isFrozen(o[prop])
|
|
) {
|
|
deepFreeze(o[prop]);
|
|
}
|
|
});
|
|
return o;
|
|
}
|
|
|
|
// Don't accidentally mutate config as part of the build
|
|
deepFreeze(bundles);
|
|
deepFreeze(bundleTypes);
|
|
deepFreeze(moduleTypes);
|
|
|
|
function getFilename(bundle, bundleType) {
|
|
let name = bundle.name || bundle.entry;
|
|
const globalName = bundle.global;
|
|
// we do this to replace / to -, for react-dom/server
|
|
name = name.replace('/index.', '.').replace('/', '-');
|
|
switch (bundleType) {
|
|
case NODE_ES2015:
|
|
return `${name}.js`;
|
|
case BUN_DEV:
|
|
return `${name}.development.js`;
|
|
case BUN_PROD:
|
|
return `${name}.production.min.js`;
|
|
case ESM_DEV:
|
|
return `${name}.development.js`;
|
|
case ESM_PROD:
|
|
return `${name}.production.min.js`;
|
|
case UMD_DEV:
|
|
return `${name}.development.js`;
|
|
case UMD_PROD:
|
|
return `${name}.production.min.js`;
|
|
case UMD_PROFILING:
|
|
return `${name}.profiling.min.js`;
|
|
case NODE_DEV:
|
|
return `${name}.development.js`;
|
|
case NODE_PROD:
|
|
return `${name}.production.min.js`;
|
|
case NODE_PROFILING:
|
|
return `${name}.profiling.min.js`;
|
|
case FB_WWW_DEV:
|
|
case RN_OSS_DEV:
|
|
case RN_FB_DEV:
|
|
return `${globalName}-dev.js`;
|
|
case FB_WWW_PROD:
|
|
case RN_OSS_PROD:
|
|
case RN_FB_PROD:
|
|
return `${globalName}-prod.js`;
|
|
case FB_WWW_PROFILING:
|
|
case RN_FB_PROFILING:
|
|
case RN_OSS_PROFILING:
|
|
return `${globalName}-profiling.js`;
|
|
case BROWSER_SCRIPT:
|
|
return `${name}.js`;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
bundleTypes,
|
|
moduleTypes,
|
|
bundles,
|
|
getFilename,
|
|
};
|