diff --git a/packages/react-scripts/config/env.js b/packages/react-scripts/config/env.js index 937076b52ba..e7d7f9f3206 100644 --- a/packages/react-scripts/config/env.js +++ b/packages/react-scripts/config/env.js @@ -11,6 +11,7 @@ 'use strict'; const fs = require('fs'); +const path = require('path'); const paths = require('./paths'); // Make sure that including paths.js after env.js will read .env variables. @@ -46,6 +47,22 @@ dotenvFiles.forEach(dotenvFile => { } }); +// We support resolving modules according to `NODE_PATH`. +// This lets you use absolute paths in imports inside large monorepos: +// https://github.com/facebookincubator/create-react-app/issues/253. +// It works similar to `NODE_PATH` in Node itself: +// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders +// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. +// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. +// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 +// We also resolve them to make sure all tools using them work consistently. +const appDirectory = fs.realpathSync(process.cwd()); +process.env.NODE_PATH = (process.env.NODE_PATH || '') + .split(path.delimiter) + .filter(folder => folder && !path.isAbsolute(folder)) + .map(folder => path.resolve(appDirectory, folder)) + .join(path.delimiter); + // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be // injected into the application via DefinePlugin in Webpack configuration. const REACT_APP = /^REACT_APP_/i; diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index 0afef5e93d5..42ec8374a15 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -17,28 +17,7 @@ const url = require('url'); // Make sure any symlinks in the project folder are resolved: // https://github.com/facebookincubator/create-react-app/issues/637 const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath); - -// We support resolving modules according to `NODE_PATH`. -// This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebookincubator/create-react-app/issues/253. - -// It works similar to `NODE_PATH` in Node itself: -// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders - -// We will export `nodePaths` as an array of absolute paths. -// It will then be used by Webpack configs. -// Jest doesn’t need this because it already handles `NODE_PATH` out of the box. - -// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. -// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. -// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 - -const nodePaths = (process.env.NODE_PATH || '') - .split(process.platform === 'win32' ? ';' : ':') - .filter(Boolean) - .filter(folder => !path.isAbsolute(folder)) - .map(resolveApp); +const resolveApp = relativePath => path.resolve(appDirectory, relativePath); const envPublicUrl = process.env.PUBLIC_URL; @@ -53,7 +32,8 @@ function ensureSlash(path, needsSlash) { } } -const getPublicUrl = (appPackageJson) => envPublicUrl || require(appPackageJson).homepage; +const getPublicUrl = appPackageJson => + envPublicUrl || require(appPackageJson).homepage; // We use `PUBLIC_URL` environment variable or "homepage" field to infer // "public path" at which the app is served. @@ -80,13 +60,12 @@ module.exports = { yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveApp('src/setupTests.js'), appNodeModules: resolveApp('node_modules'), - nodePaths: nodePaths, publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), }; // @remove-on-eject-begin -const resolveOwn = (relativePath) => path.resolve(__dirname, '..', relativePath); +const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath); // config before eject: we're in ./node_modules/react-scripts/config/ module.exports = { @@ -101,7 +80,6 @@ module.exports = { yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveApp('src/setupTests.js'), appNodeModules: resolveApp('node_modules'), - nodePaths: nodePaths, publicUrl: getPublicUrl(resolveApp('package.json')), servedPath: getServedPath(resolveApp('package.json')), // These properties only exist before ejecting: @@ -131,7 +109,6 @@ if ( yarnLockFile: resolveOwn('template/yarn.lock'), testsSetup: resolveOwn('template/src/setupTests.js'), appNodeModules: resolveOwn('node_modules'), - nodePaths: nodePaths, publicUrl: getPublicUrl(resolveOwn('package.json')), servedPath: getServedPath(resolveOwn('package.json')), // These properties only exist before ejecting: diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 540d54abf5c..0811675b000 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -83,11 +83,13 @@ module.exports = { }, resolve: { // This allows you to set a fallback for where Webpack should look for modules. - // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebookincubator/create-react-app/issues/253 - modules: ['node_modules', paths.appNodeModules].concat(paths.nodePaths), + modules: ['node_modules', paths.appNodeModules].concat( + // It is guaranteed to exist because we tweak it in `env.js` + process.env.NODE_PATH.split(path.delimiter) + ), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index 6a119d71ce8..96c79e2e23d 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -81,11 +81,13 @@ module.exports = { }, resolve: { // This allows you to set a fallback for where Webpack should look for modules. - // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. // https://github.com/facebookincubator/create-react-app/issues/253 - modules: ['node_modules', paths.appNodeModules].concat(paths.nodePaths), + modules: ['node_modules', paths.appNodeModules].concat( + // It is guaranteed to exist because we tweak it in `env.js` + process.env.NODE_PATH.split(path.delimiter) + ), // These are the reasonable defaults supported by the Node ecosystem. // We also include JSX as a common component filename extension to support // some tools, although we do not recommend using it, see: