Refactor the build scripts (#11787)
* Rewrite the build scripts * Don't crash when doing FB-only builds * Group sync imports under Sync.* * Don't print known errors twice * Use an exclamation that aligns vertically
Dan Abramov committed
Dec 6, 2017 at 20:11 UTC
f72043a36903a18703168a1ebfe271c150f27330
5 files changed
+363
-417
package.json
+1
-1
@@ -73,6 +73,7 @@
73
"jest-runtime": "^21.3.0-beta.4",
74
"merge-stream": "^1.0.0",
75
"minimist": "^1.2.0",
76
+ "mkdirp": "^0.5.1",
77
"ncp": "^2.0.0",
78
"object-assign": "^4.1.1",
79
"platform": "^1.1.0",
@@ -93,7 +94,6 @@
94
"through2": "^2.0.0",
95
"tmp": "~0.0.28",
96
"typescript": "~1.8.10",
96
- "uuid": "^3.1.0",
97
"yargs": "^6.3.0"
98
},
99
"devEngines": {
scripts/rollup/build.js
+177
-195
@@ -1,6 +1,6 @@
1
'use strict';
2
3
-const rollup = require('rollup').rollup;
3
+const {rollup} = require('rollup');
4
const babel = require('rollup-plugin-babel');
5
const closure = require('rollup-plugin-closure-compiler-js');
6
const commonjs = require('rollup-plugin-commonjs');
@@ -10,33 +10,40 @@ const stripBanner = require('rollup-plugin-strip-banner');
10
const chalk = require('chalk');
11
const path = require('path');
12
const resolve = require('rollup-plugin-node-resolve');
13
-const os = require('os');
13
const fs = require('fs');
15
-const rimraf = require('rimraf');
14
const argv = require('minimist')(process.argv.slice(2));
15
const Modules = require('./modules');
16
const Bundles = require('./bundles');
17
+const Stats = require('./stats');
18
+const Sync = require('./sync');
19
const sizes = require('./plugins/sizes-plugin');
20
const useForks = require('./plugins/use-forks-plugin');
21
-const Stats = require('./stats');
21
const extractErrorCodes = require('../error-codes/extract-errors');
23
-const syncReactDom = require('./sync').syncReactDom;
24
-const syncReactNative = require('./sync').syncReactNative;
25
-const syncReactNativeRT = require('./sync').syncReactNativeRT;
26
-const syncReactNativeCS = require('./sync').syncReactNativeCS;
22
const Packaging = require('./packaging');
23
+const {asyncCopyTo, asyncRimRaf} = require('./utils');
24
const codeFrame = require('babel-code-frame');
25
const Wrappers = require('./wrappers');
30
-const uuidv1 = require('uuid/v1');
26
32
-const UMD_DEV = Bundles.bundleTypes.UMD_DEV;
33
-const UMD_PROD = Bundles.bundleTypes.UMD_PROD;
34
-const NODE_DEV = Bundles.bundleTypes.NODE_DEV;
35
-const NODE_PROD = Bundles.bundleTypes.NODE_PROD;
36
-const FB_DEV = Bundles.bundleTypes.FB_DEV;
37
-const FB_PROD = Bundles.bundleTypes.FB_PROD;
38
-const RN_DEV = Bundles.bundleTypes.RN_DEV;
39
-const RN_PROD = Bundles.bundleTypes.RN_PROD;
27
+// Errors in promises should be fatal.
28
+let loggedErrors = new Set();
29
+process.on('unhandledRejection', err => {
30
+ if (loggedErrors.has(err)) {
31
+ // No need to print it twice.
32
+ process.exit(1);
33
+ }
34
+ throw err;
35
+});
36
+
37
+const {
38
+ UMD_DEV,
39
+ UMD_PROD,
40
+ NODE_DEV,
41
+ NODE_PROD,
42
+ FB_DEV,
43
+ FB_PROD,
44
+ RN_DEV,
45
+ RN_PROD,
46
+} = Bundles.bundleTypes;
47
48
const requestedBundleTypes = (argv.type || '')
49
.split(',')
@@ -44,16 +51,12 @@ const requestedBundleTypes = (argv.type || '')
51
const requestedBundleNames = (argv._[0] || '')
52
.split(',')
53
.map(type => type.toLowerCase());
47
-const syncFbsource = argv['sync-fbsource'];
48
-const syncWww = argv['sync-www'];
54
+const syncFBSourcePath = argv['sync-fbsource'];
55
+const syncWWWPath = argv['sync-www'];
56
const shouldExtractErrors = argv['extract-errors'];
57
const errorCodeOpts = {
58
errorMapFilePath: 'scripts/error-codes/codes.json',
59
};
53
-const npmPackagesTmpDir = path.join(
54
- os.tmpdir(),
55
- `react-npm-packages-${uuidv1()}`
56
-);
60
61
const closureOptions = {
62
compilationLevel: 'SIMPLE',
@@ -105,54 +108,11 @@ function getBabelConfig(updateBabelOptions, bundleType, filename) {
108
}
109
}
110
108
-function handleRollupWarnings(warning) {
109
- if (warning.code === 'UNRESOLVED_IMPORT') {
110
- console.error(warning.message);
111
- process.exit(1);
112
- }
113
- if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {
114
- const match = warning.message.match(/external module '([^']+)'/);
115
- if (!match || typeof match[1] !== 'string') {
116
- throw new Error(
117
- 'Could not parse a Rollup warning. ' + 'Fix this method.'
118
- );
119
- }
120
- const importSideEffects = Modules.getImportSideEffects();
121
- const externalModule = match[1];
122
- if (typeof importSideEffects[externalModule] !== 'boolean') {
123
- throw new Error(
124
- 'An external module "' +
125
- externalModule +
126
- '" is used in a DEV-only code path ' +
127
- 'but we do not know if it is safe to omit an unused require() to it in production. ' +
128
- 'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.'
129
- );
130
- }
131
- // Don't warn. We will remove side effectless require() in a later pass.
132
- return;
133
- }
134
- console.warn(warning.message || warning);
135
-}
136
-
137
-function getRollupOutputOptions(
138
- filename,
139
- format,
140
- bundleType,
141
- globals,
142
- globalName,
143
- moduleType
144
-) {
111
+function getRollupOutputOptions(outputPath, format, globals, globalName) {
112
return Object.assign(
113
{},
114
{
148
- destDir: 'build/',
149
- file:
150
- 'build/' +
151
- Packaging.getOutputPathRelativeToBuildFolder(
152
- bundleType,
153
- filename,
154
- globalName
155
- ),
115
+ file: outputPath,
116
format,
117
globals,
118
interop: false,
@@ -312,17 +272,17 @@ function getPlugins(
272
].filter(Boolean);
273
}
274
315
-async function createBundle(bundle, bundleType) {
275
+function shouldSkipBundle(bundle, bundleType) {
276
const shouldSkipBundleType = bundle.bundleTypes.indexOf(bundleType) === -1;
277
if (shouldSkipBundleType) {
318
- return;
278
+ return true;
279
}
280
if (requestedBundleTypes.length > 0) {
281
const isAskingForDifferentType = requestedBundleTypes.every(
282
requestedType => bundleType.indexOf(requestedType) === -1
283
);
284
if (isAskingForDifferentType) {
325
- return;
285
+ return true;
286
}
287
}
288
if (requestedBundleNames.length > 0) {
@@ -330,9 +290,16 @@ async function createBundle(bundle, bundleType) {
290
requestedName => bundle.label.indexOf(requestedName) === -1
291
);
292
if (isAskingForDifferentNames) {
333
- return;
293
+ return true;
294
}
295
}
296
+ return false;
297
+}
298
+
299
+async function createBundle(bundle, bundleType) {
300
+ if (shouldSkipBundle(bundle, bundleType)) {
301
+ return;
302
+ }
303
304
const filename = getFilename(bundle.entry, bundle.global, bundleType);
305
const logKey =
@@ -365,139 +332,154 @@ async function createBundle(bundle, bundleType) {
332
module => !importSideEffects[module]
333
);
334
335
+ const rollupConfig = {
336
+ input: resolvedEntry,
337
+ pureExternalModules,
338
+ external(id) {
339
+ const containsThisModule = pkg => id === pkg || id.startsWith(pkg + '/');
340
+ const isProvidedByDependency = externals.some(containsThisModule);
341
+ if (!shouldBundleDependencies && isProvidedByDependency) {
342
+ return true;
343
+ }
344
+ return !!peerGlobals[id];
345
+ },
346
+ onwarn: handleRollupWarning,
347
+ plugins: getPlugins(
348
+ bundle.entry,
349
+ externals,
350
+ bundle.babel,
351
+ filename,
352
+ bundleType,
353
+ bundle.global,
354
+ bundle.moduleType,
355
+ bundle.modulesToStub
356
+ ),
357
+ // We can't use getters in www.
358
+ legacy: bundleType === FB_DEV || bundleType === FB_PROD,
359
+ };
360
+ const [mainOutputPath, ...otherOutputPaths] = Packaging.getBundleOutputPaths(
361
+ bundleType,
362
+ filename,
363
+ packageName
364
+ );
365
+ const rollupOutputOptions = getRollupOutputOptions(
366
+ mainOutputPath,
367
+ format,
368
+ peerGlobals,
369
+ bundle.global
370
+ );
371
+
372
console.log(`${chalk.bgYellow.black(' BUILDING ')} ${logKey}`);
373
try {
370
- const result = await rollup({
371
- input: resolvedEntry,
372
- pureExternalModules,
373
- external(id) {
374
- const containsThisModule = pkg =>
375
- id === pkg || id.startsWith(pkg + '/');
376
- const isProvidedByDependency = externals.some(containsThisModule);
377
- if (!shouldBundleDependencies && isProvidedByDependency) {
378
- return true;
379
- }
380
- return !!peerGlobals[id];
381
- },
382
- onwarn: handleRollupWarnings,
383
- plugins: getPlugins(
384
- bundle.entry,
385
- externals,
386
- bundle.babel,
387
- filename,
388
- bundleType,
389
- bundle.global,
390
- bundle.moduleType,
391
- bundle.modulesToStub
392
- ),
393
- // We can't use getters in www.
394
- legacy: bundleType === FB_DEV || bundleType === FB_PROD,
395
- });
396
- await result.write(
397
- getRollupOutputOptions(
398
- filename,
399
- format,
400
- bundleType,
401
- peerGlobals,
402
- bundle.global,
403
- bundle.moduleType
404
- )
405
- );
406
- await Packaging.createNodePackage(
407
- bundleType,
408
- packageName,
409
- filename,
410
- npmPackagesTmpDir
411
- );
412
- console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
374
+ const result = await rollup(rollupConfig);
375
+ await result.write(rollupOutputOptions);
376
} catch (error) {
414
- if (error.code) {
415
- console.error(
416
- `\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --`
377
+ console.log(`${chalk.bgRed.black(' OH NOES! ')} ${logKey}\n`);
378
+ handleRollupError(error);
379
+ throw error;
380
+ }
381
+ for (let i = 0; i < otherOutputPaths.length; i++) {
382
+ await asyncCopyTo(mainOutputPath, otherOutputPaths[i]);
383
+ }
384
+ console.log(`${chalk.bgGreen.black(' COMPLETE ')} ${logKey}\n`);
385
+}
386
+
387
+function handleRollupWarning(warning) {
388
+ if (warning.code === 'UNRESOLVED_IMPORT') {
389
+ console.error(warning.message);
390
+ process.exit(1);
391
+ }
392
+ if (warning.code === 'UNUSED_EXTERNAL_IMPORT') {
393
+ const match = warning.message.match(/external module '([^']+)'/);
394
+ if (!match || typeof match[1] !== 'string') {
395
+ throw new Error(
396
+ 'Could not parse a Rollup warning. ' + 'Fix this method.'
397
);
418
- console.error(error.message);
419
- const {file, line, column} = error.loc;
420
- if (file) {
421
- // This looks like an error from Rollup, e.g. missing export.
422
- // We'll use the accurate line numbers provided by Rollup but
423
- // use Babel code frame because it looks nicer.
424
- const rawLines = fs.readFileSync(file, 'utf-8');
425
- // column + 1 is required due to rollup counting column start position from 0
426
- // whereas babel-code-frame counts from 1
427
- const frame = codeFrame(rawLines, line, column + 1, {
428
- highlightCode: true,
429
- });
430
- console.error(frame);
431
- } else {
432
- // This looks like an error from a plugin (e.g. Babel).
433
- // In this case we'll resort to displaying the provided code frame
434
- // because we can't be sure the reported location is accurate.
435
- console.error(error.codeFrame);
436
- }
437
- } else {
438
- console.error(error);
398
}
440
- process.exit(1);
399
+ const importSideEffects = Modules.getImportSideEffects();
400
+ const externalModule = match[1];
401
+ if (typeof importSideEffects[externalModule] !== 'boolean') {
402
+ throw new Error(
403
+ 'An external module "' +
404
+ externalModule +
405
+ '" is used in a DEV-only code path ' +
406
+ 'but we do not know if it is safe to omit an unused require() to it in production. ' +
407
+ 'Please add it to the `importSideEffects` list in `scripts/rollup/modules.js`.'
408
+ );
409
+ }
410
+ // Don't warn. We will remove side effectless require() in a later pass.
411
+ return;
412
}
413
+ console.warn(warning.message || warning);
414
}
415
444
-// clear the build directory
445
-rimraf('build', async () => {
446
- try {
447
- // create a new build directory
448
- fs.mkdirSync('build');
449
- // create the temp directory for local npm packing and unpacking
450
- // in operating system's default temporary directory
451
- fs.mkdirSync(npmPackagesTmpDir);
452
- // create the packages folder for NODE+UMD bundles
453
- fs.mkdirSync(path.join('build', 'packages'));
454
- // create the dist folder for UMD bundles
455
- fs.mkdirSync(path.join('build', 'dist'));
416
+function handleRollupError(error) {
417
+ loggedErrors.add(error);
418
+ if (!error.code) {
419
+ console.error(error);
420
+ return;
421
+ }
422
+ console.error(
423
+ `\x1b[31m-- ${error.code}${error.plugin ? ` (${error.plugin})` : ''} --`
424
+ );
425
+ console.error(error.message);
426
+ const {file, line, column} = error.loc;
427
+ if (file) {
428
+ // This looks like an error from Rollup, e.g. missing export.
429
+ // We'll use the accurate line numbers provided by Rollup but
430
+ // use Babel code frame because it looks nicer.
431
+ const rawLines = fs.readFileSync(file, 'utf-8');
432
+ // column + 1 is required due to rollup counting column start position from 0
433
+ // whereas babel-code-frame counts from 1
434
+ const frame = codeFrame(rawLines, line, column + 1, {
435
+ highlightCode: true,
436
+ });
437
+ console.error(frame);
438
+ } else {
439
+ // This looks like an error from a plugin (e.g. Babel).
440
+ // In this case we'll resort to displaying the provided code frame
441
+ // because we can't be sure the reported location is accurate.
442
+ console.error(error.codeFrame);
443
+ }
444
+}
445
457
- await Packaging.createFacebookWWWBuild();
458
- await Packaging.createReactNativeBuild();
459
- await Packaging.createReactNativeRTBuild();
460
- await Packaging.createReactNativeCSBuild();
446
+async function buildEverything() {
447
+ await asyncRimRaf('build');
448
462
- // Run them serially for better console output
463
- // and to avoid any potential race conditions.
464
- for (const bundle of Bundles.bundles) {
465
- await createBundle(bundle, UMD_DEV);
466
- await createBundle(bundle, UMD_PROD);
467
- await createBundle(bundle, NODE_DEV);
468
- await createBundle(bundle, NODE_PROD);
469
- await createBundle(bundle, FB_DEV);
470
- await createBundle(bundle, FB_PROD);
471
- await createBundle(bundle, RN_DEV);
472
- await createBundle(bundle, RN_PROD);
473
- }
449
+ // Run them serially for better console output
450
+ // and to avoid any potential race conditions.
451
+ for (const bundle of Bundles.bundles) {
452
+ await createBundle(bundle, UMD_DEV);
453
+ await createBundle(bundle, UMD_PROD);
454
+ await createBundle(bundle, NODE_DEV);
455
+ await createBundle(bundle, NODE_PROD);
456
+ await createBundle(bundle, FB_DEV);
457
+ await createBundle(bundle, FB_PROD);
458
+ await createBundle(bundle, RN_DEV);
459
+ await createBundle(bundle, RN_PROD);
460
+ }
461
475
- if (syncFbsource) {
476
- await syncReactNative(path.join('build', 'react-native'), syncFbsource);
477
- await syncReactNativeRT(path.join('build', 'react-rt'), syncFbsource);
478
- await syncReactNativeCS(path.join('build', 'react-cs'), syncFbsource);
479
- } else if (syncWww) {
480
- await syncReactDom(path.join('build', 'facebook-www'), syncWww);
481
- }
462
+ await Packaging.copyAllShims();
463
+ await Packaging.prepareNpmPackages();
464
483
- console.log(Stats.printResults());
484
- // save the results for next run
485
- Stats.saveResults();
486
- if (shouldExtractErrors) {
487
- console.warn(
488
- '\nWarning: this build was created with --extract-errors enabled.\n' +
489
- 'this will result in extremely slow builds and should only be\n' +
490
- 'used when the error map needs to be rebuilt.\n'
491
- );
492
- }
493
- rimraf(npmPackagesTmpDir, err => {
494
- if (err) {
495
- console.error(err);
496
- process.exit(1);
497
- }
498
- });
499
- } catch (err) {
500
- console.error(err);
501
- process.exit(1);
465
+ if (syncFBSourcePath) {
466
+ await Sync.syncReactNative('build/react-native', syncFBSourcePath);
467
+ await Sync.syncReactNativeRT('build/react-rt', syncFBSourcePath);
468
+ await Sync.syncReactNativeCS('build/react-cs', syncFBSourcePath);
469
+ } else if (syncWWWPath) {
470
+ await Sync.syncReactDom('build/facebook-www', syncWWWPath);
471
}
503
-});
472
+
473
+ console.log(Stats.printResults());
474
+ Stats.saveResults();
475
+
476
+ if (shouldExtractErrors) {
477
+ console.warn(
478
+ '\nWarning: this build was created with --extract-errors enabled.\n' +
479
+ 'this will result in extremely slow builds and should only be\n' +
480
+ 'used when the error map needs to be rebuilt.\n'
481
+ );
482
+ }
483
+}
484
+
485
+buildEverything();
scripts/rollup/packaging.js
+121
-182
@@ -1,40 +1,24 @@
1
'use strict';
2
3
-const basename = require('path').basename;
4
-const fs = require('fs');
5
-const join = require('path').join;
6
-const resolve = require('path').resolve;
3
+const {existsSync, readdirSync, unlinkSync} = require('fs');
4
const Bundles = require('./bundles');
8
-const asyncCopyTo = require('./utils').asyncCopyTo;
9
-const asyncExecuteCommand = require('./utils').asyncExecuteCommand;
10
-const asyncExtractTar = require('./utils').asyncExtractTar;
11
-
12
-const UMD_DEV = Bundles.bundleTypes.UMD_DEV;
13
-const UMD_PROD = Bundles.bundleTypes.UMD_PROD;
14
-const NODE_DEV = Bundles.bundleTypes.NODE_DEV;
15
-const NODE_PROD = Bundles.bundleTypes.NODE_PROD;
16
-const FB_DEV = Bundles.bundleTypes.FB_DEV;
17
-const FB_PROD = Bundles.bundleTypes.FB_PROD;
18
-const RN_DEV = Bundles.bundleTypes.RN_DEV;
19
-const RN_PROD = Bundles.bundleTypes.RN_PROD;
20
-
21
-const facebookWWW = 'facebook-www';
22
-
23
-// these files need to be copied to the react-native build
24
-const reactNativeSrcDependencies = [
25
- 'packages/shared/ReactTypes.js',
26
- 'packages/react-native-renderer/src/ReactNativeTypes.js',
27
-];
28
-
29
-// these files need to be copied to the react-rt build
30
-const reactNativeRTSrcDependencies = [
31
- 'packages/react-rt-renderer/src/ReactNativeRTTypes.js',
32
-];
33
-
34
-// these files need to be copied to the react-cs build
35
-const reactNativeCSSrcDependencies = [
36
- 'packages/react-cs-renderer/src/ReactNativeCSTypes.js',
37
-];
5
+const {
6
+ asyncCopyTo,
7
+ asyncExecuteCommand,
8
+ asyncExtractTar,
9
+ asyncRimRaf,
10
+} = require('./utils');
11
+
12
+const {
13
+ UMD_DEV,
14
+ UMD_PROD,
15
+ NODE_DEV,
16
+ NODE_PROD,
17
+ FB_DEV,
18
+ FB_PROD,
19
+ RN_DEV,
20
+ RN_PROD,
21
+} = Bundles.bundleTypes;
22
23
function getPackageName(name) {
24
if (name.indexOf('/') !== -1) {
@@ -43,172 +27,127 @@ function getPackageName(name) {
27
return name;
28
}
29
46
-async function createReactNativeBuild() {
47
- fs.mkdirSync(join('build', 'react-native'));
48
- fs.mkdirSync(join('build', 'react-native', 'shims'));
49
- const from = join('scripts', 'rollup', 'shims', 'react-native');
50
- const to = join('build', 'react-native', 'shims');
51
- await asyncCopyTo(from, to);
52
- await Promise.all(
53
- reactNativeSrcDependencies.map(srcDependency =>
54
- asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
55
- )
56
- );
57
-}
58
-
59
-async function createReactNativeRTBuild() {
60
- fs.mkdirSync(join('build', 'react-rt'));
61
- fs.mkdirSync(join('build', 'react-rt', 'shims'));
62
- const to = join('build', 'react-rt', 'shims');
63
- await Promise.all(
64
- reactNativeRTSrcDependencies.map(srcDependency =>
65
- asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
66
- )
67
- );
30
+function getBundleOutputPaths(bundleType, filename, packageName) {
31
+ switch (bundleType) {
32
+ case NODE_DEV:
33
+ case NODE_PROD:
34
+ return [`build/packages/${packageName}/cjs/${filename}`];
35
+ case UMD_DEV:
36
+ case UMD_PROD:
37
+ return [
38
+ `build/packages/${packageName}/umd/${filename}`,
39
+ `build/dist/${filename}`,
40
+ ];
41
+ case FB_DEV:
42
+ case FB_PROD:
43
+ return [`build/facebook-www/${filename}`];
44
+ case RN_DEV:
45
+ case RN_PROD:
46
+ switch (packageName) {
47
+ case 'react-rt-renderer':
48
+ return [`build/react-rt/${filename}`];
49
+ case 'react-cs-renderer':
50
+ return [`build/react-cs/${filename}`];
51
+ case 'react-native-renderer':
52
+ return [`build/react-native/${filename}`];
53
+ default:
54
+ throw new Error('Unknown RN package.');
55
+ }
56
+ default:
57
+ throw new Error('Unknown bundle type.');
58
+ }
59
}
60
70
-async function createReactNativeCSBuild() {
71
- fs.mkdirSync(join('build', 'react-cs'));
72
- fs.mkdirSync(join('build', 'react-cs', 'shims'));
73
- const to = join('build', 'react-cs', 'shims');
74
- await Promise.all(
75
- reactNativeCSSrcDependencies.map(srcDependency =>
76
- asyncCopyTo(resolve(srcDependency), join(to, basename(srcDependency)))
77
- )
61
+async function copyWWWShims() {
62
+ await asyncCopyTo(
63
+ `${__dirname}/shims/facebook-www`,
64
+ 'build/facebook-www/shims'
65
);
66
}
67
81
-async function createFacebookWWWBuild() {
82
- fs.mkdirSync(join('build', facebookWWW));
83
- fs.mkdirSync(join('build', facebookWWW, 'shims'));
84
- const from = join('scripts', 'rollup', 'shims', facebookWWW);
85
- const to = join('build', facebookWWW, 'shims');
86
- await asyncCopyTo(from, to);
68
+async function copyRNShims() {
69
+ await Promise.all([
70
+ // React Native
71
+ asyncCopyTo(`${__dirname}/shims/react-native`, 'build/react-native/shims'),
72
+ asyncCopyTo(
73
+ require.resolve('shared/ReactTypes.js'),
74
+ 'build/react-native/shims/ReactTypes.js'
75
+ ),
76
+ asyncCopyTo(
77
+ require.resolve('react-native-renderer/src/ReactNativeTypes.js'),
78
+ 'build/react-native/shims/ReactNativeTypes.js'
79
+ ),
80
+ // React Native CS
81
+ asyncCopyTo(
82
+ require.resolve('react-cs-renderer/src/ReactNativeCSTypes.js'),
83
+ 'build/react-cs/shims/ReactNativeCSTypes.js'
84
+ ),
85
+ // React Native RT
86
+ asyncCopyTo(
87
+ require.resolve('react-rt-renderer/src/ReactNativeRTTypes.js'),
88
+ 'build/react-rt/shims/ReactNativeRTTypes.js'
89
+ ),
90
+ ]);
91
}
92
89
-async function copyBundleIntoNodePackage(
90
- packageName,
91
- filename,
92
- bundleType,
93
- npmPackagesTmpDir
94
-) {
95
- const packageDirectory = resolve(`${npmPackagesTmpDir}/${packageName}`);
96
- if (!fs.existsSync(packageDirectory)) {
97
- return;
98
- }
99
- let from = resolve(`./build/${filename}`);
100
- let to = `${packageDirectory}/${filename}`;
101
- // for UMD bundles we have to move the files into a umd directory
102
- // within the package directory. we also need to set the from
103
- // to be the root build from directory
104
- if (bundleType === UMD_DEV || bundleType === UMD_PROD) {
105
- const distDirectory = `${packageDirectory}/umd`;
106
- // create a dist directory if not created
107
- if (!fs.existsSync(distDirectory)) {
108
- fs.mkdirSync(distDirectory);
109
- }
110
- from = resolve(`./build/dist/${filename}`);
111
- to = `${packageDirectory}/umd/${filename}`;
112
- }
113
- // for NODE bundles we have to move the files into a cjs directory
114
- // within the package directory. we also need to set the from
115
- // to be the root build from directory
116
- if (bundleType === NODE_DEV || bundleType === NODE_PROD) {
117
- const distDirectory = `${packageDirectory}/cjs`;
118
- // create a dist directory if not created
119
- if (!fs.existsSync(distDirectory)) {
120
- fs.mkdirSync(distDirectory);
121
- }
122
- to = `${packageDirectory}/cjs/${filename}`;
123
- }
124
- await asyncCopyTo(from, to);
125
- // delete the old file if this is a not a UMD bundle
126
- if (bundleType !== UMD_DEV && bundleType !== UMD_PROD) {
127
- fs.unlinkSync(from);
128
- }
93
+async function copyAllShims() {
94
+ await Promise.all([copyWWWShims(), copyRNShims()]);
95
}
96
131
-async function copyNodePackageTemplate(packageName, npmPackagesTmpDir) {
132
- const from = resolve(`./packages/${packageName}`);
133
- const to = resolve(`${npmPackagesTmpDir}/${packageName}`);
134
- const npmFrom = resolve(`${from}/npm`);
135
- if (!fs.existsSync(npmFrom)) {
136
- // The package is not meant for npm consumption.
137
- return;
138
- }
139
- if (fs.existsSync(to)) {
140
- // We already created this package (e.g. due to another entry point).
141
- return;
142
- }
143
- await asyncCopyTo(npmFrom, to);
144
- await asyncCopyTo(resolve(`${from}/package.json`), `${to}/package.json`);
145
- await asyncCopyTo(resolve(`${from}/README.md`), `${to}/README.md`);
146
- await asyncCopyTo(resolve('./LICENSE'), `${to}/LICENSE`);
97
+function getTarOptions(tgzName, packageName) {
98
+ // Files inside the `npm pack`ed archive start
99
+ // with "package/" in their paths. We'll undo
100
+ // this during extraction.
101
+ const CONTENTS_FOLDER = 'package';
102
+ return {
103
+ src: tgzName,
104
+ dest: `build/packages/${packageName}`,
105
+ tar: {
106
+ entries: [CONTENTS_FOLDER],
107
+ map(header) {
108
+ if (header.name.indexOf(CONTENTS_FOLDER + '/') === 0) {
109
+ header.name = header.name.substring(CONTENTS_FOLDER.length + 1);
110
+ }
111
+ },
112
+ },
113
+ };
114
}
115
149
-async function packForNpmAndUnpack(packageName, npmPackagesTmpDir) {
150
- const packageTmpDir = resolve(`${npmPackagesTmpDir}/${packageName}`);
151
- const extractTmpDir = resolve(`${packageTmpDir}/extract`);
152
- const build = resolve(`./build/packages/${packageName}`);
153
- const npmFrom = resolve(`./packages/${packageName}/npm`);
154
- if (!fs.existsSync(npmFrom)) {
155
- return;
156
- }
157
- let tgzName = await asyncExecuteCommand(`cd ${packageTmpDir} && npm pack`);
158
- // In npm packages, files are grouped into a root directory(named 'package').
159
- // We only copy the packed files instead of extract the root 'package' directly to build directory
160
- await asyncExtractTar({
161
- src: `${packageTmpDir}/${tgzName.trim()}`,
162
- dest: extractTmpDir,
163
- });
164
- await asyncCopyTo(`${extractTmpDir}/package`, build);
116
+async function prepareNpmPackage(name) {
117
+ await Promise.all([
118
+ asyncCopyTo('LICENSE', `build/packages/${name}/LICENSE`),
119
+ asyncCopyTo(
120
+ `packages/${name}/package.json`,
121
+ `build/packages/${name}/package.json`
122
+ ),
123
+ asyncCopyTo(
124
+ `packages/${name}/README.md`,
125
+ `build/packages/${name}/README.md`
126
+ ),
127
+ asyncCopyTo(`packages/${name}/npm`, `build/packages/${name}`),
128
+ ]);
129
+ const tgzName = (await asyncExecuteCommand(
130
+ `npm pack build/packages/${name}`
131
+ )).trim();
132
+ await asyncRimRaf(`build/packages/${name}`);
133
+ await asyncExtractTar(getTarOptions(tgzName, name));
134
+ unlinkSync(tgzName);
135
}
136
167
-async function createNodePackage(
168
- bundleType,
169
- packageName,
170
- filename,
171
- npmPackagesTmpDir
172
-) {
173
- // the only case where we don't want to copy the package is for FB bundles
174
- if (bundleType === FB_DEV || bundleType === FB_PROD) {
137
+async function prepareNpmPackages() {
138
+ if (!existsSync('build/packages')) {
139
+ // We didn't build any npm packages.
140
return;
141
}
177
- await copyNodePackageTemplate(packageName, npmPackagesTmpDir);
178
- await copyBundleIntoNodePackage(
179
- packageName,
180
- filename,
181
- bundleType,
182
- npmPackagesTmpDir
142
+ const builtPackageFolders = readdirSync('build/packages').filter(
143
+ dir => dir.charAt(0) !== '.'
144
);
184
- // Packing packages locally, simulate npm publish,
185
- // Then unpacking generated packages to build directory
186
- await packForNpmAndUnpack(packageName, npmPackagesTmpDir);
187
-}
188
-
189
-function getOutputPathRelativeToBuildFolder(bundleType, filename, hasteName) {
190
- if (bundleType === FB_DEV || bundleType === FB_PROD) {
191
- return `${facebookWWW}/${filename}`;
192
- } else if (bundleType === UMD_DEV || bundleType === UMD_PROD) {
193
- return `dist/${filename}`;
194
- } else if (bundleType === RN_DEV || bundleType === RN_PROD) {
195
- if (hasteName === 'ReactRTRenderer') {
196
- return `react-rt/${filename}`;
197
- } else if (hasteName === 'ReactCSRenderer') {
198
- return `react-cs/${filename}`;
199
- } else {
200
- return `react-native/${filename}`;
201
- }
202
- }
203
- return filename;
145
+ await Promise.all(builtPackageFolders.map(prepareNpmPackage));
146
}
147
148
module.exports = {
207
- getOutputPathRelativeToBuildFolder,
208
- createNodePackage,
149
+ copyAllShims,
150
getPackageName,
210
- createFacebookWWWBuild,
211
- createReactNativeBuild,
212
- createReactNativeRTBuild,
213
- createReactNativeCSBuild,
151
+ getBundleOutputPaths,
152
+ prepareNpmPackages,
153
};
scripts/rollup/utils.js
+64
-35
@@ -1,60 +1,89 @@
1
'use strict';
2
3
const ncp = require('ncp').ncp;
4
-const join = require('path').join;
5
-const resolve = require('path').resolve;
4
+const path = require('path');
5
+const mkdirp = require('mkdirp');
6
+const rimraf = require('rimraf');
7
const exec = require('child_process').exec;
8
const targz = require('targz');
9
10
function asyncCopyTo(from, to) {
10
- return new Promise(_resolve => {
11
- ncp(from, to, error => {
12
- if (error) {
13
- console.error(error);
14
- process.exit(1);
15
- }
16
- _resolve();
17
- });
18
- });
19
-}
20
-
21
-function resolvePath(path) {
22
- if (path[0] === '~') {
23
- return join(process.env.HOME, path.slice(1));
24
- } else {
25
- return resolve(path);
26
- }
11
+ return asyncMkDirP(path.dirname(to)).then(
12
+ () =>
13
+ new Promise((resolve, reject) => {
14
+ ncp(from, to, error => {
15
+ if (error) {
16
+ // Wrap to have a useful stack trace.
17
+ reject(new Error(error));
18
+ return;
19
+ }
20
+ resolve();
21
+ });
22
+ })
23
+ );
24
}
25
26
function asyncExecuteCommand(command) {
30
- return new Promise(_resolve =>
27
+ return new Promise((resolve, reject) =>
28
exec(command, (error, stdout) => {
32
- if (!error) {
33
- _resolve(stdout);
34
- } else {
35
- console.error(error);
36
- process.exit(1);
29
+ if (error) {
30
+ reject(error);
31
+ return;
32
}
33
+ resolve(stdout);
34
})
35
);
36
}
37
38
function asyncExtractTar(options) {
43
- return new Promise(_resolve =>
39
+ return new Promise((resolve, reject) =>
40
targz.decompress(options, error => {
45
- if (!error) {
46
- _resolve();
47
- } else {
48
- console.error(error);
49
- process.exit(1);
41
+ if (error) {
42
+ reject(error);
43
+ return;
44
}
45
+ resolve();
46
})
47
);
48
}
49
50
+function asyncMkDirP(filepath) {
51
+ return new Promise((resolve, reject) =>
52
+ mkdirp(filepath, error => {
53
+ if (error) {
54
+ reject(error);
55
+ return;
56
+ }
57
+ resolve();
58
+ })
59
+ );
60
+}
61
+
62
+function asyncRimRaf(filepath) {
63
+ return new Promise((resolve, reject) =>
64
+ rimraf(filepath, error => {
65
+ if (error) {
66
+ reject(error);
67
+ return;
68
+ }
69
+ resolve();
70
+ })
71
+ );
72
+}
73
+
74
+function resolvePath(filepath) {
75
+ if (filepath[0] === '~') {
76
+ return path.join(process.env.HOME, filepath.slice(1));
77
+ } else {
78
+ return path.resolve(filepath);
79
+ }
80
+}
81
+
82
module.exports = {
56
- asyncCopyTo: asyncCopyTo,
57
- resolvePath: resolvePath,
58
- asyncExecuteCommand: asyncExecuteCommand,
59
- asyncExtractTar: asyncExtractTar,
83
+ asyncCopyTo,
84
+ resolvePath,
85
+ asyncExecuteCommand,
86
+ asyncExtractTar,
87
+ asyncMkDirP,
88
+ asyncRimRaf,
89
};
yarn.lock
-4
@@ -4788,10 +4788,6 @@ uuid@^3.0.0:
4788
version "3.0.1"
4789
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
4790
4791
-uuid@^3.1.0:
4792
- version "3.1.0"
4793
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
4794
-
4791
v8flags@^2.0.10:
4792
version "2.1.1"
4793
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"