mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-04-28 09:25:42 +08:00
Support Yarn (#898)
In the `create-react-app` command, try to install packages using Yarn. If Yarn is not installed, use npm instead. In `react-scripts`, detect if the project is using Yarn by checking if a `yarn.lock` file exists. If the project is using Yarn, display all the instructions with Yarn commands and use Yarn to install packages in `init` and `eject` scripts.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
3
packages/react-scripts/config/paths.js
vendored
3
packages/react-scripts/config/paths.js
vendored
@@ -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'),
|
||||
@@ -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:
|
||||
@@ -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'),
|
||||
|
||||
17
packages/react-scripts/scripts/build.js
vendored
17
packages/react-scripts/scripts/build.js
vendored
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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"
|
||||
@@ -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();
|
||||
|
||||
14
packages/react-scripts/scripts/eject.js
vendored
14
packages/react-scripts/scripts/eject.js
vendored
@@ -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;
|
||||
@@ -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();
|
||||
|
||||
|
||||
45
packages/react-scripts/scripts/init.js
vendored
45
packages/react-scripts/scripts/init.js
vendored
@@ -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 || {};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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`'));
|
||||
|
||||
6
packages/react-scripts/scripts/start.js
vendored
6
packages/react-scripts/scripts/start.js
vendored
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user