Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Yarn #898

Merged
merged 2 commits into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ cache:
- packages/create-react-app/node_modules
- packages/react-scripts/node_modules
script: tasks/e2e.sh
env:
- USE_YARN=no
- USE_YARN=yes
52 changes: 40 additions & 12 deletions packages/create-react-app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,26 +101,54 @@ function createApp(name, verbose, version) {
process.chdir(root);

console.log('Installing packages. This might take a couple minutes.');
console.log('Installing react-scripts from npm...');
console.log('Installing react-scripts...');
console.log();

run(root, appName, version, verbose, originalDirectory);
}

function run(root, appName, version, verbose, originalDirectory) {
var installPackage = getInstallPackage(version);
var packageName = getPackageName(installPackage);
function install(packageToInstall, verbose, callback) {
var args = [
'install',
verbose && '--verbose',
'--save-dev',
'--save-exact',
installPackage,
].filter(function(e) { return e; });
var proc = spawn('npm', args, {stdio: 'inherit'});
'add',
'--dev',
'--exact',
packageToInstall,
];
var proc = spawn('yarn', args, {stdio: 'inherit'});

var yarnExists = true;
proc.on('error', function (err) {
if (err.code === 'ENOENT') {
yarnExists = false;
}
});
proc.on('close', function (code) {
if (yarnExists) {
callback(code, 'yarn', args);
return;
}
// No Yarn installed, continuing with npm.
args = [
'install',
verbose && '--verbose',
'--save-dev',
'--save-exact',
packageToInstall,
].filter(function(e) { return e; });
var npmProc = spawn('npm', args, {stdio: 'inherit'});
npmProc.on('close', function (code) {
callback(code, 'npm', args);
});
});
}

function run(root, appName, version, verbose, originalDirectory) {
var packageToInstall = getInstallPackage(version);
var packageName = getPackageName(packageToInstall);

install(packageToInstall, verbose, function (code, command, args) {
if (code !== 0) {
console.error('`npm ' + args.join(' ') + '` failed');
console.error('`' + command + ' ' + args.join(' ') + '` failed');
return;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/react-scripts/config/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = {
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
ownNodeModules: resolveApp('node_modules'),
Expand All @@ -62,6 +63,7 @@ module.exports = {
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
// this is empty with npm3 but node resolution searches higher anyway:
Expand All @@ -79,6 +81,7 @@ if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1)
appIndexJs: resolveOwn('../template/src/index.js'),
appPackageJson: resolveOwn('../package.json'),
appSrc: resolveOwn('../template/src'),
yarnLockFile: resolveOwn('../template/yarn.lock'),
testsSetup: resolveOwn('../template/src/setupTests.js'),
appNodeModules: resolveOwn('../node_modules'),
ownNodeModules: resolveOwn('../node_modules'),
Expand Down
17 changes: 14 additions & 3 deletions packages/react-scripts/scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require('dotenv').config({silent: true});
var chalk = require('chalk');
var fs = require('fs-extra');
var path = require('path');
var pathExists = require('path-exists');
var filesize = require('filesize');
var gzipSize = require('gzip-size').sync;
var rimrafSync = require('rimraf').sync;
Expand All @@ -31,6 +32,8 @@ var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
var recursive = require('recursive-readdir');
var stripAnsi = require('strip-ansi');

var useYarn = pathExists.sync(paths.yarnLockFile);

// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
Expand Down Expand Up @@ -161,7 +164,11 @@ function build(previousSizeMap) {
console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
console.log('To publish it at ' + chalk.green(homepagePath) + ', run:');
console.log();
console.log(' ' + chalk.cyan('npm') + ' install --save-dev gh-pages');
if (useYarn) {
console.log(' ' + chalk.cyan('yarn') + ' add gh-pages');
} else {
console.log(' ' + chalk.cyan('npm') + ' install --save-dev gh-pages');
}
console.log();
console.log('Add the following script in your ' + chalk.cyan('package.json') + '.');
console.log();
Expand All @@ -173,7 +180,7 @@ function build(previousSizeMap) {
console.log();
console.log('Then run:');
console.log();
console.log(' ' + chalk.cyan('npm') + ' run deploy');
console.log(' ' + chalk.cyan(useYarn ? 'yarn' : 'npm') + ' run deploy');
console.log();
} else if (publicPath !== '/') {
// "homepage": "http://mywebsite.com/project"
Expand All @@ -200,7 +207,11 @@ function build(previousSizeMap) {
console.log('The ' + chalk.cyan('build') + ' folder is ready to be deployed.');
console.log('You may also serve it locally with a static server:')
console.log();
console.log(' ' + chalk.cyan('npm') + ' install -g pushstate-server');
if (useYarn) {
console.log(' ' + chalk.cyan('yarn') + ' global add pushstate-server');
} else {
console.log(' ' + chalk.cyan('npm') + ' install -g pushstate-server');
}
console.log(' ' + chalk.cyan('pushstate-server') + ' build');
console.log(' ' + chalk.cyan(openCommand) + ' http://localhost:9000');
console.log();
Expand Down
14 changes: 11 additions & 3 deletions packages/react-scripts/scripts/eject.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
var createJestConfig = require('../utils/createJestConfig');
var fs = require('fs');
var path = require('path');
var pathExists = require('path-exists');
var paths = require('../config/paths');
var prompt = require('react-dev-utils/prompt');
var rimrafSync = require('rimraf').sync;
var spawnSync = require('cross-spawn').sync;
Expand Down Expand Up @@ -143,9 +145,15 @@ prompt(
);
console.log();

console.log(cyan('Running npm install...'));
rimrafSync(ownPath);
spawnSync('npm', ['install'], {stdio: 'inherit'});
if (pathExists.sync(paths.yarnLockFile)) {
console.log(cyan('Running yarn...'));
rimrafSync(ownPath);
spawnSync('yarn', [], {stdio: 'inherit'});
} else {
console.log(cyan('Running npm install...'));
rimrafSync(ownPath);
spawnSync('npm', ['install'], {stdio: 'inherit'});
}
console.log(green('Ejected successfully!'));
console.log();

Expand Down
45 changes: 28 additions & 17 deletions packages/react-scripts/scripts/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name;
var ownPath = path.join(appPath, 'node_modules', ownPackageName);
var appPackage = require(path.join(appPath, 'package.json'));
var useYarn = pathExists.sync(path.join(appPath, 'yarn.lock'));

// Copy over some of the devDependencies
appPackage.dependencies = appPackage.dependencies || {};
Expand Down Expand Up @@ -58,21 +59,31 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
}
});

// Run another npm install for react and react-dom
console.log('Installing react and react-dom from npm...');
// 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 args;

if (useYarn) {
command = 'yarn';
args = ['add'];
} else {
command = 'npm';
args = [
'install',
'--save',
verbose && '--verbose'
].filter(function(e) { return e; });
}
args.push('react', 'react-dom');

console.log('Installing react and react-dom using ' + command + '...');
console.log();
// TODO: having to do two npm installs is bad, can we avoid it?
var args = [
'install',
'react',
'react-dom',
'--save',
verbose && '--verbose'
].filter(function(e) { return e; });
var proc = spawn('npm', args, {stdio: 'inherit'});

var proc = spawn(command, args, {stdio: 'inherit'});
proc.on('close', function (code) {
if (code !== 0) {
console.error('`npm ' + args.join(' ') + '` failed');
console.error('`' + command + ' ' + args.join(' ') + '` failed');
return;
}

Expand All @@ -91,23 +102,23 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
console.log('Success! Created ' + appName + ' at ' + appPath);
console.log('Inside that directory, you can run several commands:');
console.log();
console.log(chalk.cyan(' npm start'));
console.log(chalk.cyan(' ' + command + ' start'));
console.log(' Starts the development server.');
console.log();
console.log(chalk.cyan(' npm run build'));
console.log(chalk.cyan(' ' + command + ' run build'));
console.log(' Bundles the app into static files for production.');
console.log();
console.log(chalk.cyan(' npm test'));
console.log(chalk.cyan(' ' + command + ' test'));
console.log(' Starts the test runner.');
console.log();
console.log(chalk.cyan(' npm run eject'));
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('npm start'));
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`'));
Expand Down
6 changes: 5 additions & 1 deletion packages/react-scripts/scripts/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
var openBrowser = require('react-dev-utils/openBrowser');
var prompt = require('react-dev-utils/prompt');
var pathExists = require('path-exists');
var config = require('../config/webpack.config.dev');
var paths = require('../config/paths');

var useYarn = pathExists.sync(paths.yarnLockFile);
var cli = useYarn ? 'yarn' : 'npm';

// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
Expand Down Expand Up @@ -85,7 +89,7 @@ function setupCompiler(host, port, protocol) {
console.log(' ' + chalk.cyan(protocol + '://' + host + ':' + port + '/'));
console.log();
console.log('Note that the development build is not optimized.');
console.log('To create a production build, use ' + chalk.cyan('npm run build') + '.');
console.log('To create a production build, use ' + chalk.cyan(cli + ' run build') + '.');
console.log();
}

Expand Down
6 changes: 6 additions & 0 deletions tasks/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ set -x
cd ..
root_path=$PWD

if [ "$USE_YARN" = "yes" ]
then
# Install Yarn so that the test can use it to install packages.
npm install -g yarn
fi

npm install

# Lint own code
Expand Down