Skip to content

Commit

Permalink
Use env var to detect yarn or npm as the package manager (#11322)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys authored Sep 1, 2021
1 parent ece4dbf commit 04482a6
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 53 deletions.
8 changes: 4 additions & 4 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
# ******************************************************************************
# Installs test suite
# ******************************************************************************
# - template: azure-pipelines-test-job.yml
# parameters:
# name: Installs
# testScript: tasks/e2e-installs.sh
- template: azure-pipelines-test-job.yml
parameters:
name: Installs
testScript: tasks/e2e-installs.sh

# ******************************************************************************
# Kitchensink test suite
Expand Down
7 changes: 5 additions & 2 deletions docusaurus/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ If you already have a project and would like to add TypeScript, see our [Adding

### Selecting a package manager

When you create a new app, the CLI will use [Yarn](https://yarnpkg.com/) to install dependencies (when available). If you have Yarn installed, but would prefer to use npm, you can append `--use-npm` to the creation command. For example:
When you create a new app, the CLI will use [npm](https://docs.npmjs.com) or [Yarn](https://yarnpkg.com/) to install dependencies, depending on which tool you use to run `create-react-app`. For example:

```sh
npx create-react-app my-app --use-npm
# Run this to use npm
npx create-react-app my-app
# Or run this to use yarn
yarn create react-app my-app
```

## Output
Expand Down
20 changes: 7 additions & 13 deletions packages/create-react-app/createReactApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ const validateProjectName = require('validate-npm-package-name');

const packageJson = require('./package.json');

function isUsingYarn() {
return (process.env.npm_config_user_agent || '').indexOf('yarn') === 0;
}

let projectName;

function init() {
Expand All @@ -69,7 +73,6 @@ function init() {
'--template <path-to-template>',
'specify a template for the created project'
)
.option('--use-npm')
.option('--use-pnp')
.allowUnknownOption()
.on('--help', () => {
Expand Down Expand Up @@ -223,19 +226,20 @@ function init() {
console.log();
process.exit(1);
} else {
const useYarn = isUsingYarn();
createApp(
projectName,
program.verbose,
program.scriptsVersion,
program.template,
program.useNpm,
useYarn,
program.usePnp
);
}
});
}

function createApp(name, verbose, version, template, useNpm, usePnp) {
function createApp(name, verbose, version, template, useYarn, usePnp) {
const unsupportedNodeVersion = !semver.satisfies(
// Coerce strings with metadata (i.e. `15.0.0-nightly`).
semver.coerce(process.version),
Expand Down Expand Up @@ -276,7 +280,6 @@ function createApp(name, verbose, version, template, useNpm, usePnp) {
JSON.stringify(packageJson, null, 2) + os.EOL
);

const useYarn = useNpm ? false : shouldUseYarn();
const originalDirectory = process.cwd();
process.chdir(root);
if (!useYarn && !checkThatNpmCanReadCwd()) {
Expand Down Expand Up @@ -351,15 +354,6 @@ function createApp(name, verbose, version, template, useNpm, usePnp) {
);
}

function shouldUseYarn() {
try {
execSync('yarnpkg --version', { stdio: 'ignore' });
return true;
} catch (e) {
return false;
}
}

function install(root, useYarn, usePnp, dependencies, verbose, isOnline) {
return new Promise((resolve, reject) => {
let command;
Expand Down
26 changes: 12 additions & 14 deletions tasks/e2e-installs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ cd "$temp_app_path"
npx create-react-app test-app-dist-tag --scripts-version=@latest
cd test-app-dist-tag

# Check corresponding scripts version is installed and no TypeScript is present.
# Check corresponding scripts version is installed and no TypeScript or yarn is present by default
exists node_modules/react-scripts
! exists node_modules/typescript
! exists src/index.tsx
! exists yarn.lock
exists src/index.js
checkDependencies

Expand All @@ -133,16 +134,16 @@ grep '"version": "1.0.17"' node_modules/react-scripts/package.json
checkDependencies

# ******************************************************************************
# Test --use-npm flag
# Test yarn create
# ******************************************************************************

cd "$temp_app_path"
npx create-react-app test-use-npm-flag --use-npm --scripts-version=1.0.17
cd test-use-npm-flag
yarn create react-app test-use-yarn-create --scripts-version=1.0.17
cd test-use-yarn-create

# Check corresponding scripts version is installed.
exists node_modules/react-scripts
[ ! -e "yarn.lock" ] && echo "yarn.lock correctly does not exist"
exists yarn.lock
grep '"version": "1.0.17"' node_modules/react-scripts/package.json
checkDependencies

Expand Down Expand Up @@ -172,10 +173,6 @@ CI=true npm test
# Eject...
echo yes | npm run eject

# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099
rm yarn.lock
yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self

# Ensure env file still exists
exists src/react-app-env.d.ts

Expand Down Expand Up @@ -230,8 +227,8 @@ echo '## Hello' > ./test-app-should-remain/README.md
npx create-react-app test-app-should-remain --scripts-version=`date +%s` || true
# confirm the file exist
test -e test-app-should-remain/README.md
# confirm only README.md and error log are the only files in the directory
if [ "$(ls -1 ./test-app-should-remain | wc -l | tr -d '[:space:]')" != "2" ]; then
# confirm only README.md is the only file in the directory
if [ "$(ls -1 ./test-app-should-remain | wc -l | tr -d '[:space:]')" != "1" ]; then
false
fi

Expand Down Expand Up @@ -277,12 +274,13 @@ npm start -- --smoke-test
# Test when PnP is enabled
# ******************************************************************************
cd "$temp_app_path"
npx create-react-app test-app-pnp --use-pnp
yarn create react-app test-app-pnp --use-pnp
cd test-app-pnp
! exists node_modules
exists .pnp.js
npm start -- --smoke-test
npm run build
# TODO: start and build tasks error with --use-pnp
# npm start -- --smoke-test
# npm run build

# Cleanup
cleanup
4 changes: 0 additions & 4 deletions tasks/e2e-kitchensink-eject.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ export BROWSERSLIST='ie 9'
# Eject...
echo yes | npm run eject

# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099
rm yarn.lock
yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self

# Test the build
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
NODE_PATH=src \
Expand Down
4 changes: 0 additions & 4 deletions tasks/e2e-simple.sh
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,6 @@ verify_module_scope
# Eject...
echo yes | npm run eject

# Temporary workaround for https://github.com/facebook/create-react-app/issues/6099
rm yarn.lock
yarn add @babel/plugin-transform-react-jsx-source @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self

# Test ejected files were staged
test -n "$(git diff --staged --name-only)"

Expand Down
32 changes: 20 additions & 12 deletions test/integration/create-react-app/index.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const execa = require('execa');
const { mkdirp, remove, writeFileSync } = require('fs-extra');
const { mkdirp, remove, writeFileSync, existsSync } = require('fs-extra');
const { join } = require('path');

const cli = require.resolve('create-react-app/index.js');
Expand All @@ -11,13 +11,20 @@ jest.setTimeout(1000 * 60 * 5);
const projectName = 'test-app';
const genPath = join(__dirname, projectName);

const generatedFiles = ['.gitignore', 'package.json', 'src', 'yarn.lock'];
const generatedFiles = [
'.gitignore',
'package.json',
'src',
'package-lock.json',
];

beforeEach(() => remove(genPath));
afterAll(() => remove(genPath));

const run = (args, options) => execa('node', [cli].concat(args), options);

const genFileExists = f => existsSync(join(genPath, f));

describe('create-react-app', () => {
it('asks to supply an argument if none supplied', async () => {
const { stderr } = await run([], { reject: false });
Expand All @@ -28,7 +35,7 @@ describe('create-react-app', () => {
await run([projectName], { cwd: __dirname });

// Assert for the generated files
generatedFiles.forEach(file => expect(join(genPath, file)).toBeTruthy());
generatedFiles.forEach(file => expect(genFileExists(file)).toBeTruthy());
});

it('warns about conflicting files in path', async () => {
Expand Down Expand Up @@ -58,22 +65,23 @@ describe('create-react-app', () => {
await run(['.'], { cwd: genPath });

// Assert for the generated files
generatedFiles.forEach(file => expect(join(genPath, file)).toBeTruthy());
generatedFiles.forEach(file => expect(genFileExists(file)).toBeTruthy());
});

it('uses npm as the package manager', async () => {
await run([projectName, '--use-npm'], {
it('uses yarn as the package manager', async () => {
await run([projectName], {
cwd: __dirname,
env: { npm_config_user_agent: 'yarn' },
});

// Assert for the generated files
const generatedFilesWithNpm = [
...generatedFiles.filter(file => file !== 'yarn.lock'),
'package-lock.json',
const generatedFilesWithYarn = [
...generatedFiles.filter(file => file !== 'package-lock.json'),
'yarn.lock',
];

generatedFilesWithNpm.forEach(file =>
expect(join(genPath, file)).toBeTruthy()
generatedFilesWithYarn.forEach(file =>
expect(genFileExists(file)).toBeTruthy()
);
});

Expand All @@ -84,7 +92,7 @@ describe('create-react-app', () => {

// Assert for the generated files
[...generatedFiles, 'tsconfig.json'].forEach(file =>
expect(join(genPath, file)).toBeTruthy()
expect(genFileExists(file)).toBeTruthy()
);
});
});

0 comments on commit 04482a6

Please sign in to comment.