Commit a82896c3 authored by Jirat Ki's avatar Jirat Ki Committed by Joe Haddad
Browse files

Install react, react-dom, and react-scripts at the same time (#1253)

* Install react and react-dom along with react-scripts

- Install react, react-dom and react-script in a same time
- Move react-scripts to devDependencies.

* Check if react, react-dom has been already installed

- To backward compatibility with old CRA’s cli
- In case old CRA doesn’t install react, react-don along with
react-scripts

* Use packageName to find script dependency

- use packageName to find dependency
- fix pathExists.sync

* Check dependencies.react in package.json instead of actual files

* Process exit when dependencies not found

- Show error and exit when dependencies not found.
- Log install show custom package name

* Remove template string

* Install dependencies if template is preseted

* Remove dangling comma

Resolves #1239
parent d9453703
Showing with 97 additions and 54 deletions
+97 -54
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
var chalk = require('chalk'); var chalk = require('chalk');
var currentNodeVersion = process.versions.node var currentNodeVersion = process.versions.node;
if (currentNodeVersion.split('.')[0] < 4) { if (currentNodeVersion.split('.')[0] < 4) {
console.error( console.error(
chalk.red( chalk.red(
...@@ -124,7 +124,7 @@ function createApp(name, verbose, version, template) { ...@@ -124,7 +124,7 @@ function createApp(name, verbose, version, template) {
var packageJson = { var packageJson = {
name: appName, name: appName,
version: '0.1.0', version: '0.1.0',
private: true, private: true
}; };
fs.writeFileSync( fs.writeFileSync(
path.join(root, 'package.json'), path.join(root, 'package.json'),
...@@ -133,10 +133,6 @@ function createApp(name, verbose, version, template) { ...@@ -133,10 +133,6 @@ function createApp(name, verbose, version, template) {
var originalDirectory = process.cwd(); var originalDirectory = process.cwd();
process.chdir(root); process.chdir(root);
console.log('Installing packages. This might take a couple minutes.');
console.log('Installing ' + chalk.cyan('react-scripts') + '...');
console.log();
run(root, appName, version, verbose, originalDirectory, template); run(root, appName, version, verbose, originalDirectory, template);
} }
...@@ -149,15 +145,15 @@ function shouldUseYarn() { ...@@ -149,15 +145,15 @@ function shouldUseYarn() {
} }
} }
function install(packageToInstall, verbose, callback) { function install(dependencies, verbose, callback) {
var command; var command;
var args; var args;
if (shouldUseYarn()) { if (shouldUseYarn()) {
command = 'yarnpkg'; command = 'yarnpkg';
args = [ 'add', '--dev', '--exact', packageToInstall]; args = [ 'add', '--exact'].concat(dependencies);
} else { } else {
command = 'npm'; command = 'npm';
args = ['install', '--save-dev', '--save-exact', packageToInstall]; args = ['install', '--save', '--save-exact'].concat(dependencies);
} }
if (verbose) { if (verbose) {
...@@ -174,7 +170,13 @@ function run(root, appName, version, verbose, originalDirectory, template) { ...@@ -174,7 +170,13 @@ function run(root, appName, version, verbose, originalDirectory, template) {
var packageToInstall = getInstallPackage(version); var packageToInstall = getInstallPackage(version);
var packageName = getPackageName(packageToInstall); var packageName = getPackageName(packageToInstall);
install(packageToInstall, verbose, function(code, command, args) { var allDependencies = ['react', 'react-dom', packageToInstall];
console.log('Installing packages. This might take a couple minutes.');
console.log('Installing ' + chalk.cyan('react, react-dom, ' + packageName) + '...');
console.log();
install(allDependencies, verbose, function(code, command, args) {
if (code !== 0) { if (code !== 0) {
console.error(chalk.cyan(command + ' ' + args.join(' ')) + ' failed'); console.error(chalk.cyan(command + ' ' + args.join(' ')) + ' failed');
process.exit(1); process.exit(1);
...@@ -182,6 +184,10 @@ function run(root, appName, version, verbose, originalDirectory, template) { ...@@ -182,6 +184,10 @@ function run(root, appName, version, verbose, originalDirectory, template) {
checkNodeVersion(packageName); checkNodeVersion(packageName);
// Since react-scripts has been installed with --save
// We need to move it into devDependencies and rewrite package.json
moveReactScriptsToDev(packageName);
var scriptsPath = path.resolve( var scriptsPath = path.resolve(
process.cwd(), process.cwd(),
'node_modules', 'node_modules',
...@@ -273,6 +279,33 @@ function checkAppName(appName) { ...@@ -273,6 +279,33 @@ function checkAppName(appName) {
} }
} }
function moveReactScriptsToDev(packageName) {
var packagePath = path.join(process.cwd(), 'package.json');
var packageJson = require(packagePath);
if (typeof packageJson.dependencies === 'undefined') {
console.error(
chalk.red('Missing dependencies in package.json')
);
process.exit(1);
}
var packageVersion = packageJson.dependencies[packageName];
if (typeof packageVersion === 'undefined') {
console.error(
chalk.red('Unable to find ' + packageName + ' in package.json')
);
process.exit(1);
}
packageJson.devDependencies = packageJson.devDependencies || {};
packageJson.devDependencies[packageName] = packageVersion;
delete packageJson.dependencies[packageName];
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
}
// If project only contains files generated by GH, it’s safe. // If project only contains files generated by GH, it’s safe.
// We also special case IJ-based products .idea because it integrates with CRA: // We also special case IJ-based products .idea because it integrates with CRA:
// https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-243446094 // https://github.com/facebookincubator/create-react-app/pull/368#issuecomment-243446094
......
...@@ -64,8 +64,6 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template ...@@ -64,8 +64,6 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template
} }
}); });
// Run yarn or npm for react and react-dom
// TODO: having to do two npm/yarn installs is bad, can we avoid it?
var command; var command;
var args; var args;
...@@ -92,53 +90,65 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template ...@@ -92,53 +90,65 @@ module.exports = function(appPath, appName, verbose, originalDirectory, template
fs.unlinkSync(templateDependenciesPath); fs.unlinkSync(templateDependenciesPath);
} }
console.log('Installing react and react-dom using ' + command + '...'); // Install react and react-dom for backward compatibility with old CRA cli
console.log(); // which doesn't install react and react-dom along with react-scripts
// or template is presetend (via --internal-testing-template)
if (!isReactInstalled(appPackage) || template) {
console.log('Installing react and react-dom using ' + command + '...');
console.log();
var proc = spawn(command, args, {stdio: 'inherit'}); var proc = spawn.sync(command, args, {stdio: 'inherit'});
proc.on('close', function (code) { if (proc.status !== 0) {
if (code !== 0) {
console.error('`' + command + ' ' + args.join(' ') + '` failed'); console.error('`' + command + ' ' + args.join(' ') + '` failed');
return; return;
} }
}
// Display the most elegant way to cd. // Display the most elegant way to cd.
// This needs to handle an undefined originalDirectory for // This needs to handle an undefined originalDirectory for
// backward compatibility with old global-cli's. // backward compatibility with old global-cli's.
var cdpath; var cdpath;
if (originalDirectory && if (originalDirectory &&
path.join(originalDirectory, appName) === appPath) { path.join(originalDirectory, appName) === appPath) {
cdpath = appName; cdpath = appName;
} else { } else {
cdpath = appPath; cdpath = appPath;
} }
console.log();
console.log('Success! Created ' + appName + ' at ' + appPath);
console.log('Inside that directory, you can run several commands:');
console.log();
console.log(chalk.cyan(' ' + command + ' start'));
console.log(' Starts the development server.');
console.log();
console.log(chalk.cyan(' ' + command + ' run build'));
console.log(' Bundles the app into static files for production.');
console.log();
console.log(chalk.cyan(' ' + command + ' test'));
console.log(' Starts the test runner.');
console.log();
console.log(chalk.cyan(' ' + command + ' run eject'));
console.log(' Removes this tool and copies build dependencies, configuration files');
console.log(' and scripts into the app directory. If you do this, you can’t go back!');
console.log();
console.log('We suggest that you begin by typing:');
console.log();
console.log(chalk.cyan(' cd'), cdpath);
console.log(' ' + chalk.cyan(command + ' start'));
if (readmeExists) {
console.log(); console.log();
console.log('Success! Created ' + appName + ' at ' + appPath); console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`'));
console.log('Inside that directory, you can run several commands:'); }
console.log(); console.log();
console.log(chalk.cyan(' ' + command + ' start')); console.log('Happy hacking!');
console.log(' Starts the development server.');
console.log();
console.log(chalk.cyan(' ' + command + ' run build'));
console.log(' Bundles the app into static files for production.');
console.log();
console.log(chalk.cyan(' ' + command + ' test'));
console.log(' Starts the test runner.');
console.log();
console.log(chalk.cyan(' ' + command + ' run eject'));
console.log(' Removes this tool and copies build dependencies, configuration files');
console.log(' and scripts into the app directory. If you do this, you can’t go back!');
console.log();
console.log('We suggest that you begin by typing:');
console.log();
console.log(chalk.cyan(' cd'), cdpath);
console.log(' ' + chalk.cyan(command + ' start'));
if (readmeExists) {
console.log();
console.log(chalk.yellow('You had a `README.md` file, we renamed it to `README.old.md`'));
}
console.log();
console.log('Happy hacking!');
});
}; };
function isReactInstalled(appPackage) {
var dependencies = appPackage.dependencies || {};
return (
typeof dependencies.react !== 'undefined' &&
typeof dependencies['react-dom'] !== 'undefined'
)
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment