Use async/await in Rollup scripts (#11669)

This commit is contained in:
Dan Abramov 2017-11-27 17:57:28 +00:00 committed by GitHub
parent 018276976c
commit a65a8abc65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 197 additions and 272 deletions

View File

@ -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;
}
} else {
console.error(error);
}
process.exit(1);
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 {
// 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);
}
} 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)
);
await Packaging.createFacebookWWWBuild();
await Packaging.createReactNativeBuild();
await Packaging.createReactNativeRTBuild();
await Packaging.createReactNativeCSBuild();
// 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);
}
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);
}
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);
}
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);
});
});
function runWaterfall(promiseFactories) {
if (promiseFactories.length === 0) {
return Promise.resolve();
}
const head = promiseFactories[0];
const tail = promiseFactories.slice(1);
const nextPromiseFactory = head;
const nextPromise = nextPromiseFactory();
if (!nextPromise || typeof nextPromise.then !== 'function') {
throw new Error('runWaterfall() received something that is not a Promise.');
}
return nextPromise.then(() => {
return runWaterfall(tail);
});
}

View File

@ -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) {

View File

@ -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 = {