diff --git a/packages/create-react-app/createReactApp.js b/packages/create-react-app/createReactApp.js index fbf0f3c8160..015417a2c2a 100755 --- a/packages/create-react-app/createReactApp.js +++ b/packages/create-react-app/createReactApp.js @@ -49,7 +49,7 @@ const url = require('url'); const hyperquest = require('hyperquest'); const envinfo = require('envinfo'); const os = require('os'); -const findMonorepo = require('react-dev-utils/workspaceUtils').findMonorepo; + const packageJson = require('./package.json'); // These files should be allowed to remain on a failed install, @@ -204,7 +204,7 @@ function createApp(name, verbose, version, useNpm, template) { JSON.stringify(packageJson, null, 2) + os.EOL ); - const useYarn = useNpm ? false : shouldUseYarn(root); + const useYarn = useNpm ? false : shouldUseYarn(); const originalDirectory = process.cwd(); process.chdir(root); if (!useYarn && !checkThatNpmCanReadCwd()) { @@ -244,7 +244,7 @@ function createApp(name, verbose, version, useNpm, template) { run(root, appName, version, verbose, originalDirectory, template, useYarn); } -function isYarnAvailable() { +function shouldUseYarn() { try { execSync('yarnpkg --version', { stdio: 'ignore' }); return true; @@ -253,11 +253,6 @@ function isYarnAvailable() { } } -function shouldUseYarn(appDir) { - const mono = findMonorepo(appDir); - return (mono.isYarnWs && mono.isAppIncluded) || isYarnAvailable(); -} - function install(root, useYarn, dependencies, verbose, isOnline) { return new Promise((resolve, reject) => { let command; diff --git a/packages/create-react-app/package.json b/packages/create-react-app/package.json index 27f7fc74089..dbc8a188e73 100644 --- a/packages/create-react-app/package.json +++ b/packages/create-react-app/package.json @@ -27,7 +27,6 @@ "envinfo": "5.4.0", "fs-extra": "^5.0.0", "hyperquest": "^2.1.2", - "react-dev-utils": "^5.0.0", "semver": "^5.0.3", "tar-pack": "^3.4.0", "tmp": "0.0.33", diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 606aff50392..61394095fde 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -34,8 +34,7 @@ "printHostingInstructions.js", "WatchMissingNodeModulesPlugin.js", "WebpackDevServerUtils.js", - "webpackHotDevClient.js", - "workspaceUtils.js" + "webpackHotDevClient.js" ], "dependencies": { "@babel/code-frame": "7.0.0-beta.46", @@ -46,9 +45,7 @@ "detect-port-alt": "1.1.6", "escape-string-regexp": "1.0.5", "filesize": "3.6.1", - "find-pkg": "1.0.0", "global-modules": "1.0.0", - "globby": "8.0.1", "gzip-size": "4.1.0", "inquirer": "5.1.0", "is-root": "1.0.0", diff --git a/packages/react-dev-utils/workspaceUtils.js b/packages/react-dev-utils/workspaceUtils.js deleted file mode 100644 index 159580e6066..00000000000 --- a/packages/react-dev-utils/workspaceUtils.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2018-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -'use strict'; -const fs = require('fs'); -const path = require('path'); -const findPkg = require('find-pkg'); -const globby = require('globby'); - -const findPkgs = (rootPath, globPatterns) => { - if (!globPatterns) { - return []; - } - const globOpts = { - cwd: rootPath, - strict: true, - absolute: true, - }; - return globPatterns - .reduce( - (pkgs, pattern) => - pkgs.concat(globby.sync(path.join(pattern, 'package.json'), globOpts)), - [] - ) - .map(f => path.dirname(path.normalize(f))); -}; - -const findMonorepo = appDir => { - const monoPkgPath = findPkg.sync(path.resolve(appDir, '..')); - const monoPkg = monoPkgPath && require(monoPkgPath); - const patterns = monoPkg && monoPkg.workspaces; - const isYarnWs = Boolean(patterns); - const allPkgs = patterns && findPkgs(path.dirname(monoPkgPath), patterns); - const isIncluded = dir => allPkgs && allPkgs.indexOf(dir) !== -1; - const isAppIncluded = isIncluded(appDir); - const pkgs = allPkgs - ? allPkgs.filter(f => fs.realpathSync(f) !== appDir) - : []; - - return { - isAppIncluded, - isYarnWs, - pkgs, - }; -}; - -module.exports = { - findMonorepo, -}; diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 32665e9b76c..f701bf2bd40 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -11,7 +11,8 @@ const path = require('path'); const fs = require('fs'); const url = require('url'); -const findMonorepo = require('react-dev-utils/workspaceUtils').findMonorepo; +const findPkg = require('find-pkg'); +const globby = require('globby'); // Make sure any symlinks in the project folder are resolved: // https://github.com/facebook/create-react-app/issues/637 @@ -57,6 +58,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'), publicUrl: getPublicUrl(resolveApp('package.json')), @@ -78,6 +80,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'), publicUrl: getPublicUrl(resolveApp('package.json')), @@ -103,6 +106,7 @@ if (useTemplate) { 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'), publicUrl: getPublicUrl(resolveOwn('package.json')), @@ -116,16 +120,40 @@ if (useTemplate) { module.exports.srcPaths = [module.exports.appSrc]; -module.exports.useYarn = fs.existsSync( - path.join(module.exports.appPath, 'yarn.lock') -); +const findPkgs = (rootPath, globPatterns) => { + const globOpts = { + cwd: rootPath, + strict: true, + absolute: true, + }; + return globPatterns + .reduce( + (pkgs, pattern) => + pkgs.concat(globby.sync(path.join(pattern, 'package.json'), globOpts)), + [] + ) + .map(f => path.dirname(path.normalize(f))); +}; + +const getMonorepoPkgPaths = () => { + const monoPkgPath = findPkg.sync(path.resolve(appDirectory, '..')); + if (monoPkgPath) { + // get monorepo config from yarn workspace + const pkgPatterns = require(monoPkgPath).workspaces; + if (pkgPatterns == null) { + return []; + } + const pkgPaths = findPkgs(path.dirname(monoPkgPath), pkgPatterns); + // only include monorepo pkgs if app itself is included in monorepo + if (pkgPaths.indexOf(appDirectory) !== -1) { + return pkgPaths.filter(f => fs.realpathSync(f) !== appDirectory); + } + } + return []; +}; if (checkForMonorepo) { // if app is in a monorepo (lerna or yarn workspace), treat other packages in // the monorepo as if they are app source - const mono = findMonorepo(appDirectory); - if (mono.isAppIncluded) { - Array.prototype.push.apply(module.exports.srcPaths, mono.pkgs); - } - module.exports.useYarn = module.exports.useYarn || mono.isYarnWs; + Array.prototype.push.apply(module.exports.srcPaths, getMonorepoPkgPaths()); } diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 0e639a768dd..7fe0b2bb1c6 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -44,7 +44,9 @@ "eslint-plugin-jsx-a11y": "6.0.3", "eslint-plugin-react": "7.8.2", "file-loader": "1.1.11", + "find-pkg": "1.0.0", "fs-extra": "5.0.0", + "globby": "7.1.1", "graphql": "0.13.2", "graphql-tag": "2.9.2", "html-webpack-plugin": "3.2.0", diff --git a/packages/react-scripts/scripts/build.js b/packages/react-scripts/scripts/build.js index 599aa32ee4e..6c37f3d71ae 100644 --- a/packages/react-scripts/scripts/build.js +++ b/packages/react-scripts/scripts/build.js @@ -46,6 +46,7 @@ const { printBrowsers } = require('react-dev-utils/browsersHelper'); const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild; const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild; +const useYarn = fs.existsSync(paths.yarnLockFile); // These sizes are pretty large. We'll warn for bundles exceeding them. const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; @@ -116,7 +117,7 @@ checkBrowsers(paths.appPath) publicUrl, publicPath, buildFolder, - paths.useYarn + useYarn ); printBrowsers(paths.appPath); }, diff --git a/packages/react-scripts/scripts/eject.js b/packages/react-scripts/scripts/eject.js index 98863b915f2..e8c64a77853 100644 --- a/packages/react-scripts/scripts/eject.js +++ b/packages/react-scripts/scripts/eject.js @@ -224,7 +224,7 @@ inquirer } } - if (paths.useYarn) { + if (fs.existsSync(paths.yarnLockFile)) { const windowsCmdFilePath = path.join( appPath, 'node_modules', diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 95502bc2a24..1b080f92ac2 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -29,6 +29,7 @@ if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') { } // @remove-on-eject-end +const fs = require('fs'); const chalk = require('chalk'); const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); @@ -45,6 +46,7 @@ const paths = require('../config/paths'); const config = require('../config/webpack.config.dev'); const createDevServerConfig = require('../config/webpackDevServer.config'); +const useYarn = fs.existsSync(paths.yarnLockFile); const isInteractive = process.stdout.isTTY; // Warn and crash if required files are missing @@ -91,13 +93,7 @@ checkBrowsers(paths.appPath) const appName = require(paths.appPackageJson).name; const urls = prepareUrls(protocol, HOST, port); // Create a webpack compiler that is configured with custom messages. - const compiler = createCompiler( - webpack, - config, - appName, - urls, - paths.useYarn - ); + const compiler = createCompiler(webpack, config, appName, urls, useYarn); // Load proxy config const proxySetting = require(paths.appPackageJson).proxy; const proxyConfig = prepareProxy(proxySetting, paths.appPublic);