Skip to content

Commit 34ee0de

Browse files
committed
Move preflight check into individual scripts
This ensures we don't try to filter NODE_PATH twice, accidentally removing the now-absolute path.
1 parent 0189867 commit 34ee0de

File tree

5 files changed

+170
-150
lines changed

5 files changed

+170
-150
lines changed

packages/react-scripts/bin/react-scripts.js

Lines changed: 0 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -15,156 +15,6 @@ process.on('unhandledRejection', err => {
1515
throw err;
1616
});
1717

18-
// Set this so that importing "../config/env" doesn't fail.
19-
// In practice it won't matter because we'll spawn another process now.
20-
process.env.NODE_ENV = 'development';
21-
// Ensure environment variables are read.
22-
require('../config/env');
23-
24-
const chalk = require('chalk');
25-
const fs = require('fs');
26-
const path = require('path');
27-
28-
// We assume that having wrong versions of these
29-
// in the tree will likely break your setup.
30-
// This is a relatively low-effort way to find common issues.
31-
function verifyPackageTree() {
32-
const depsToCheck = [
33-
// These are packages most likely to break in practice.
34-
// See https://github.com/facebookincubator/create-react-app/issues/1795 for reasons why.
35-
// I have not included Babel here because plugins typically don't import Babel (so it's not affected).
36-
'eslint',
37-
'jest',
38-
'webpack',
39-
'webpack-dev-server',
40-
];
41-
// Inlined from semver-regex, MIT license.
42-
// Don't want to make this a dependency after ejecting.
43-
const getSemverRegex = () =>
44-
/\bv?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?\b/gi;
45-
const ownPackageJson = require('../package.json');
46-
const expectedVersionsByDep = {};
47-
// Gather wanted deps
48-
depsToCheck.forEach(dep => {
49-
const expectedVersion = ownPackageJson.dependencies[dep];
50-
if (!expectedVersion) {
51-
throw new Error('This dependency list is outdated, fix it.');
52-
}
53-
if (!getSemverRegex().test(expectedVersion)) {
54-
throw new Error(
55-
`The ${dep} package should be pinned, instead got version ${expectedVersion}.`
56-
);
57-
}
58-
expectedVersionsByDep[dep] = expectedVersion;
59-
});
60-
// Verify we don't have other versions up the tree
61-
let currentDir = __dirname;
62-
// eslint-disable-next-line no-constant-condition
63-
while (true) {
64-
const previousDir = currentDir;
65-
currentDir = path.resolve(currentDir, '..');
66-
if (currentDir === previousDir) {
67-
// We've reached the root.
68-
break;
69-
}
70-
const maybeNodeModules = path.resolve(currentDir, 'node_modules');
71-
if (!fs.existsSync(maybeNodeModules)) {
72-
continue;
73-
}
74-
depsToCheck.forEach(dep => {
75-
const maybeDep = path.resolve(maybeNodeModules, dep);
76-
if (!fs.existsSync(maybeDep)) {
77-
return;
78-
}
79-
const maybeDepPackageJson = path.resolve(maybeDep, 'package.json');
80-
if (!fs.existsSync(maybeDepPackageJson)) {
81-
return;
82-
}
83-
const depPackageJson = JSON.parse(
84-
fs.readFileSync(maybeDepPackageJson, 'utf8')
85-
);
86-
const expectedVersion = expectedVersionsByDep[dep];
87-
if (depPackageJson.version !== expectedVersion) {
88-
console.error(
89-
chalk.red(
90-
`There might be a problem with the project dependency tree.\n` +
91-
`It is likely ${chalk.bold(
92-
'not'
93-
)} a bug in Create React App, but something you need to fix locally.\n\n`
94-
) +
95-
`The ${chalk.bold(
96-
'react-scripts'
97-
)} package provided by Create React App requires a dependency:\n\n` +
98-
chalk.green(
99-
` "${chalk.bold(dep)}": "${chalk.bold(expectedVersion)}"\n\n`
100-
) +
101-
`However, a different version of ${chalk.bold(
102-
dep
103-
)} was detected higher up in the tree:\n\n` +
104-
` ${chalk.bold(chalk.red(maybeDep))} (version: ${chalk.bold(
105-
chalk.red(depPackageJson.version)
106-
)}) \n\n` +
107-
`This is known to cause hard-to-debug issues.\n` +
108-
`Try following these steps:\n\n` +
109-
` ${chalk.cyan('1.')} Delete ${chalk.bold(
110-
'package-lock.json'
111-
)} (${chalk.underline('not')} ${chalk.bold(
112-
'package.json'
113-
)}!) and/or ${chalk.bold(
114-
'yarn.lock'
115-
)} in your project folder.\n\n` +
116-
` ${chalk.cyan('2.')} Delete ${chalk.bold(
117-
'node_modules'
118-
)} in your project folder.\n\n` +
119-
` ${chalk.cyan('3.')} Remove "${chalk.bold(
120-
dep
121-
)}" from ${chalk.bold('dependencies')} and/or ${chalk.bold(
122-
'devDependencies'
123-
)} in the ${chalk.bold(
124-
'package.json'
125-
)} file in your project folder.\n\n` +
126-
` ${chalk.cyan('4.')} Run ${chalk.bold(
127-
'npm install'
128-
)} or ${chalk.bold(
129-
'yarn'
130-
)}, depending on the package manager you use.\n\n` +
131-
`If this has not helped, there are a few other things to try:\n\n` +
132-
` ${chalk.cyan('5.')} If you used ${chalk.bold(
133-
'npm'
134-
)}, install ${chalk.bold(
135-
'yarn'
136-
)} (http://yarnpkg.com/) and repeat the above steps with it instead.\n` +
137-
` This may help because npm has known issues with package hoisting which may get resolved in future versions.\n\n` +
138-
` ${chalk.cyan('6.')} Check if ${chalk.bold(
139-
maybeDep
140-
)} is outside your project directory.\n` +
141-
` For example, you might have installed something accidentally in your home folder.\n\n` +
142-
` ${chalk.cyan('7.')} Try running ${chalk.bold(
143-
`npm ls ${dep}`
144-
)} in your project folder.\n` +
145-
` This will tell you which ${chalk.underline(
146-
'other'
147-
)} package (apart from the expected ${chalk.bold(
148-
'react-scripts'
149-
)}) installed ${chalk.bold(dep)}.\n\n` +
150-
`If nothing else helps, add ${chalk.bold(
151-
'SKIP_PREFLIGHT_CHECK=true'
152-
)} to an ${chalk.bold('.env')} file in your project.\n` +
153-
`This permanently disables this preflight check in case you want to proceed anyway.\n\n` +
154-
chalk.cyan(
155-
`P.S. We know this message is long but please read the steps above :-) We hope you find them helpful!\n`
156-
)
157-
);
158-
process.exit(1);
159-
}
160-
});
161-
}
162-
}
163-
164-
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
165-
verifyPackageTree();
166-
}
167-
16818
const spawn = require('react-dev-utils/crossSpawn');
16919
const args = process.argv.slice(2);
17020

packages/react-scripts/scripts/build.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ process.on('unhandledRejection', err => {
2121

2222
// Ensure environment variables are read.
2323
require('../config/env');
24+
// @remove-on-eject-begin
25+
// Do the preflight check (only happens before eject).
26+
const verifyPackageTree = require('./utils/verifyPackageTree');
27+
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
28+
verifyPackageTree();
29+
}
30+
// @remove-on-eject-end
2431

2532
const path = require('path');
2633
const chalk = require('chalk');

packages/react-scripts/scripts/start.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ process.on('unhandledRejection', err => {
2121

2222
// Ensure environment variables are read.
2323
require('../config/env');
24+
// @remove-on-eject-begin
25+
// Do the preflight check (only happens before eject).
26+
const verifyPackageTree = require('./utils/verifyPackageTree');
27+
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
28+
verifyPackageTree();
29+
}
30+
// @remove-on-eject-end
2431

2532
const fs = require('fs');
2633
const chalk = require('chalk');

packages/react-scripts/scripts/test.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ process.on('unhandledRejection', err => {
2222

2323
// Ensure environment variables are read.
2424
require('../config/env');
25+
// @remove-on-eject-begin
26+
// Do the preflight check (only happens before eject).
27+
const verifyPackageTree = require('./utils/verifyPackageTree');
28+
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
29+
verifyPackageTree();
30+
}
31+
// @remove-on-eject-end
2532

2633
const jest = require('jest');
2734
const argv = process.argv.slice(2);
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// @remove-file-on-eject
2+
/**
3+
* Copyright (c) 2015-present, Facebook, Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
const chalk = require('chalk');
10+
const fs = require('fs');
11+
const path = require('path');
12+
13+
// We assume that having wrong versions of these
14+
// in the tree will likely break your setup.
15+
// This is a relatively low-effort way to find common issues.
16+
function verifyPackageTree() {
17+
const depsToCheck = [
18+
// These are packages most likely to break in practice.
19+
// See https://github.com/facebookincubator/create-react-app/issues/1795 for reasons why.
20+
// I have not included Babel here because plugins typically don't import Babel (so it's not affected).
21+
'eslint',
22+
'jest',
23+
'webpack',
24+
'webpack-dev-server',
25+
];
26+
// Inlined from semver-regex, MIT license.
27+
// Don't want to make this a dependency after ejecting.
28+
const getSemverRegex = () =>
29+
/\bv?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?\b/gi;
30+
const ownPackageJson = require('../../package.json');
31+
const expectedVersionsByDep = {};
32+
// Gather wanted deps
33+
depsToCheck.forEach(dep => {
34+
const expectedVersion = ownPackageJson.dependencies[dep];
35+
if (!expectedVersion) {
36+
throw new Error('This dependency list is outdated, fix it.');
37+
}
38+
if (!getSemverRegex().test(expectedVersion)) {
39+
throw new Error(
40+
`The ${dep} package should be pinned, instead got version ${expectedVersion}.`
41+
);
42+
}
43+
expectedVersionsByDep[dep] = expectedVersion;
44+
});
45+
// Verify we don't have other versions up the tree
46+
let currentDir = __dirname;
47+
// eslint-disable-next-line no-constant-condition
48+
while (true) {
49+
const previousDir = currentDir;
50+
currentDir = path.resolve(currentDir, '..');
51+
if (currentDir === previousDir) {
52+
// We've reached the root.
53+
break;
54+
}
55+
const maybeNodeModules = path.resolve(currentDir, 'node_modules');
56+
if (!fs.existsSync(maybeNodeModules)) {
57+
continue;
58+
}
59+
depsToCheck.forEach(dep => {
60+
const maybeDep = path.resolve(maybeNodeModules, dep);
61+
if (!fs.existsSync(maybeDep)) {
62+
return;
63+
}
64+
const maybeDepPackageJson = path.resolve(maybeDep, 'package.json');
65+
if (!fs.existsSync(maybeDepPackageJson)) {
66+
return;
67+
}
68+
const depPackageJson = JSON.parse(
69+
fs.readFileSync(maybeDepPackageJson, 'utf8')
70+
);
71+
const expectedVersion = expectedVersionsByDep[dep];
72+
if (depPackageJson.version !== expectedVersion) {
73+
console.error(
74+
chalk.red(
75+
`There might be a problem with the project dependency tree.\n` +
76+
`It is likely ${chalk.bold(
77+
'not'
78+
)} a bug in Create React App, but something you need to fix locally.\n\n`
79+
) +
80+
`The ${chalk.bold(
81+
ownPackageJson.name
82+
)} package provided by Create React App requires a dependency:\n\n` +
83+
chalk.green(
84+
` "${chalk.bold(dep)}": "${chalk.bold(expectedVersion)}"\n\n`
85+
) +
86+
`However, a different version of ${chalk.bold(
87+
dep
88+
)} was detected higher up in the tree:\n\n` +
89+
` ${chalk.bold(chalk.red(maybeDep))} (version: ${chalk.bold(
90+
chalk.red(depPackageJson.version)
91+
)}) \n\n` +
92+
`This is known to cause hard-to-debug issues.\n` +
93+
`Try following these steps:\n\n` +
94+
` ${chalk.cyan('1.')} Delete ${chalk.bold(
95+
'package-lock.json'
96+
)} (${chalk.underline('not')} ${chalk.bold(
97+
'package.json'
98+
)}!) and/or ${chalk.bold(
99+
'yarn.lock'
100+
)} in your project folder.\n\n` +
101+
` ${chalk.cyan('2.')} Delete ${chalk.bold(
102+
'node_modules'
103+
)} in your project folder.\n\n` +
104+
` ${chalk.cyan('3.')} Remove "${chalk.bold(
105+
dep
106+
)}" from ${chalk.bold('dependencies')} and/or ${chalk.bold(
107+
'devDependencies'
108+
)} in the ${chalk.bold(
109+
'package.json'
110+
)} file in your project folder.\n\n` +
111+
` ${chalk.cyan('4.')} Run ${chalk.bold(
112+
'npm install'
113+
)} or ${chalk.bold(
114+
'yarn'
115+
)}, depending on the package manager you use.\n\n` +
116+
`If this has not helped, there are a few other things to try:\n\n` +
117+
` ${chalk.cyan('5.')} If you used ${chalk.bold(
118+
'npm'
119+
)}, install ${chalk.bold(
120+
'yarn'
121+
)} (http://yarnpkg.com/) and repeat the above steps with it instead.\n` +
122+
` This may help because npm has known issues with package hoisting which may get resolved in future versions.\n\n` +
123+
` ${chalk.cyan('6.')} Check if ${chalk.bold(
124+
maybeDep
125+
)} is outside your project directory.\n` +
126+
` For example, you might have installed something accidentally in your home folder.\n\n` +
127+
` ${chalk.cyan('7.')} Try running ${chalk.bold(
128+
`npm ls ${dep}`
129+
)} in your project folder.\n` +
130+
` This will tell you which ${chalk.underline(
131+
'other'
132+
)} package (apart from the expected ${chalk.bold(
133+
ownPackageJson.name
134+
)}) installed ${chalk.bold(dep)}.\n\n` +
135+
`If nothing else helps, add ${chalk.bold(
136+
'SKIP_PREFLIGHT_CHECK=true'
137+
)} to an ${chalk.bold('.env')} file in your project.\n` +
138+
`This permanently disables this preflight check in case you want to proceed anyway.\n\n` +
139+
chalk.cyan(
140+
`P.S. We know this message is long but please read the steps above :-) We hope you find them helpful!\n`
141+
)
142+
);
143+
process.exit(1);
144+
}
145+
});
146+
}
147+
}
148+
149+
module.exports = verifyPackageTree;

0 commit comments

Comments
 (0)