@samitouri / QOS-React / commits / a65a8abc65

Use async/await in Rollup scripts (#11669)

Dan Abramov committed Nov 27, 2017 at 17:57 UTC a65a8abc65cd31c862f5e83eb24a8dc68458b521
3 files changed +194 -269
scripts/rollup/build.js
+115 -152
@@ -89,10 +89,8 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
89 plugins: options.plugins.concat([
90 // Use object-assign polyfill in open source
91 resolve('./scripts/babel/transform-object-assign-require'),
92 -
92 // Minify invariant messages
93 require('../error-codes/replace-invariant-error-codes'),
95 -
94 // Wrap warning() calls in a __DEV__ check so they are stripped from production.
95 require('./plugins/wrap-warning-with-env-check'),
96 ]),
@@ -310,17 +308,17 @@ function getPlugins(
308 ].filter(Boolean);
309 }
310
313 -function createBundle(bundle, bundleType) {
311 +async function createBundle(bundle, bundleType) {
312 const shouldSkipBundleType = bundle.bundleTypes.indexOf(bundleType) === -1;
313 if (shouldSkipBundleType) {
316 - return Promise.resolve();
314 + return;
315 }
316 if (requestedBundleTypes.length > 0) {
317 const isAskingForDifferentType = requestedBundleTypes.every(
318 requestedType => bundleType.indexOf(requestedType) === -1
319 );
320 if (isAskingForDifferentType) {
323 - return Promise.resolve();
321 + return;
322 }
323 }
324 if (requestedBundleNames.length > 0) {
@@ -328,7 +326,7 @@ function createBundle(bundle, bundleType) {
326 requestedName => bundle.label.indexOf(requestedName) === -1
327 );
328 if (isAskingForDifferentNames) {
331 - return Promise.resolve();
329 + return;
330 }
331 }
332
@@ -364,160 +362,125 @@ function createBundle(bundle, bundleType) {
362 );
363
364 console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);
367 - return rollup({
368 - input: resolvedEntry,
369 - pureExternalModules,
370 - external(id) {
371 - const containsThisModule = pkg => id === pkg || id.startsWith(pkg + '/');
372 - const isProvidedByDependency = externals.some(containsThisModule);
373 - if (!shouldBundleDependencies && isProvidedByDependency) {
374 - return true;
375 - }
376 - return !!peerGlobals[id];
377 - },
378 - onwarn: handleRollupWarnings,
379 - plugins: getPlugins(
380 - bundle.entry,
381 - externals,
382 - bundle.babel,
383 - filename,
384 - bundleType,
385 - bundle.global,
386 - bundle.moduleType,
387 - bundle.modulesToStub,
388 - bundle.featureFlags
389 - ),
390 - // We can't use getters in www.
391 - legacy: bundleType === FB_DEV || bundleType === FB_PROD,
392 - })
393 - .then(result =>
394 - result.write(
395 - getRollupOutputOptions(
396 - filename,
397 - format,
398 - bundleType,
399 - peerGlobals,
400 - bundle.global,
401 - bundle.moduleType
402 - )
403 - )
404 - )
405 - .then(() => Packaging.createNodePackage(bundleType, packageName, filename))
406 - .then(() => {
407 - console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
408 - })
409 - .catch(error => {
410 - if (error.code) {
411 - console.error(
412 - `\x1b[31m-- ${error.code}${
413 - error.plugin ? ` (${error.plugin})` : ''
414 - } --`
415 - );
416 - console.error(error.message);
417 -
418 - const {file, line, column} = error.loc;
419 - if (file) {
420 - // This looks like an error from Rollup, e.g. missing export.
421 - // We'll use the accurate line numbers provided by Rollup but
422 - // use Babel code frame because it looks nicer.
423 - const rawLines = fs.readFileSync(file, 'utf-8');
424 - // column + 1 is required due to rollup counting column start position from 0
425 - // whereas babel-code-frame counts from 1
426 - const frame = codeFrame(rawLines, line, column + 1, {
427 - highlightCode: true,
428 - });
429 - console.error(frame);
430 - } else {
431 - // This looks like an error from a plugin (e.g. Babel).
432 - // In this case we'll resort to displaying the provided code frame
433 - // because we can't be sure the reported location is accurate.
434 - console.error(error.codeFrame);
365 + try {
366 + const result = await rollup({
367 + input: resolvedEntry,
368 + pureExternalModules,
369 + external(id) {
370 + const containsThisModule = pkg =>
371 + id === pkg || id.startsWith(pkg + '/');
372 + const isProvidedByDependency = externals.some(containsThisModule);
373 + if (!shouldBundleDependencies && isProvidedByDependency) {
374 + return true;
375 }
376 + return !!peerGlobals[id];
377 + },
378 + onwarn: handleRollupWarnings,
379 + plugins: getPlugins(
380 + bundle.entry,
381 + externals,
382 + bundle.babel,
383 + filename,
384 + bundleType,
385 + bundle.global,
386 + bundle.moduleType,
387 + bundle.modulesToStub,
388 + bundle.featureFlags
389 + ),
390 + // We can't use getters in www.
391 + legacy: bundleType === FB_DEV || bundleType === FB_PROD,
392 + });
393 + await result.write(
394 + getRollupOutputOptions(
395 + filename,
396 + format,
397 + bundleType,
398 + peerGlobals,
399 + bundle.global,
400 + bundle.moduleType
401 + )
402 + );
403 + await Packaging.createNodePackage(bundleType, packageName, filename);
404 + console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
405 + } catch (error) {
406 + if (error.code) {
407 + console.error(
408 + `\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --`
409 + );
410 + console.error(error.message);
411 + const {file, line, column} = error.loc;
412 + if (file) {
413 + // This looks like an error from Rollup, e.g. missing export.
414 + // We'll use the accurate line numbers provided by Rollup but
415 + // use Babel code frame because it looks nicer.
416 + const rawLines = fs.readFileSync(file, 'utf-8');
417 + // column + 1 is required due to rollup counting column start position from 0
418 + // whereas babel-code-frame counts from 1
419 + const frame = codeFrame(rawLines, line, column + 1, {
420 + highlightCode: true,
421 + });
422 + console.error(frame);
423 } else {
437 - console.error(error);
424 + // This looks like an error from a plugin (e.g. Babel).
425 + // In this case we'll resort to displaying the provided code frame
426 + // because we can't be sure the reported location is accurate.
427 + console.error(error.codeFrame);
428 }
439 - process.exit(1);
440 - });
429 + } else {
430 + console.error(error);
431 + }
432 + process.exit(1);
433 + }
434 }
435
436 // clear the build directory
444 -rimraf('build', () => {
445 - // create a new build directory
446 - fs.mkdirSync('build');
447 - // create the packages folder for NODE+UMD bundles
448 - fs.mkdirSync(join('build', 'packages'));
449 - // create the dist folder for UMD bundles
450 - fs.mkdirSync(join('build', 'dist'));
437 +rimraf('build', async () => {
438 + try {
439 + // create a new build directory
440 + fs.mkdirSync('build');
441 + // create the packages folder for NODE+UMD bundles
442 + fs.mkdirSync(join('build', 'packages'));
443 + // create the dist folder for UMD bundles
444 + fs.mkdirSync(join('build', 'dist'));
445
452 - const tasks = [
453 - Packaging.createFacebookWWWBuild,
454 - Packaging.createReactNativeBuild,
455 - Packaging.createReactNativeRTBuild,
456 - Packaging.createReactNativeCSBuild,
457 - ];
458 - for (const bundle of Bundles.bundles) {
459 - tasks.push(
460 - () => createBundle(bundle, UMD_DEV),
461 - () => createBundle(bundle, UMD_PROD),
462 - () => createBundle(bundle, NODE_DEV),
463 - () => createBundle(bundle, NODE_PROD),
464 - () => createBundle(bundle, FB_DEV),
465 - () => createBundle(bundle, FB_PROD),
466 - () => createBundle(bundle, RN_DEV),
467 - () => createBundle(bundle, RN_PROD)
468 - );
469 - }
470 - if (syncFbsource) {
471 - tasks.push(() =>
472 - syncReactNative(join('build', 'react-native'), syncFbsource)
473 - );
474 - tasks.push(() =>
475 - syncReactNativeRT(join('build', 'react-rt'), syncFbsource)
476 - );
477 - tasks.push(() =>
478 - syncReactNativeCS(join('build', 'react-cs'), syncFbsource)
479 - );
480 - } else if (syncWww) {
481 - tasks.push(() => syncReactDom(join('build', 'facebook-www'), syncWww));
482 - }
483 - // rather than run concurrently, opt to run them serially
484 - // this helps improve console/warning/error output
485 - // and fixes a bunch of IO failures that sometimes occurred
486 - return runWaterfall(tasks)
487 - .then(() => {
488 - // output the results
489 - console.log(Stats.printResults());
490 - // save the results for next run
491 - Stats.saveResults();
492 - if (shouldExtractErrors) {
493 - console.warn(
494 - '\nWarning: this build was created with --extract-errors enabled.\n' +
495 - 'this will result in extremely slow builds and should only be\n' +
496 - 'used when the error map needs to be rebuilt.\n'
497 - );
498 - }
499 - })
500 - .catch(err => {
501 - console.error(err);
502 - process.exit(1);
503 - });
504 -});
446 + await Packaging.createFacebookWWWBuild();
447 + await Packaging.createReactNativeBuild();
448 + await Packaging.createReactNativeRTBuild();
449 + await Packaging.createReactNativeCSBuild();
450
506 -function runWaterfall(promiseFactories) {
507 - if (promiseFactories.length === 0) {
508 - return Promise.resolve();
509 - }
451 + // Run them serially for better console output
452 + // and to avoid any potential race conditions.
453 + for (const bundle of Bundles.bundles) {
454 + await createBundle(bundle, UMD_DEV);
455 + await createBundle(bundle, UMD_PROD);
456 + await createBundle(bundle, NODE_DEV);
457 + await createBundle(bundle, NODE_PROD);
458 + await createBundle(bundle, FB_DEV);
459 + await createBundle(bundle, FB_PROD);
460 + await createBundle(bundle, RN_DEV);
461 + await createBundle(bundle, RN_PROD);
462 + }
463
511 - const head = promiseFactories[0];
512 - const tail = promiseFactories.slice(1);
464 + if (syncFbsource) {
465 + await syncReactNative(join('build', 'react-native'), syncFbsource);
466 + await syncReactNativeRT(join('build', 'react-rt'), syncFbsource);
467 + await syncReactNativeCS(join('build', 'react-cs'), syncFbsource);
468 + } else if (syncWww) {
469 + await syncReactDom(join('build', 'facebook-www'), syncWww);
470 + }
471
514 - const nextPromiseFactory = head;
515 - const nextPromise = nextPromiseFactory();
516 - if (!nextPromise || typeof nextPromise.then !== 'function') {
517 - throw new Error('runWaterfall() received something that is not a Promise.');
472 + console.log(Stats.printResults());
473 + // save the results for next run
474 + Stats.saveResults();
475 + if (shouldExtractErrors) {
476 + console.warn(
477 + '\nWarning: this build was created with --extract-errors enabled.\n' +
478 + 'this will result in extremely slow builds and should only be\n' +
479 + 'used when the error map needs to be rebuilt.\n'
480 + );
481 + }
482 + } catch (err) {
483 + console.error(err);
484 + process.exit(1);
485 }
519 -
520 - return nextPromise.then(() => {
521 - return runWaterfall(tail);
522 - });
523 -}
486 +});
scripts/rollup/packaging.js
+62 -98
@@ -41,149 +41,113 @@ function getPackageName(name) {
41 return name;
42 }
43
44 -function createReactNativeBuild() {
45 - // create the react-native folder for FB bundles
44 +async function createReactNativeBuild() {
45 fs.mkdirSync(join('build', 'react-native'));
47 - // create the react-native shims folder for FB shims
46 fs.mkdirSync(join('build', 'react-native', 'shims'));
49 - // copy in all the shims from build/rollup/shims/react-native
47 const from = join('scripts', 'rollup', 'shims', 'react-native');
48 const to = join('build', 'react-native', 'shims');
52 -
53 - return asyncCopyTo(from, to).then(() => {
54 - let promises = [];
55 - // we also need to copy over some specific files from src
56 - // defined in reactNativeSrcDependencies
57 - for (const srcDependency of reactNativeSrcDependencies) {
58 - promises.push(
59 - asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
60 - );
61 - }
62 - return Promise.all(promises);
63 - });
49 + await asyncCopyTo(from, to);
50 + await Promise.all(
51 + reactNativeSrcDependencies.map(srcDependency =>
52 + asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
53 + )
54 + );
55 }
56
66 -function createReactNativeRTBuild() {
67 - // create the react-rt folder for FB bundles
57 +async function createReactNativeRTBuild() {
58 fs.mkdirSync(join('build', 'react-rt'));
69 - // create the react-rt shims folder for FB shims
59 fs.mkdirSync(join('build', 'react-rt', 'shims'));
71 -
60 const to = join('build', 'react-rt', 'shims');
73 -
74 - let promises = [];
75 - // we also need to copy over some specific files from src
76 - // defined in reactNativeRTSrcDependencies
77 - for (const srcDependency of reactNativeRTSrcDependencies) {
78 - promises.push(
61 + await Promise.all(
62 + reactNativeRTSrcDependencies.map(srcDependency =>
63 asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
80 - );
81 - }
82 - return Promise.all(promises);
64 + )
65 + );
66 }
67
85 -function createReactNativeCSBuild() {
86 - // create the react-cs folder for FB bundles
68 +async function createReactNativeCSBuild() {
69 fs.mkdirSync(join('build', 'react-cs'));
88 - // create the react-cs shims folder for FB shims
70 fs.mkdirSync(join('build', 'react-cs', 'shims'));
90 -
71 const to = join('build', 'react-cs', 'shims');
92 -
93 - let promises = [];
94 - // we also need to copy over some specific files from src
95 - // defined in reactNativeCSSrcDependencies
96 - for (const srcDependency of reactNativeCSSrcDependencies) {
97 - promises.push(
72 + await Promise.all(
73 + reactNativeCSSrcDependencies.map(srcDependency =>
74 asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
99 - );
100 - }
101 - return Promise.all(promises);
75 + )
76 + );
77 }
78
104 -function createFacebookWWWBuild() {
105 - // create the facebookWWW folder for FB bundles
79 +async function createFacebookWWWBuild() {
80 fs.mkdirSync(join('build', facebookWWW));
107 - // create the facebookWWW shims folder for FB shims
81 fs.mkdirSync(join('build', facebookWWW, 'shims'));
109 - // copy in all the shims from build/rollup/shims/facebook-www
82 const from = join('scripts', 'rollup', 'shims', facebookWWW);
83 const to = join('build', facebookWWW, 'shims');
112 -
113 - return asyncCopyTo(from, to);
84 + await asyncCopyTo(from, to);
85 }
86
116 -function copyBundleIntoNodePackage(packageName, filename, bundleType) {
87 +async function copyBundleIntoNodePackage(packageName, filename, bundleType) {
88 const packageDirectory = resolve(`./build/packages/${packageName}`);
118 -
119 - if (fs.existsSync(packageDirectory)) {
120 - let from = resolve(`./build/${filename}`);
121 - let to = `${packageDirectory}/${filename}`;
122 - // for UMD bundles we have to move the files into a umd directory
123 - // within the package directory. we also need to set the from
124 - // to be the root build from directory
125 - if (bundleType === UMD_DEV || bundleType === UMD_PROD) {
126 - const distDirectory = `${packageDirectory}/umd`;
127 - // create a dist directory if not created
128 - if (!fs.existsSync(distDirectory)) {
129 - fs.mkdirSync(distDirectory);
130 - }
131 - from = resolve(`./build/dist/${filename}`);
132 - to = `${packageDirectory}/umd/${filename}`;
89 + if (!fs.existsSync(packageDirectory)) {
90 + return;
91 + }
92 + let from = resolve(`./build/${filename}`);
93 + let to = `${packageDirectory}/${filename}`;
94 + // for UMD bundles we have to move the files into a umd directory
95 + // within the package directory. we also need to set the from
96 + // to be the root build from directory
97 + if (bundleType === UMD_DEV || bundleType === UMD_PROD) {
98 + const distDirectory = `${packageDirectory}/umd`;
99 + // create a dist directory if not created
100 + if (!fs.existsSync(distDirectory)) {
101 + fs.mkdirSync(distDirectory);
102 }
134 - // for NODE bundles we have to move the files into a cjs directory
135 - // within the package directory. we also need to set the from
136 - // to be the root build from directory
137 - if (bundleType === NODE_DEV || bundleType === NODE_PROD) {
138 - const distDirectory = `${packageDirectory}/cjs`;
139 - // create a dist directory if not created
140 - if (!fs.existsSync(distDirectory)) {
141 - fs.mkdirSync(distDirectory);
142 - }
143 - to = `${packageDirectory}/cjs/${filename}`;
103 + from = resolve(`./build/dist/${filename}`);
104 + to = `${packageDirectory}/umd/${filename}`;
105 + }
106 + // for NODE bundles we have to move the files into a cjs directory
107 + // within the package directory. we also need to set the from
108 + // to be the root build from directory
109 + if (bundleType === NODE_DEV || bundleType === NODE_PROD) {
110 + const distDirectory = `${packageDirectory}/cjs`;
111 + // create a dist directory if not created
112 + if (!fs.existsSync(distDirectory)) {
113 + fs.mkdirSync(distDirectory);
114 }
145 - return asyncCopyTo(from, to).then(() => {
146 - // delete the old file if this is a not a UMD bundle
147 - if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) {
148 - fs.unlinkSync(from);
149 - }
150 - });
151 - } else {
152 - return Promise.resolve();
115 + to = `${packageDirectory}/cjs/${filename}`;
116 + }
117 + await asyncCopyTo(from, to);
118 + // delete the old file if this is a not a UMD bundle
119 + if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) {
120 + fs.unlinkSync(from);
121 }
122 }
123
156 -function copyNodePackageTemplate(packageName) {
124 +async function copyNodePackageTemplate(packageName) {
125 const from = resolve(`./packages/${packageName}`);
126 const to = resolve(`./build/packages/${packageName}`);
127 const npmFrom = resolve(`${from}/npm`);
128 if (!fs.existsSync(npmFrom)) {
129 // The package is not meant for npm consumption.
162 - return Promise.resolve();
130 + return;
131 }
132 if (fs.existsSync(to)) {
133 // We already created this package (e.g. due to another entry point).
166 - return Promise.resolve();
134 + return;
135 }
136 // TODO: verify that all copied files are either in the "files"
137 // whitelist or implicitly published by npm.
170 - return asyncCopyTo(npmFrom, to).then(() =>
171 - Promise.all([
172 - asyncCopyTo(resolve(`${from}/package.json`), `${to}/package.json`),
173 - asyncCopyTo(resolve(`${from}/README.md`), `${to}/README.md`),
174 - asyncCopyTo(resolve('./LICENSE'), `${to}/LICENSE`),
175 - ])
176 - );
138 + await asyncCopyTo(npmFrom, to);
139 + await asyncCopyTo(resolve(`${from}/package.json`), `${to}/package.json`);
140 + await asyncCopyTo(resolve(`${from}/README.md`), `${to}/README.md`);
141 + await asyncCopyTo(resolve('./LICENSE'), `${to}/LICENSE`);
142 }
143
179 -function createNodePackage(bundleType, packageName, filename) {
144 +async function createNodePackage(bundleType, packageName, filename) {
145 // the only case where we don't want to copy the package is for FB bundles
181 - if (bundleType !== FB_DEV && bundleType !== FB_PROD) {
182 - return copyNodePackageTemplate(packageName).then(() =>
183 - copyBundleIntoNodePackage(packageName, filename, bundleType)
184 - );
146 + if (bundleType === FB_DEV || bundleType === FB_PROD) {
147 + return;
148 }
186 - return Promise.resolve();
149 + await copyNodePackageTemplate(packageName);
150 + await copyBundleIntoNodePackage(packageName, filename, bundleType);
151 }
152
153 function getOutputPathRelativeToBuildFolder(bundleType, filename, hasteName) {
scripts/rollup/sync.js
+17 -19
@@ -11,18 +11,14 @@ const RELATIVE_RN_CS_PATH = 'xplat/js/RKJSModules/Libraries/CS/downstream/';
11 const RELATIVE_RN_RT_PATH = 'xplat/js/RKJSModules/Libraries/RT/downstream/';
12 const RELATIVE_WWW_PATH = 'html/shared/react/';
13
14 -function doSync(buildPath, destPath) {
14 +async function doSync(buildPath, destPath) {
15 console.log(`${chalk.bgYellow.black(' SYNCING ')} React to ${destPath}`);
16
17 - const promise = asyncCopyTo(buildPath, destPath);
18 - promise.then(() => {
19 - console.log(`${chalk.bgGreen.black(' SYNCED ')} React to ${destPath}`);
20 - });
21 -
22 - return promise;
17 + await asyncCopyTo(buildPath, destPath);
18 + console.log(`${chalk.bgGreen.black(' SYNCED ')} React to ${destPath}`);
19 }
20
25 -function syncReactDom(buildPath, wwwPath) {
21 +async function syncReactDom(buildPath, wwwPath) {
22 wwwPath = typeof wwwPath === 'string' ? wwwPath : DEFAULT_WWW_PATH;
23
24 if (wwwPath.charAt(wwwPath.length - 1) !== '/') {
@@ -30,11 +26,14 @@ function syncReactDom(buildPath, wwwPath) {
26 }
27
28 const destPath = resolvePath(wwwPath + RELATIVE_WWW_PATH);
33 -
34 - return doSync(buildPath, destPath);
29 + await doSync(buildPath, destPath);
30 }
31
37 -function syncReactNativeHelper(buildPath, fbSourcePath, relativeDestPath) {
32 +async function syncReactNativeHelper(
33 + buildPath,
34 + fbSourcePath,
35 + relativeDestPath
36 +) {
37 fbSourcePath =
38 typeof fbSourcePath === 'string' ? fbSourcePath : DEFAULT_FB_SOURCE_PATH;
39
@@ -43,20 +42,19 @@ function syncReactNativeHelper(buildPath, fbSourcePath, relativeDestPath) {
42 }
43
44 const destPath = resolvePath(fbSourcePath + relativeDestPath);
46 -
47 - return doSync(buildPath, destPath);
45 + await doSync(buildPath, destPath);
46 }
47
50 -function syncReactNative(buildPath, fbSourcePath) {
51 - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_PATH);
48 +async function syncReactNative(buildPath, fbSourcePath) {
49 + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_PATH);
50 }
51
54 -function syncReactNativeCS(buildPath, fbSourcePath) {
55 - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_CS_PATH);
52 +async function syncReactNativeCS(buildPath, fbSourcePath) {
53 + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_CS_PATH);
54 }
55
58 -function syncReactNativeRT(buildPath, fbSourcePath) {
59 - return syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_RT_PATH);
56 +async function syncReactNativeRT(buildPath, fbSourcePath) {
57 + await syncReactNativeHelper(buildPath, fbSourcePath, RELATIVE_RN_RT_PATH);
58 }
59
60 module.exports = {