Use a separate babel config for the local-cli and the packager
Summary: This separates the babel config of the local-cli and the packager from the one used by the transforms of the packager since it doesn't run in the same environment and the local-cli/packager doesn't require react specific transforms and runs in node 4 so we can also avoid some es2015 transforms that node already supports. I had to move the code in cli.js so it can still run in node 0.12 that doesn't support `const` since it is no longer transformed. **Test plan** Run the local-cli on node 0.12 and there should be a message saying that it requires at least node 4. Run the local-cli on node 4 and 5 and everything should work the same as before. I was also hoping for some perf gains but there was nothing noticeable. I did benchmark the babel-register call and it stayed pretty much the same. As for runtime performance it can help if there are optimisations for es2015 features in node. Closes https://github.com/facebook/react-native/pull/6155 Differential Revision: D3242754 Pulled By: davidaurelio fb-gh-sync-id: 02880c841c10562d5f107e1c975d668e55cc619f fbshipit-source-id: 02880c841c10562d5f107e1c975d668e55cc619f
This commit is contained in:
parent
69d5ddd349
commit
19429f79b2
158
local-cli/cli.js
158
local-cli/cli.js
|
@ -8,164 +8,20 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
// This file must be able to run in node 0.12 without babel so we can show that
|
||||
// it is not supported. This is why the rest of the cli code is in `cliEntry.js`.
|
||||
require('./server/checkNodeVersion')();
|
||||
|
||||
require('../packager/babelRegisterOnly')([
|
||||
/private-cli\/src/,
|
||||
/local-cli/,
|
||||
/react-packager\/src/
|
||||
]);
|
||||
|
||||
var bundle = require('./bundle/bundle');
|
||||
var childProcess = require('child_process');
|
||||
var Config = require('./util/Config');
|
||||
var defaultConfig = require('./default.config');
|
||||
var dependencies = require('./dependencies/dependencies');
|
||||
var generate = require('./generate/generate');
|
||||
var library = require('./library/library');
|
||||
var path = require('path');
|
||||
var Promise = require('promise');
|
||||
var runAndroid = require('./runAndroid/runAndroid');
|
||||
var runIOS = require('./runIOS/runIOS');
|
||||
var server = require('./server/server');
|
||||
var TerminalAdapter = require('yeoman-environment/lib/adapter.js');
|
||||
var yeoman = require('yeoman-environment');
|
||||
var unbundle = require('./bundle/unbundle');
|
||||
var upgrade = require('./upgrade/upgrade');
|
||||
var version = require('./version/version');
|
||||
|
||||
var fs = require('fs');
|
||||
var gracefulFs = require('graceful-fs');
|
||||
|
||||
// graceful-fs helps on getting an error when we run out of file
|
||||
// descriptors. When that happens it will enqueue the operation and retry it.
|
||||
gracefulFs.gracefulify(fs);
|
||||
|
||||
var documentedCommands = {
|
||||
'start': [server, 'starts the webserver'],
|
||||
'bundle': [bundle, 'builds the javascript bundle for offline use'],
|
||||
'unbundle': [unbundle, 'builds javascript as "unbundle" for offline use'],
|
||||
'new-library': [library, 'generates a native library bridge'],
|
||||
'android': [generateWrapper, 'generates an Android project for your app'],
|
||||
'run-android': [runAndroid, 'builds your app and starts it on a connected Android emulator or device'],
|
||||
'run-ios': [runIOS, 'builds your app and starts it on iOS simulator'],
|
||||
'upgrade': [upgrade, 'upgrade your app\'s template files to the latest version; run this after ' +
|
||||
'updating the react-native version in your package.json and running npm install']
|
||||
};
|
||||
|
||||
var exportedCommands = {dependencies: dependencies};
|
||||
Object.keys(documentedCommands).forEach(function(command) {
|
||||
exportedCommands[command] = documentedCommands[command][0];
|
||||
});
|
||||
|
||||
var undocumentedCommands = {
|
||||
'--version': [version, ''],
|
||||
'init': [printInitWarning, ''],
|
||||
};
|
||||
|
||||
var commands = Object.assign({}, documentedCommands, undocumentedCommands);
|
||||
|
||||
/**
|
||||
* Parses the command line and runs a command of the CLI.
|
||||
*/
|
||||
function run() {
|
||||
var args = process.argv.slice(2);
|
||||
if (args.length === 0) {
|
||||
printUsage();
|
||||
}
|
||||
|
||||
var setupEnvScript = /^win/.test(process.platform)
|
||||
? 'setup_env.bat'
|
||||
: 'setup_env.sh';
|
||||
childProcess.execFileSync(path.join(__dirname, setupEnvScript));
|
||||
|
||||
var command = commands[args[0]];
|
||||
if (!command) {
|
||||
console.error('Command `%s` unrecognized', args[0]);
|
||||
printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
command[0](args, Config.get(__dirname, defaultConfig)).done();
|
||||
}
|
||||
|
||||
function generateWrapper(args, config) {
|
||||
return generate([
|
||||
'--platform', 'android',
|
||||
'--project-path', process.cwd(),
|
||||
'--project-name', JSON.parse(
|
||||
fs.readFileSync('package.json', 'utf8')
|
||||
).name
|
||||
], config);
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log([
|
||||
'Usage: react-native <command>',
|
||||
'',
|
||||
'Commands:'
|
||||
].concat(Object.keys(documentedCommands).map(function(name) {
|
||||
return ' - ' + name + ': ' + documentedCommands[name][1];
|
||||
})).join('\n'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// The user should never get here because projects are inited by
|
||||
// using `react-native-cli` from outside a project directory.
|
||||
function printInitWarning() {
|
||||
return Promise.resolve().then(function() {
|
||||
console.log([
|
||||
'Looks like React Native project already exists in the current',
|
||||
'folder. Run this command from a different folder or remove node_modules/react-native'
|
||||
].join('\n'));
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
class CreateSuppressingTerminalAdapter extends TerminalAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
// suppress 'create' output generated by yeoman
|
||||
this.log.create = function() {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the template for a React Native project given the provided
|
||||
* parameters:
|
||||
* - projectDir: templates will be copied here.
|
||||
* - argsOrName: project name or full list of custom arguments to pass to the
|
||||
* generator.
|
||||
*/
|
||||
function init(projectDir, argsOrName) {
|
||||
console.log('Setting up new React Native app in ' + projectDir);
|
||||
var env = yeoman.createEnv(
|
||||
undefined,
|
||||
undefined,
|
||||
new CreateSuppressingTerminalAdapter()
|
||||
);
|
||||
|
||||
env.register(
|
||||
require.resolve(path.join(__dirname, 'generator')),
|
||||
'react:app'
|
||||
);
|
||||
|
||||
// argv is for instance
|
||||
// ['node', 'react-native', 'init', 'AwesomeApp', '--verbose']
|
||||
// args should be ['AwesomeApp', '--verbose']
|
||||
var args = Array.isArray(argsOrName)
|
||||
? argsOrName
|
||||
: [argsOrName].concat(process.argv.slice(4));
|
||||
|
||||
var generator = env.create('react:app', {args: args});
|
||||
generator.destinationRoot(projectDir);
|
||||
generator.run();
|
||||
}
|
||||
var cliEntry = require('./cliEntry');
|
||||
|
||||
if (require.main === module) {
|
||||
run();
|
||||
cliEntry.run();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run: run,
|
||||
init: init,
|
||||
commands: exportedCommands
|
||||
};
|
||||
module.exports = cliEntry;
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const bundle = require('./bundle/bundle');
|
||||
const childProcess = require('child_process');
|
||||
const Config = require('./util/Config');
|
||||
const defaultConfig = require('./default.config');
|
||||
const dependencies = require('./dependencies/dependencies');
|
||||
const generate = require('./generate/generate');
|
||||
const library = require('./library/library');
|
||||
const path = require('path');
|
||||
const Promise = require('promise');
|
||||
const runAndroid = require('./runAndroid/runAndroid');
|
||||
const runIOS = require('./runIOS/runIOS');
|
||||
const server = require('./server/server');
|
||||
const TerminalAdapter = require('yeoman-environment/lib/adapter.js');
|
||||
const yeoman = require('yeoman-environment');
|
||||
const unbundle = require('./bundle/unbundle');
|
||||
const upgrade = require('./upgrade/upgrade');
|
||||
const version = require('./version/version');
|
||||
|
||||
const fs = require('fs');
|
||||
const gracefulFs = require('graceful-fs');
|
||||
|
||||
// graceful-fs helps on getting an error when we run out of file
|
||||
// descriptors. When that happens it will enqueue the operation and retry it.
|
||||
gracefulFs.gracefulify(fs);
|
||||
|
||||
const documentedCommands = {
|
||||
'start': [server, 'starts the webserver'],
|
||||
'bundle': [bundle, 'builds the javascript bundle for offline use'],
|
||||
'unbundle': [unbundle, 'builds javascript as "unbundle" for offline use'],
|
||||
'new-library': [library, 'generates a native library bridge'],
|
||||
'android': [generateWrapper, 'generates an Android project for your app'],
|
||||
'run-android': [runAndroid, 'builds your app and starts it on a connected Android emulator or device'],
|
||||
'run-ios': [runIOS, 'builds your app and starts it on iOS simulator'],
|
||||
'upgrade': [upgrade, 'upgrade your app\'s template files to the latest version; run this after ' +
|
||||
'updating the react-native version in your package.json and running npm install']
|
||||
};
|
||||
|
||||
const exportedCommands = {dependencies: dependencies};
|
||||
Object.keys(documentedCommands).forEach(function(command) {
|
||||
exportedCommands[command] = documentedCommands[command][0];
|
||||
});
|
||||
|
||||
const undocumentedCommands = {
|
||||
'--version': [version, ''],
|
||||
'init': [printInitWarning, ''],
|
||||
};
|
||||
|
||||
const commands = Object.assign({}, documentedCommands, undocumentedCommands);
|
||||
|
||||
/**
|
||||
* Parses the command line and runs a command of the CLI.
|
||||
*/
|
||||
function run() {
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length === 0) {
|
||||
printUsage();
|
||||
}
|
||||
|
||||
const setupEnvScript = /^win/.test(process.platform)
|
||||
? 'setup_env.bat'
|
||||
: 'setup_env.sh';
|
||||
childProcess.execFileSync(path.join(__dirname, setupEnvScript));
|
||||
|
||||
const command = commands[args[0]];
|
||||
if (!command) {
|
||||
console.error('Command `%s` unrecognized', args[0]);
|
||||
printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
command[0](args, Config.get(__dirname, defaultConfig)).done();
|
||||
}
|
||||
|
||||
function generateWrapper(args, config) {
|
||||
return generate([
|
||||
'--platform', 'android',
|
||||
'--project-path', process.cwd(),
|
||||
'--project-name', JSON.parse(
|
||||
fs.readFileSync('package.json', 'utf8')
|
||||
).name
|
||||
], config);
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log([
|
||||
'Usage: react-native <command>',
|
||||
'',
|
||||
'Commands:'
|
||||
].concat(Object.keys(documentedCommands).map(function(name) {
|
||||
return ' - ' + name + ': ' + documentedCommands[name][1];
|
||||
})).join('\n'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// The user should never get here because projects are inited by
|
||||
// using `react-native-cli` from outside a project directory.
|
||||
function printInitWarning() {
|
||||
return Promise.resolve().then(function() {
|
||||
console.log([
|
||||
'Looks like React Native project already exists in the current',
|
||||
'folder. Run this command from a different folder or remove node_modules/react-native'
|
||||
].join('\n'));
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
class CreateSuppressingTerminalAdapter extends TerminalAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
// suppress 'create' output generated by yeoman
|
||||
this.log.create = function() {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the template for a React Native project given the provided
|
||||
* parameters:
|
||||
* - projectDir: templates will be copied here.
|
||||
* - argsOrName: project name or full list of custom arguments to pass to the
|
||||
* generator.
|
||||
*/
|
||||
function init(projectDir, argsOrName) {
|
||||
console.log('Setting up new React Native app in ' + projectDir);
|
||||
const env = yeoman.createEnv(
|
||||
undefined,
|
||||
undefined,
|
||||
new CreateSuppressingTerminalAdapter()
|
||||
);
|
||||
|
||||
env.register(
|
||||
require.resolve(path.join(__dirname, 'generator')),
|
||||
'react:app'
|
||||
);
|
||||
|
||||
// argv is for instance
|
||||
// ['node', 'react-native', 'init', 'AwesomeApp', '--verbose']
|
||||
// args should be ['AwesomeApp', '--verbose']
|
||||
const args = Array.isArray(argsOrName)
|
||||
? argsOrName
|
||||
: [argsOrName].concat(process.argv.slice(4));
|
||||
|
||||
const generator = env.create('react:app', {args: args});
|
||||
generator.destinationRoot(projectDir);
|
||||
generator.run();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run: run,
|
||||
init: init,
|
||||
commands: exportedCommands
|
||||
};
|
|
@ -8,17 +8,17 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
const chalk = require('chalk');
|
||||
const formatBanner = require('./formatBanner');
|
||||
const semver = require('semver');
|
||||
var chalk = require('chalk');
|
||||
var formatBanner = require('./formatBanner');
|
||||
var semver = require('semver');
|
||||
|
||||
module.exports = function() {
|
||||
if (!semver.satisfies(process.version, '>=4')) {
|
||||
const engine = semver.satisfies(process.version, '<1 >=4')
|
||||
var engine = semver.satisfies(process.version, '<1')
|
||||
? 'Node'
|
||||
: 'io.js';
|
||||
|
||||
const message = 'You are currently running ' + engine + ' ' +
|
||||
var message = 'You are currently running ' + engine + ' ' +
|
||||
process.version + '.\n' +
|
||||
'\n' +
|
||||
'React Native runs on Node 4.0 or newer. There are several ways to ' +
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
'use strict';
|
||||
|
||||
const chalk = require('chalk');
|
||||
const checkNodeVersion = require('./checkNodeVersion');
|
||||
const formatBanner = require('./formatBanner');
|
||||
const parseCommandLine = require('../util/parseCommandLine');
|
||||
const path = require('path');
|
||||
|
@ -88,8 +87,6 @@ function _server(argv, config, resolve, reject) {
|
|||
)
|
||||
: config.getAssetRoots();
|
||||
|
||||
checkNodeVersion();
|
||||
|
||||
console.log(formatBanner(
|
||||
'Running packager on port ' + args.port + '.\n\n' +
|
||||
'Keep this packager running while developing on any JS projects. ' +
|
||||
|
|
|
@ -131,7 +131,11 @@
|
|||
"art": "^0.10.0",
|
||||
"babel-core": "^6.6.4",
|
||||
"babel-plugin-external-helpers": "^6.5.0",
|
||||
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
|
||||
"babel-plugin-transform-flow-strip-types": "^6.6.5",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.6.5",
|
||||
"babel-polyfill": "^6.6.1",
|
||||
"babel-preset-es2015-node": "^4.0.2",
|
||||
"babel-preset-react-native": "~1.6.0",
|
||||
"babel-register": "^6.6.0",
|
||||
"babel-types": "^6.6.4",
|
||||
|
|
|
@ -12,20 +12,19 @@ Array.prototype.values || require('core-js/fn/array/values');
|
|||
Object.entries || require('core-js/fn/object/entries');
|
||||
Object.values || require('core-js/fn/object/values');
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var _only = [];
|
||||
|
||||
function readBabelRC() {
|
||||
var rcpath = path.join(__dirname, 'react-packager', 'rn-babelrc.json');
|
||||
var source = fs.readFileSync(rcpath).toString();
|
||||
return JSON.parse(source);
|
||||
}
|
||||
|
||||
module.exports = function(onlyList) {
|
||||
_only = _only.concat(onlyList);
|
||||
var config = readBabelRC();
|
||||
config.only = _only;
|
||||
require('babel-register')(config);
|
||||
|
||||
require('babel-register')({
|
||||
presets: ['es2015-node'],
|
||||
plugins: [
|
||||
'transform-flow-strip-types',
|
||||
'syntax-trailing-function-commas',
|
||||
'transform-object-rest-spread',
|
||||
],
|
||||
only: _only,
|
||||
sourceMaps: 'inline',
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue