From a479ce9f3cd9a1254fe9c1e72c27e52e0b6316d0 Mon Sep 17 00:00:00 2001 From: Reinier Hartog Date: Thu, 9 Nov 2017 15:31:26 +0100 Subject: [PATCH 1/7] Use `resolve-from` to respect `node_modules` hierarchy in `createReactApp.js` --- packages/create-react-app/createReactApp.js | 22 +++++++++------------ packages/create-react-app/package.json | 1 + 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index 16acace8fa2..e9700b53fea 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -49,6 +49,7 @@ const url = require('url'); const hyperquest = require('hyperquest'); const envinfo = require('envinfo'); const os = require('os'); +const resolveFrom = require('resolve-from'); const packageJson = require('./package.json'); @@ -318,15 +319,12 @@ function run( ); }) .then(packageName => { - checkNodeVersion(packageName); + checkNodeVersion(root, packageName); setCaretRangeForRuntimeDeps(packageName); - const scriptsPath = path.resolve( - process.cwd(), - 'node_modules', - packageName, - 'scripts', - 'init.js' + const scriptsPath = resolveFrom( + root, + path.join(packageName, 'scripts', 'init.js') ); const init = require(scriptsPath); init(root, appName, verbose, originalDirectory, template); @@ -506,12 +504,10 @@ function checkNpmVersion() { }; } -function checkNodeVersion(packageName) { - const packageJsonPath = path.resolve( - process.cwd(), - 'node_modules', - packageName, - 'package.json' +function checkNodeVersion(root, packageName) { + const packageJsonPath = resolveFrom( + root, + path.join(packageName, 'package.json') ); const packageJson = require(packageJsonPath); if (!packageJson.engines || !packageJson.engines.node) { diff --git a/packages/create-react-app/package.json b/packages/create-react-app/package.json index 1a66c6a7f3c..b5d4bee5ebf 100644 --- a/packages/create-react-app/package.json +++ b/packages/create-react-app/package.json @@ -27,6 +27,7 @@ "envinfo": "3.4.2", "fs-extra": "^5.0.0", "hyperquest": "^2.1.2", + "resolve-from": "^4.0.0", "semver": "^5.0.3", "tar-pack": "^3.4.0", "tmp": "0.0.33", From e2d2decad2c0be0f0db125562aa6d6a81b2ce8cd Mon Sep 17 00:00:00 2001 From: Reinier Hartog Date: Fri, 10 Nov 2017 08:19:25 +0100 Subject: [PATCH 2/7] Resolve `ownPath` in `init.js` using `resolve-from` --- packages/react-scripts/scripts/init.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index ac695d167d9..0b43447dd6d 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -21,6 +21,7 @@ const execSync = require('child_process').execSync; const spawn = require('react-dev-utils/crossSpawn'); const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); +const resolveFrom = require('resolve-from'); function isInGitRepository() { try { @@ -83,7 +84,10 @@ module.exports = function( ) { const ownPackageName = require(path.join(__dirname, '..', 'package.json')) .name; - const ownPath = path.join(appPath, 'node_modules', ownPackageName); + const ownPath = path.join( + resolveFrom(appPath, path.join(ownPackageName, 'package.json')), + '..' + ); const appPackage = require(path.join(appPath, 'package.json')); const useYarn = fs.existsSync(path.join(appPath, 'yarn.lock')); From 3dab136fa9bda4271eeaea4ca5189e57de43057b Mon Sep 17 00:00:00 2001 From: Bradford Lemley Date: Sat, 3 Feb 2018 15:34:50 -0700 Subject: [PATCH 3/7] Test running create-react-app inside monorepo. --- .../cra-app/.template.dependencies.json | 5 +++ .../fixtures/monorepos/cra-app/gitignore | 24 ++++++++++++ .../cra-app1 => cra-app}/public/favicon.ico | Bin .../cra-app1 => cra-app}/public/index.html | 0 .../cra-app1 => cra-app}/public/manifest.json | 0 .../cra-app1 => cra-app}/src/App.css | 0 .../{packages/cra-app1 => cra-app}/src/App.js | 0 .../cra-app1 => cra-app}/src/App.test.js | 0 .../cra-app1 => cra-app}/src/index.css | 0 .../cra-app1 => cra-app}/src/index.js | 0 .../cra-app1 => cra-app}/src/logo.svg | 0 packages/react-scripts/scripts/init.js | 12 +++++- tasks/e2e-monorepos.sh | 37 ++++++++++++++---- 13 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 packages/react-scripts/fixtures/monorepos/cra-app/.template.dependencies.json create mode 100644 packages/react-scripts/fixtures/monorepos/cra-app/gitignore rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/public/favicon.ico (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/public/index.html (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/public/manifest.json (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/App.css (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/App.js (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/App.test.js (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/index.css (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/index.js (100%) rename packages/react-scripts/fixtures/monorepos/{packages/cra-app1 => cra-app}/src/logo.svg (100%) diff --git a/packages/react-scripts/fixtures/monorepos/cra-app/.template.dependencies.json b/packages/react-scripts/fixtures/monorepos/cra-app/.template.dependencies.json new file mode 100644 index 00000000000..93d99993f2f --- /dev/null +++ b/packages/react-scripts/fixtures/monorepos/cra-app/.template.dependencies.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "comp2": "^1.0.0" + } +} diff --git a/packages/react-scripts/fixtures/monorepos/cra-app/gitignore b/packages/react-scripts/fixtures/monorepos/cra-app/gitignore new file mode 100644 index 00000000000..57078cd1367 --- /dev/null +++ b/packages/react-scripts/fixtures/monorepos/cra-app/gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# generated test output +testoutput.json + +# dependencies +/node_modules + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/favicon.ico b/packages/react-scripts/fixtures/monorepos/cra-app/public/favicon.ico similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/favicon.ico rename to packages/react-scripts/fixtures/monorepos/cra-app/public/favicon.ico diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/index.html b/packages/react-scripts/fixtures/monorepos/cra-app/public/index.html similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/index.html rename to packages/react-scripts/fixtures/monorepos/cra-app/public/index.html diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/manifest.json b/packages/react-scripts/fixtures/monorepos/cra-app/public/manifest.json similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/public/manifest.json rename to packages/react-scripts/fixtures/monorepos/cra-app/public/manifest.json diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.css b/packages/react-scripts/fixtures/monorepos/cra-app/src/App.css similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.css rename to packages/react-scripts/fixtures/monorepos/cra-app/src/App.css diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.js b/packages/react-scripts/fixtures/monorepos/cra-app/src/App.js similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.js rename to packages/react-scripts/fixtures/monorepos/cra-app/src/App.js diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.test.js b/packages/react-scripts/fixtures/monorepos/cra-app/src/App.test.js similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/App.test.js rename to packages/react-scripts/fixtures/monorepos/cra-app/src/App.test.js diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/index.css b/packages/react-scripts/fixtures/monorepos/cra-app/src/index.css similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/index.css rename to packages/react-scripts/fixtures/monorepos/cra-app/src/index.css diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/index.js b/packages/react-scripts/fixtures/monorepos/cra-app/src/index.js similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/index.js rename to packages/react-scripts/fixtures/monorepos/cra-app/src/index.js diff --git a/packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/logo.svg b/packages/react-scripts/fixtures/monorepos/cra-app/src/logo.svg similarity index 100% rename from packages/react-scripts/fixtures/monorepos/packages/cra-app1/src/logo.svg rename to packages/react-scripts/fixtures/monorepos/cra-app/src/logo.svg diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 0b43447dd6d..2803c32d313 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -75,6 +75,15 @@ function tryGitInit(appPath) { } } +function isYarnAvailable() { + try { + execSync('yarnpkg --version', { stdio: 'ignore' }); + return true; + } catch (e) { + return false; + } +} + module.exports = function( appPath, appName, @@ -89,7 +98,8 @@ module.exports = function( '..' ); const appPackage = require(path.join(appPath, 'package.json')); - const useYarn = fs.existsSync(path.join(appPath, 'yarn.lock')); + const useYarn = + fs.existsSync(path.join(appPath, 'yarn.lock')) || isYarnAvailable(); // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; diff --git a/tasks/e2e-monorepos.sh b/tasks/e2e-monorepos.sh index 635badcf219..25485303704 100755 --- a/tasks/e2e-monorepos.sh +++ b/tasks/e2e-monorepos.sh @@ -110,25 +110,48 @@ pushd "$temp_app_path" cp -r "$root_path/packages/react-scripts/fixtures/monorepos/yarn-ws" . cd "yarn-ws" cp -r "$root_path/packages/react-scripts/fixtures/monorepos/packages" . -yarn # Test cra-app1 -cd packages/cra-app1 +pushd packages/cra-app1 +cp -r "$root_path/packages/react-scripts/fixtures/monorepos/cra-app/"* . +yarn +verifyBuild +yarn start --smoke-test +verifyTest +popd + +# ****************************************************************************** +# Test clean create-react-app inside workspace +# ****************************************************************************** +pushd packages +npx create-react-app newapp +cd newapp +yarn +yarn build +yarn start --smoke-test +CI=true yarn test --watch=no +popd + +# ****************************************************************************** +# Test create-react-app w/ shared comps inside workspace +# ****************************************************************************** +pushd packages +npx create-react-app --internal-testing-template="$root_path"/packages/react-scripts/fixtures/monorepos/cra-app cra-app2 +cd cra-app2 +yarn verifyBuild yarn start --smoke-test verifyTest # Test eject +# TODO: veriy tests can be run from other apps after eject +# -- will currently fail due to picking up ejected scripts/test.js echo yes | npm run eject verifyBuild yarn start --smoke-test verifyTest +popd -# ****************************************************************************** -# Test create-react-app inside workspace -# ****************************************************************************** -# npx create-react-app --internal-testing-template="$root_path"/packages/react-scripts/fixtures/yarn-ws/ws/cra-app1 cra-app2 -# -- above needs https://github.com/facebookincubator/create-react-app/pull/3435 to user create-react-app popd # Cleanup From 69d822c3c843f72cde124cba2afb84b1a69398a7 Mon Sep 17 00:00:00 2001 From: Bradford Lemley Date: Sat, 10 Feb 2018 07:55:01 -0700 Subject: [PATCH 4/7] Use common strategy to decide whether to use yarn or npm. --- packages/react-scripts/scripts/init.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index 2803c32d313..f8faa9e758e 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -22,6 +22,7 @@ const spawn = require('react-dev-utils/crossSpawn'); const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); const resolveFrom = require('resolve-from'); +const paths = require('../config/paths'); function isInGitRepository() { try { @@ -75,15 +76,6 @@ function tryGitInit(appPath) { } } -function isYarnAvailable() { - try { - execSync('yarnpkg --version', { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } -} - module.exports = function( appPath, appName, @@ -98,8 +90,7 @@ module.exports = function( '..' ); const appPackage = require(path.join(appPath, 'package.json')); - const useYarn = - fs.existsSync(path.join(appPath, 'yarn.lock')) || isYarnAvailable(); + const useYarn = paths.useYarn; // Copy over some of the devDependencies appPackage.dependencies = appPackage.dependencies || {}; From 40bb89c342a4d09705f5dad5df114a052835f21e Mon Sep 17 00:00:00 2001 From: Bradford Lemley Date: Tue, 13 Feb 2018 05:58:34 -0700 Subject: [PATCH 5/7] Workaround yarn workspace bug not creating app/node_modules/.bin link for react-scripts. --- packages/react-scripts/scripts/init.js | 11 ++++++++++- tasks/e2e-monorepos.sh | 2 -- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index f8faa9e758e..a5564ae29e8 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -23,6 +23,7 @@ const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); const resolveFrom = require('resolve-from'); const paths = require('../config/paths'); +const { findMonorepo } = require('react-dev-utils/workspaceUtils'); function isInGitRepository() { try { @@ -177,10 +178,18 @@ module.exports = function( fs.unlinkSync(templateDependenciesPath); } + // yarn ws bug not creating app/node_modules/.bin link to hoisted react-scripts + // -- workaround: install react-scripts again to create link + // bug in yarn 1.3.2, fixed in nightly 1.4.1-20180211.2236 + const rerunYarn = useYarn && findMonorepo(appPath).isAppIncluded; + if (rerunYarn) { + console.log('Detected app in yarn workspace, running install again'); + } + // Install react and react-dom for backward compatibility with old CRA cli // which doesn't install react and react-dom along with react-scripts // or template is presetend (via --internal-testing-template) - if (!isReactInstalled(appPackage) || template) { + if (!isReactInstalled(appPackage) || template || rerunYarn) { console.log(`Installing react and react-dom using ${command}...`); console.log(); diff --git a/tasks/e2e-monorepos.sh b/tasks/e2e-monorepos.sh index 25485303704..480bb016df5 100755 --- a/tasks/e2e-monorepos.sh +++ b/tasks/e2e-monorepos.sh @@ -126,7 +126,6 @@ popd pushd packages npx create-react-app newapp cd newapp -yarn yarn build yarn start --smoke-test CI=true yarn test --watch=no @@ -138,7 +137,6 @@ popd pushd packages npx create-react-app --internal-testing-template="$root_path"/packages/react-scripts/fixtures/monorepos/cra-app cra-app2 cd cra-app2 -yarn verifyBuild yarn start --smoke-test verifyTest From e188e1e5204e69f09c3d3d3d0f164bc391634a16 Mon Sep 17 00:00:00 2001 From: Bradford Lemley Date: Tue, 22 May 2018 14:27:41 -0600 Subject: [PATCH 6/7] Remove yarn < 1.5 workaround. --- packages/react-scripts/scripts/init.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index a5564ae29e8..f8faa9e758e 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -23,7 +23,6 @@ const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); const resolveFrom = require('resolve-from'); const paths = require('../config/paths'); -const { findMonorepo } = require('react-dev-utils/workspaceUtils'); function isInGitRepository() { try { @@ -178,18 +177,10 @@ module.exports = function( fs.unlinkSync(templateDependenciesPath); } - // yarn ws bug not creating app/node_modules/.bin link to hoisted react-scripts - // -- workaround: install react-scripts again to create link - // bug in yarn 1.3.2, fixed in nightly 1.4.1-20180211.2236 - const rerunYarn = useYarn && findMonorepo(appPath).isAppIncluded; - if (rerunYarn) { - console.log('Detected app in yarn workspace, running install again'); - } - // Install react and react-dom for backward compatibility with old CRA cli // which doesn't install react and react-dom along with react-scripts // or template is presetend (via --internal-testing-template) - if (!isReactInstalled(appPackage) || template || rerunYarn) { + if (!isReactInstalled(appPackage) || template) { console.log(`Installing react and react-dom using ${command}...`); console.log(); From 9d9b057914e6a54199c15f017ce8e02272985124 Mon Sep 17 00:00:00 2001 From: Bradford Lemley Date: Thu, 24 May 2018 07:00:40 -0600 Subject: [PATCH 7/7] Revert "Remove yarn < 1.5 workaround." This reverts commit e188e1e5204e69f09c3d3d3d0f164bc391634a16. --- packages/react-scripts/scripts/init.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/scripts/init.js b/packages/react-scripts/scripts/init.js index f8faa9e758e..5328ae2880d 100644 --- a/packages/react-scripts/scripts/init.js +++ b/packages/react-scripts/scripts/init.js @@ -23,6 +23,7 @@ const { defaultBrowsers } = require('react-dev-utils/browsersHelper'); const os = require('os'); const resolveFrom = require('resolve-from'); const paths = require('../config/paths'); +const { findMonorepo } = require('react-dev-utils/workspaceUtils'); function isInGitRepository() { try { @@ -177,10 +178,19 @@ module.exports = function( fs.unlinkSync(templateDependenciesPath); } + // yarn ws not creating app/node_modules/.bin link to hoisted react-scripts + // -- workaround: install react-scripts again to create link + // -- bug in yarn 1.3.2, fix verified in nightly 1.4.1-20180211.2236 and 1.5.1 + // TODO: remove this workaround when CRA enforces min yarn version + const rerunYarn = useYarn && findMonorepo(appPath).isAppIncluded; + if (rerunYarn) { + console.log('Detected app in yarn workspace, running install again'); + } + // Install react and react-dom for backward compatibility with old CRA cli // which doesn't install react and react-dom along with react-scripts // or template is presetend (via --internal-testing-template) - if (!isReactInstalled(appPackage) || template) { + if (!isReactInstalled(appPackage) || template || rerunYarn) { console.log(`Installing react and react-dom using ${command}...`); console.log();