diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index c697d3142c1c3..eda06fb8fd6ab 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -89,10 +89,8 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) { plugins: options.plugins.concat([ // Use object-assign polyfill in open source resolve('./scripts/babel/transform-object-assign-require'), - // Minify invariant messages require('../error-codes/replace-invariant-error-codes'), - // Wrap warning() calls in a __DEV__ check so they are stripped from production. require('./plugins/wrap-warning-with-env-check'), ]), @@ -310,17 +308,17 @@ function getPlugins( ].filter(Boolean); } -function createBundle(bundle, bundleType) { +async function createBundle(bundle, bundleType) { const shouldSkipBundleType = bundle.bundleTypes.indexOf(bundleType) === -1; if (shouldSkipBundleType) { - return Promise.resolve(); + return; } if (requestedBundleTypes.length > 0) { const isAskingForDifferentType = requestedBundleTypes.every( requestedType => bundleType.indexOf(requestedType) === -1 ); if (isAskingForDifferentType) { - return Promise.resolve(); + return; } } if (requestedBundleNames.length > 0) { @@ -328,7 +326,7 @@ function createBundle(bundle, bundleType) { requestedName => bundle.label.indexOf(requestedName) === -1 ); if (isAskingForDifferentNames) { - return Promise.resolve(); + return; } } @@ -364,160 +362,125 @@ function createBundle(bundle, bundleType) { ); console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`); - return rollup({ - input: resolvedEntry, - pureExternalModules, - external(id) { - const containsThisModule = pkg => id === pkg || id.startsWith(pkg + '/'); - const isProvidedByDependency = externals.some(containsThisModule); - if (!shouldBundleDependencies && isProvidedByDependency) { - return true; - } - return !!peerGlobals[id]; - }, - onwarn: handleRollupWarnings, - plugins: getPlugins( - bundle.entry, - externals, - bundle.babel, - filename, - bundleType, - bundle.global, - bundle.moduleType, - bundle.modulesToStub, - bundle.featureFlags - ), - // We can't use getters in www. - legacy: bundleType === FB_DEV || bundleType === FB_PROD, - }) - .then(result => - result.write( - getRollupOutputOptions( - filename, - format, - bundleType, - peerGlobals, - bundle.global, - bundle.moduleType - ) - ) - ) - .then(() => Packaging.createNodePackage(bundleType, packageName, filename)) - .then(() => { - console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`); - }) - .catch(error => { - if (error.code) { - console.error( - `\x1b[31m-- ${error.code}${ - error.plugin ? ` (${error.plugin})` : '' - } --` - ); - console.error(error.message); - - const {file, line, column} = error.loc; - if (file) { - // This looks like an error from Rollup, e.g. missing export. - // We'll use the accurate line numbers provided by Rollup but - // use Babel code frame because it looks nicer. - const rawLines = fs.readFileSync(file, 'utf-8'); - // column + 1 is required due to rollup counting column start position from 0 - // whereas babel-code-frame counts from 1 - const frame = codeFrame(rawLines, line, column + 1, { - highlightCode: true, - }); - console.error(frame); - } else { - // This looks like an error from a plugin (e.g. Babel). - // In this case we'll resort to displaying the provided code frame - // because we can't be sure the reported location is accurate. - console.error(error.codeFrame); + try { + const result = await rollup({ + input: resolvedEntry, + pureExternalModules, + external(id) { + const containsThisModule = pkg => + id === pkg || id.startsWith(pkg + '/'); + const isProvidedByDependency = externals.some(containsThisModule); + if (!shouldBundleDependencies && isProvidedByDependency) { + return true; } + return !!peerGlobals[id]; + }, + onwarn: handleRollupWarnings, + plugins: getPlugins( + bundle.entry, + externals, + bundle.babel, + filename, + bundleType, + bundle.global, + bundle.moduleType, + bundle.modulesToStub, + bundle.featureFlags + ), + // We can't use getters in www. + legacy: bundleType === FB_DEV || bundleType === FB_PROD, + }); + await result.write( + getRollupOutputOptions( + filename, + format, + bundleType, + peerGlobals, + bundle.global, + bundle.moduleType + ) + ); + await Packaging.createNodePackage(bundleType, packageName, filename); + console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`); + } catch (error) { + if (error.code) { + console.error( + `\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --` + ); + console.error(error.message); + const {file, line, column} = error.loc; + if (file) { + // This looks like an error from Rollup, e.g. missing export. + // We'll use the accurate line numbers provided by Rollup but + // use Babel code frame because it looks nicer. + const rawLines = fs.readFileSync(file, 'utf-8'); + // column + 1 is required due to rollup counting column start position from 0 + // whereas babel-code-frame counts from 1 + const frame = codeFrame(rawLines, line, column + 1, { + highlightCode: true, + }); + console.error(frame); } else { - console.error(error); + // This looks like an error from a plugin (e.g. Babel). + // In this case we'll resort to displaying the provided code frame + // because we can't be sure the reported location is accurate. + console.error(error.codeFrame); } - process.exit(1); - }); + } else { + console.error(error); + } + process.exit(1); + } } // clear the build directory -rimraf('build', () => { - // create a new build directory - fs.mkdirSync('build'); - // create the packages folder for NODE+UMD bundles - fs.mkdirSync(join('build', 'packages')); - // create the dist folder for UMD bundles - fs.mkdirSync(join('build', 'dist')); +rimraf('build', async () => { + try { + // create a new build directory + fs.mkdirSync('build'); + // create the packages folder for NODE+UMD bundles + fs.mkdirSync(join('build', 'packages')); + // create the dist folder for UMD bundles + fs.mkdirSync(join('build', 'dist')); - const tasks = [ - Packaging.createFacebookWWWBuild, - Packaging.createReactNativeBuild, - Packaging.createReactNativeRTBuild, - Packaging.createReactNativeCSBuild, - ]; - for (const bundle of Bundles.bundles) { - tasks.push( - () => createBundle(bundle, UMD_DEV), - () => createBundle(bundle, UMD_PROD), - () => createBundle(bundle, NODE_DEV), - () => createBundle(bundle, NODE_PROD), - () => createBundle(bundle, FB_DEV), - () => createBundle(bundle, FB_PROD), - () => createBundle(bundle, RN_DEV), - () => createBundle(bundle, RN_PROD) - ); - } - if (syncFbsource) { - tasks.push(() => - syncReactNative(join('build', 'react-native'), syncFbsource) - ); - tasks.push(() => - syncReactNativeRT(join('build', 'react-rt'), syncFbsource) - ); - tasks.push(() => - syncReactNativeCS(join('build', 'react-cs'), syncFbsource) - ); - } else if (syncWww) { - tasks.push(() => syncReactDom(join('build', 'facebook-www'), syncWww)); - } - // rather than run concurrently, opt to run them serially - // this helps improve console/warning/error output - // and fixes a bunch of IO failures that sometimes occurred - return runWaterfall(tasks) - .then(() => { - // output the results - console.log(Stats.printResults()); - // save the results for next run - Stats.saveResults(); - if (shouldExtractErrors) { - console.warn( - '\nWarning: this build was created with --extract-errors enabled.\n' + - 'this will result in extremely slow builds and should only be\n' + - 'used when the error map needs to be rebuilt.\n' - ); - } - }) - .catch(err => { - console.error(err); - process.exit(1); - }); -}); + await Packaging.createFacebookWWWBuild(); + await Packaging.createReactNativeBuild(); + await Packaging.createReactNativeRTBuild(); + await Packaging.createReactNativeCSBuild(); -function runWaterfall(promiseFactories) { - if (promiseFactories.length === 0) { - return Promise.resolve(); - } + // Run them serially for better console output + // and to avoid any potential race conditions. + for (const bundle of Bundles.bundles) { + await createBundle(bundle, UMD_DEV); + await createBundle(bundle, UMD_PROD); + await createBundle(bundle, NODE_DEV); + await createBundle(bundle, NODE_PROD); + await createBundle(bundle, FB_DEV); + await createBundle(bundle, FB_PROD); + await createBundle(bundle, RN_DEV); + await createBundle(bundle, RN_PROD); + } - const head = promiseFactories[0]; - const tail = promiseFactories.slice(1); + if (syncFbsource) { + await syncReactNative(join('build', 'react-native'), syncFbsource); + await syncReactNativeRT(join('build', 'react-rt'), syncFbsource); + await syncReactNativeCS(join('build', 'react-cs'), syncFbsource); + } else if (syncWww) { + await syncReactDom(join('build', 'facebook-www'), syncWww); + } - const nextPromiseFactory = head; - const nextPromise = nextPromiseFactory(); - if (!nextPromise || typeof nextPromise.then !== 'function') { - throw new Error('runWaterfall() received something that is not a Promise.'); + console.log(Stats.printResults()); + // save the results for next run + Stats.saveResults(); + if (shouldExtractErrors) { + console.warn( + '\nWarning: this build was created with --extract-errors enabled.\n' + + 'this will result in extremely slow builds and should only be\n' + + 'used when the error map needs to be rebuilt.\n' + ); + } + } catch (err) { + console.error(err); + process.exit(1); } - - return nextPromise.then(() => { - return runWaterfall(tail); - }); -} +}); diff --git a/scripts/rollup/packaging.js b/scripts/rollup/packaging.js index c272d7cddd751..af3aa50ac5c4b 100644 --- a/scripts/rollup/packaging.js +++ b/scripts/rollup/packaging.js @@ -41,149 +41,113 @@ function getPackageName(name) { return name; } -function createReactNativeBuild() { - // create the react-native folder for FB bundles +async function createReactNativeBuild() { fs.mkdirSync(join('build', 'react-native')); - // create the react-native shims folder for FB shims fs.mkdirSync(join('build', 'react-native', 'shims')); - // copy in all the shims from build/rollup/shims/react-native const from = join('scripts', 'rollup', 'shims', 'react-native'); const to = join('build', 'react-native', 'shims'); - - return asyncCopyTo(from, to).then(() => { - let promises = []; - // we also need to copy over some specific files from src - // defined in reactNativeSrcDependencies - for (const srcDependency of reactNativeSrcDependencies) { - promises.push( - asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency))) - ); - } - return Promise.all(promises); - }); + await asyncCopyTo(from, to); + await Promise.all( + reactNativeSrcDependencies.map(srcDependency => + asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency))) + ) + ); } -function createReactNativeRTBuild() { - // create the react-rt folder for FB bundles +async function createReactNativeRTBuild() { fs.mkdirSync(join('build', 'react-rt')); - // create the react-rt shims folder for FB shims fs.mkdirSync(join('build', 'react-rt', 'shims')); - const to = join('build', 'react-rt', 'shims'); - - let promises = []; - // we also need to copy over some specific files from src - // defined in reactNativeRTSrcDependencies - for (const srcDependency of reactNativeRTSrcDependencies) { - promises.push( + await Promise.all( + reactNativeRTSrcDependencies.map(srcDependency => asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency))) - ); - } - return Promise.all(promises); + ) + ); } -function createReactNativeCSBuild() { - // create the react-cs folder for FB bundles +async function createReactNativeCSBuild() { fs.mkdirSync(join('build', 'react-cs')); - // create the react-cs shims folder for FB shims fs.mkdirSync(join('build', 'react-cs', 'shims')); - const to = join('build', 'react-cs', 'shims'); - - let promises = []; - // we also need to copy over some specific files from src - // defined in reactNativeCSSrcDependencies - for (const srcDependency of reactNativeCSSrcDependencies) { - promises.push( + await Promise.all( + reactNativeCSSrcDependencies.map(srcDependency => asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency))) - ); - } - return Promise.all(promises); + ) + ); } -function createFacebookWWWBuild() { - // create the facebookWWW folder for FB bundles +async function createFacebookWWWBuild() { fs.mkdirSync(join('build', facebookWWW)); - // create the facebookWWW shims folder for FB shims fs.mkdirSync(join('build', facebookWWW, 'shims')); - // copy in all the shims from build/rollup/shims/facebook-www const from = join('scripts', 'rollup', 'shims', facebookWWW); const to = join('build', facebookWWW, 'shims'); - - return asyncCopyTo(from, to); + await asyncCopyTo(from, to); } -function copyBundleIntoNodePackage(packageName, filename, bundleType) { +async function copyBundleIntoNodePackage(packageName, filename, bundleType) { const packageDirectory = resolve(`./build/packages/${packageName}`); - - if (fs.existsSync(packageDirectory)) { - let from = resolve(`./build/${filename}`); - let to = `${packageDirectory}/${filename}`; - // for UMD bundles we have to move the files into a umd directory - // within the package directory. we also need to set the from - // to be the root build from directory - if (bundleType === UMD_DEV || bundleType === UMD_PROD) { - const distDirectory = `${packageDirectory}/umd`; - // create a dist directory if not created - if (!fs.existsSync(distDirectory)) { - fs.mkdirSync(distDirectory); - } - from = resolve(`./build/dist/${filename}`); - to = `${packageDirectory}/umd/${filename}`; + if (!fs.existsSync(packageDirectory)) { + return; + } + let from = resolve(`./build/${filename}`); + let to = `${packageDirectory}/${filename}`; + // for UMD bundles we have to move the files into a umd directory + // within the package directory. we also need to set the from + // to be the root build from directory + if (bundleType === UMD_DEV || bundleType === UMD_PROD) { + const distDirectory = `${packageDirectory}/umd`; + // create a dist directory if not created + if (!fs.existsSync(distDirectory)) { + fs.mkdirSync(distDirectory); } - // for NODE bundles we have to move the files into a cjs directory - // within the package directory. we also need to set the from - // to be the root build from directory - if (bundleType === NODE_DEV || bundleType === NODE_PROD) { - const distDirectory = `${packageDirectory}/cjs`; - // create a dist directory if not created - if (!fs.existsSync(distDirectory)) { - fs.mkdirSync(distDirectory); - } - to = `${packageDirectory}/cjs/${filename}`; + from = resolve(`./build/dist/${filename}`); + to = `${packageDirectory}/umd/${filename}`; + } + // for NODE bundles we have to move the files into a cjs directory + // within the package directory. we also need to set the from + // to be the root build from directory + if (bundleType === NODE_DEV || bundleType === NODE_PROD) { + const distDirectory = `${packageDirectory}/cjs`; + // create a dist directory if not created + if (!fs.existsSync(distDirectory)) { + fs.mkdirSync(distDirectory); } - return asyncCopyTo(from, to).then(() => { - // delete the old file if this is a not a UMD bundle - if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) { - fs.unlinkSync(from); - } - }); - } else { - return Promise.resolve(); + to = `${packageDirectory}/cjs/${filename}`; + } + await asyncCopyTo(from, to); + // delete the old file if this is a not a UMD bundle + if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) { + fs.unlinkSync(from); } } -function copyNodePackageTemplate(packageName) { +async function copyNodePackageTemplate(packageName) { const from = resolve(`./packages/${packageName}`); const to = resolve(`./build/packages/${packageName}`); const npmFrom = resolve(`${from}/npm`); if (!fs.existsSync(npmFrom)) { // The package is not meant for npm consumption. - return Promise.resolve(); + return; } if (fs.existsSync(to)) { // We already created this package (e.g. due to another entry point). - return Promise.resolve(); + return; } // TODO: verify that all copied files are either in the "files" // whitelist or implicitly published by npm. - return asyncCopyTo(npmFrom, to).then(() => - Promise.all([ - asyncCopyTo(resolve(`${from}/package.json`), `${to}/package.json`), - asyncCopyTo(resolve(`${from}/README.md`), `${to}/README.md`), - asyncCopyTo(resolve('./LICENSE'), `${to}/LICENSE`), - ]) - ); + await asyncCopyTo(npmFrom, to); + await asyncCopyTo(resolve(`${from}/package.json`), `${to}/package.json`); + await asyncCopyTo(resolve(`${from}/README.md`), `${to}/README.md`); + await asyncCopyTo(resolve('./LICENSE'), `${to}/LICENSE`); } -function createNodePackage(bundleType, packageName, filename) { +async function createNodePackage(bundleType, packageName, filename) { // the only case where we don't want to copy the package is for FB bundles - if (bundleType !== FB_DEV && bundleType !== FB_PROD) { - return copyNodePackageTemplate(packageName).then(() => - copyBundleIntoNodePackage(packageName, filename, bundleType) - ); + if (bundleType === FB_DEV || bundleType === FB_PROD) { + return; } - return Promise.resolve(); + await copyNodePackageTemplate(packageName); + await copyBundleIntoNodePackage(packageName, filename, bundleType); } function getOutputPathRelativeToBuildFolder(bundleType, filename, hasteName) { diff --git a/scripts/rollup/sync.js b/scripts/rollup/sync.js index 70626b61f6bd2..81217f6c83ee5 100644 --- a/scripts/rollup/sync.js +++ b/scripts/rollup/sync.js @@ -11,18 +11,14 @@ const RELATIVE_RN_CS_PATH = 'xplat/js/RKJSModules/Libraries/CS/downstream/'; const RELATIVE_RN_RT_PATH = 'xplat/js/RKJSModules/Libraries/RT/downstream/'; const RELATIVE_WWW_PATH = 'html/shared/react/'; -function doSync(buildPath, destPath) { +async function doSync(buildPath, destPath) { console.log(`${chalk.bgYellow.black(' SYNCING ')} React to ${destPath}`); - const promise = asyncCopyTo(buildPath, destPath); - promise.then(() => { - console.log(`${chalk.bgGreen.black(' SYNCED ')} React to ${destPath}`); - }); - - return promise; + await asyncCopyTo(buildPath, destPath); + console.log(`${chalk.bgGreen.black(' SYNCED ')} React to ${destPath}`); } -function syncReactDom(buildPath, wwwPath) { +async function syncReactDom(buildPath, wwwPath) { wwwPath = typeof wwwPath === 'string' ? wwwPath : DEFAULT_WWW_PATH; if (wwwPath.charAt(wwwPath.length - 1) !== '/') { @@ -30,11 +26,14 @@ function syncReactDom(buildPath, wwwPath) { } const destPath = resolvePath(wwwPath + RELATIVE_WWW_PATH); - - return doSync(buildPath, destPath); + await doSync(buildPath, destPath); } -function syncReactNativeHelper(buildPath, fbSourcePath, relativeDestPath) { +async function syncReactNativeHelper( + buildPath, + fbSourcePath, + relativeDestPath +) { fbSourcePath = typeof fbSourcePath === 'string' ? fbSourcePath : DEFAULT_FB_SOURCE_PATH; @@ -43,20 +42,19 @@ function syncReactNativeHelper(buildPath, fbSourcePath, relativeDestPath) { } const destPath = resolvePath(fbSourcePath + relativeDestPath); - - return doSync(buildPath, destPath); + await doSync(buildPath, destPath); } -function syncReactNative(buildPath, fbSourcePath) { - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_PATH); +async function syncReactNative(buildPath, fbSourcePath) { + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_PATH); } -function syncReactNativeCS(buildPath, fbSourcePath) { - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_CS_PATH); +async function syncReactNativeCS(buildPath, fbSourcePath) { + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_CS_PATH); } -function syncReactNativeRT(buildPath, fbSourcePath) { - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_RT_PATH); +async function syncReactNativeRT(buildPath, fbSourcePath) { + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_RT_PATH); } module.exports = {