From 6f01debb9fc3fa51262c184e9aeb1091dd637ed8 Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Mon, 30 Sep 2019 14:51:04 +0200 Subject: [PATCH] Support setting baseUrl to root directory --- packages/react-scripts/config/modules.js | 55 ++++++++++++++++++- .../react-scripts/config/webpack.config.js | 5 +- .../scripts/utils/createJestConfig.js | 1 + 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/packages/react-scripts/config/modules.js b/packages/react-scripts/config/modules.js index d861f2b2dc8..13bd8891e23 100644 --- a/packages/react-scripts/config/modules.js +++ b/packages/react-scripts/config/modules.js @@ -15,7 +15,7 @@ const chalk = require('react-dev-utils/chalk'); const resolve = require('resolve'); /** - * Get the baseUrl of a compilerOptions object. + * Get additional module paths based on the baseUrl of a compilerOptions object. * * @param {Object} options */ @@ -46,6 +46,15 @@ function getAdditionalModulePaths(options = {}) { return [paths.appSrc]; } + // If the path is equal to the root directory we ignore it here. + // We don't want to allow importing from the root directly as source files are + // not transpiled outside of `src`. We do allow importing them with the + // absolute path (e.g. `src/Components/Button.js`) but we set that up with + // an alias. + if (path.relative(paths.appPath, baseUrlResolved) === '') { + return null; + } + // Otherwise, throw an error. throw new Error( chalk.red.bold( @@ -55,6 +64,48 @@ function getAdditionalModulePaths(options = {}) { ); } +/** + * Get webpack aliases based on the baseUrl of a compilerOptions object. + * + * @param {*} options + */ +function getWebpackAliases(options = {}) { + const baseUrl = options.baseUrl; + + if (!baseUrl) { + return {}; + } + + const baseUrlResolved = path.resolve(paths.appPath, baseUrl); + + if (path.relative(paths.appPath, baseUrlResolved) === '') { + return { + src: paths.appSrc, + }; + } +} + +/** + * Get jest aliases based on the baseUrl of a compilerOptions object. + * + * @param {*} options + */ +function getJestAliases(options = {}) { + const baseUrl = options.baseUrl; + + if (!baseUrl) { + return {}; + } + + const baseUrlResolved = path.resolve(paths.appPath, baseUrl); + + if (path.relative(paths.appPath, baseUrlResolved) === '') { + return { + 'src/(.*)$': '/src/$1', + }; + } +} + function getModules() { // Check if TypeScript is setup const hasTsConfig = fs.existsSync(paths.appTsConfig); @@ -89,6 +140,8 @@ function getModules() { return { additionalModulePaths: additionalModulePaths, + webpackAliases: getWebpackAliases(options), + jestAliases: getJestAliases(options), hasTsConfig, }; } diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index ab2309b37d8..15854139057 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -306,6 +306,7 @@ module.exports = function(webpackEnv) { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ 'react-native': 'react-native-web', + ...(modules.webpackAliases || {}), }, plugins: [ // Adds support for installing with Plug'n'Play, leading to faster installs and adding @@ -352,7 +353,9 @@ module.exports = function(webpackEnv) { const eslintCli = new eslint.CLIEngine(); let eslintConfig; try { - eslintConfig = eslintCli.getConfigForFile(paths.appIndexJs); + eslintConfig = eslintCli.getConfigForFile( + paths.appIndexJs + ); } catch (e) { console.error(e); process.exit(1); diff --git a/packages/react-scripts/scripts/utils/createJestConfig.js b/packages/react-scripts/scripts/utils/createJestConfig.js index 0beef9addb7..c6408f8906c 100644 --- a/packages/react-scripts/scripts/utils/createJestConfig.js +++ b/packages/react-scripts/scripts/utils/createJestConfig.js @@ -56,6 +56,7 @@ module.exports = (resolve, rootDir, isEjecting) => { moduleNameMapper: { '^react-native$': 'react-native-web', '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy', + ...(modules.jestAliases || {}), }, moduleFileExtensions: [...paths.moduleFileExtensions, 'node'].filter( ext => !ext.includes('mjs')