diff --git a/packages/react-dom/package.json b/packages/react-dom/package.json index c39432aa32046..baa9032ef4c62 100644 --- a/packages/react-dom/package.json +++ b/packages/react-dom/package.json @@ -38,6 +38,7 @@ "server-rendering-stub.js", "test-utils.js", "unstable_testing.js", + "unstable_server-external-runtime.js", "cjs/", "umd/" ], diff --git a/packages/react-dom/src/server/ReactDOMServerExternalRuntime.js b/packages/react-dom/src/server/ReactDOMServerExternalRuntime.js new file mode 100644 index 0000000000000..dccb1bb3debe9 --- /dev/null +++ b/packages/react-dom/src/server/ReactDOMServerExternalRuntime.js @@ -0,0 +1,18 @@ +// TODO: Add Flow types +import { + clientRenderBoundary, + completeBoundaryWithStyles, + completeBoundary, + completeSegment, +} from 'react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSet'; + +// Intentionally does nothing. Implementation will be added in future PR. +// eslint-disable-next-line no-unused-vars +const observer = new MutationObserver(mutations => { + // These are only called so I can check what the module output looks like. The + // code is unreachable. + clientRenderBoundary(); + completeBoundaryWithStyles(); + completeBoundary(); + completeSegment(); +}); diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index 52c0b7dc9fe29..97b949b560f15 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -60,6 +60,7 @@ const { RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING, + BROWSER_SCRIPT, } = Bundles.bundleTypes; const {getFilename} = Bundles; @@ -93,19 +94,6 @@ const isWatchMode = argv.watch; const syncFBSourcePath = argv['sync-fbsource']; const syncWWWPath = argv['sync-www']; -const closureOptions = { - compilation_level: 'SIMPLE', - language_in: 'ECMASCRIPT_2015', - language_out: 'ECMASCRIPT5_STRICT', - env: 'CUSTOM', - warning_level: 'QUIET', - apply_input_source_maps: false, - use_types_for_optimization: false, - process_common_js_modules: false, - rewrite_polyfills: false, - inject_libraries: false, -}; - // Non-ES2015 stuff applied before closure compiler. const babelPlugins = [ // These plugins filter out non-ES2015. @@ -224,6 +212,8 @@ function getFormat(bundleType) { return `cjs`; case NODE_ESM: return `es`; + case BROWSER_SCRIPT: + return `iife`; } } @@ -247,6 +237,7 @@ function isProductionBundleType(bundleType) { case RN_OSS_PROFILING: case RN_FB_PROD: case RN_FB_PROFILING: + case BROWSER_SCRIPT: return true; default: throw new Error(`Unknown type: ${bundleType}`); @@ -267,6 +258,7 @@ function isProfilingBundleType(bundleType) { case RN_OSS_PROD: case UMD_DEV: case UMD_PROD: + case BROWSER_SCRIPT: return false; case FB_WWW_PROFILING: case NODE_PROFILING: @@ -371,14 +363,24 @@ function getPlugins( isUMDBundle && entry === 'react-art' && commonjs(), // Apply dead code elimination and/or minification. isProduction && - closure( - Object.assign({}, closureOptions, { - // Don't let it create global variables in the browser. - // https://github.com/facebook/react/issues/10909 - assume_function_wrapper: !isUMDBundle, - renaming: !shouldStayReadable, - }) - ), + closure({ + compilation_level: 'SIMPLE', + language_in: 'ECMASCRIPT_2015', + language_out: + bundleType === BROWSER_SCRIPT ? 'ECMASCRIPT5' : 'ECMASCRIPT5_STRICT', + env: 'CUSTOM', + warning_level: 'QUIET', + apply_input_source_maps: false, + use_types_for_optimization: false, + process_common_js_modules: false, + rewrite_polyfills: false, + inject_libraries: false, + + // Don't let it create global variables in the browser. + // https://github.com/facebook/react/issues/10909 + assume_function_wrapper: !isUMDBundle, + renaming: !shouldStayReadable, + }), // HACK to work around the fact that Rollup isn't removing unused, pure-module imports. // Note that this plugin must be called after closure applies DCE. isProduction && stripUnusedImports(pureExternalModules), @@ -582,6 +584,7 @@ async function createBundle(bundle, bundleType) { }, }; const mainOutputPath = Packaging.getBundleOutputPath( + bundle, bundleType, filename, packageName @@ -724,7 +727,8 @@ async function buildEverything() { [bundle, RN_OSS_PROFILING], [bundle, RN_FB_DEV], [bundle, RN_FB_PROD], - [bundle, RN_FB_PROFILING] + [bundle, RN_FB_PROFILING], + [bundle, BROWSER_SCRIPT] ); } diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index 1f7297a8f2174..81072166a0269 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -25,6 +25,7 @@ const bundleTypes = { RN_FB_DEV: 'RN_FB_DEV', RN_FB_PROD: 'RN_FB_PROD', RN_FB_PROFILING: 'RN_FB_PROFILING', + BROWSER_SCRIPT: 'BROWSER_SCRIPT', }; const { @@ -45,6 +46,7 @@ const { RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING, + BROWSER_SCRIPT, } = bundleTypes; const moduleTypes = { @@ -351,6 +353,18 @@ const bundles = [ externals: ['react', 'util', 'stream', 'react-dom'], }, + /******* React DOM Fizz Server External Runtime *******/ + { + bundleTypes: [BROWSER_SCRIPT], + moduleType: RENDERER, + entry: 'react-dom/src/server/ReactDOMServerExternalRuntime.js', + 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], @@ -1030,6 +1044,8 @@ function getOriginalFilename(bundle, bundleType) { case RN_FB_PROFILING: case RN_OSS_PROFILING: return `${globalName}-profiling.js`; + case BROWSER_SCRIPT: + return `${name}.js`; } } diff --git a/scripts/rollup/packaging.js b/scripts/rollup/packaging.js index bd66d0b634730..717210ec45521 100644 --- a/scripts/rollup/packaging.js +++ b/scripts/rollup/packaging.js @@ -33,6 +33,7 @@ const { RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING, + BROWSER_SCRIPT, } = Bundles.bundleTypes; function getPackageName(name) { @@ -42,7 +43,7 @@ function getPackageName(name) { return name; } -function getBundleOutputPath(bundleType, filename, packageName) { +function getBundleOutputPath(bundle, bundleType, filename, packageName) { switch (bundleType) { case NODE_ES2015: return `build/node_modules/${packageName}/cjs/${filename}`; @@ -88,6 +89,23 @@ function getBundleOutputPath(bundleType, filename, packageName) { default: throw new Error('Unknown RN package.'); } + case BROWSER_SCRIPT: { + // Bundles that are served as browser scripts need to be able to be sent + // straight to the browser with any additional bundling. We shouldn't use + // a module to re-export. Depending on how they are served, they also may + // not go through package.json module resolution, so we shouldn't rely on + // that either. We should consider the output path as part of the public + // contract, and explicitly specify its location within the package's + // directory structure. + const outputPath = bundle.outputPath; + if (!outputPath) { + throw new Error( + 'Bundles with type BROWSER_SCRIPT must specific an explicit ' + + 'output path.' + ); + } + return `build/node_modules/${packageName}/${outputPath}`; + } default: throw new Error('Unknown bundle type.'); } diff --git a/scripts/rollup/wrappers.js b/scripts/rollup/wrappers.js index 44d83e4f58ee0..e73fb01546312 100644 --- a/scripts/rollup/wrappers.js +++ b/scripts/rollup/wrappers.js @@ -22,6 +22,7 @@ const { RN_FB_DEV, RN_FB_PROD, RN_FB_PROFILING, + BROWSER_SCRIPT, } = bundleTypes; const {RECONCILER} = moduleTypes; @@ -384,6 +385,12 @@ function wrapBundle( } } + if (bundleType === BROWSER_SCRIPT) { + // Bundles of type BROWSER_SCRIPT get sent straight to the browser without + // additional processing. So we should exclude any extra wrapper comments. + return source; + } + if (moduleType === RECONCILER) { // Standalone reconciler is only used by third-party renderers. // It is handled separately. @@ -395,6 +402,7 @@ function wrapBundle( } return wrapper(source, globalName, filename, moduleType); } + // All the other packages. const wrapper = wrappers[bundleType]; if (typeof wrapper !== 'function') { diff --git a/scripts/shared/inlinedHostConfigs.js b/scripts/shared/inlinedHostConfigs.js index 1113bad1247d0..027c71aa173b3 100644 --- a/scripts/shared/inlinedHostConfigs.js +++ b/scripts/shared/inlinedHostConfigs.js @@ -15,6 +15,7 @@ module.exports = [ 'react-dom/src/server/ReactDOMFizzServerNode.js', 'react-dom/static.node', 'react-dom/server-rendering-stub', + 'react-dom/src/server/ReactDOMServerExternalRuntime.js', 'react-server-dom-webpack/writer.node.server', 'react-server-dom-webpack', ], @@ -51,6 +52,7 @@ module.exports = [ 'react-dom/src/server/ReactDOMFizzServerBrowser.js', 'react-dom/static.browser', 'react-dom/server-rendering-stub', + 'react-dom/src/server/ReactDOMServerExternalRuntime.js', 'react-server-dom-webpack/writer.browser.server', 'react-server-dom-webpack', ],