diff --git a/packages/react-dev-utils/globby.js b/packages/react-dev-utils/globby.js new file mode 100644 index 00000000000..8b32d1d3970 --- /dev/null +++ b/packages/react-dev-utils/globby.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2015-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'; + +var globby = require('globby'); + +module.exports = globby; diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 7c3748af901..54d0f286007 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -23,6 +23,7 @@ "getCacheIdentifier.js", "getCSSModuleLocalIdent.js", "getProcessForPort.js", + "globby.js", "ignoredFiles.js", "immer.js", "InlineChunkHtmlPlugin.js", @@ -53,6 +54,7 @@ "filesize": "3.6.1", "find-up": "3.0.0", "global-modules": "1.0.0", + "globby": "8.0.1", "gzip-size": "5.0.0", "immer": "1.7.2", "inquirer": "6.2.0", diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index 4716345b75c..8a23af48a6e 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -39,6 +39,9 @@ const publicUrl = ''; // Get environment variables to inject into our app. const env = getClientEnvironment(publicUrl); +// Check if TypeScript is setup +const useTypeScript = fs.existsSync(paths.appTsConfig); + // style files regexes const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/; @@ -150,7 +153,9 @@ module.exports = { // https://github.com/facebook/create-react-app/issues/290 // `web` extension prefixes have been added for better support // for React Native Web. - extensions: paths.moduleFileExtensions.map(ext => `.${ext}`), + extensions: paths.moduleFileExtensions + .map(ext => `.${ext}`) + .filter(ext => useTypeScript || !ext.includes('ts')), alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ @@ -411,7 +416,7 @@ module.exports = { publicPath: publicPath, }), // TypeScript type checking - fs.existsSync(paths.appTsConfig) && + useTypeScript && new ForkTsCheckerWebpackPlugin({ typescript: resolve.sync('typescript', { basedir: paths.appNodeModules, diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js index bbe9842fd68..654fb3390a2 100644 --- a/packages/react-scripts/config/webpack.config.prod.js +++ b/packages/react-scripts/config/webpack.config.prod.js @@ -57,6 +57,9 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') { throw new Error('Production builds must have NODE_ENV=production.'); } +// Check if TypeScript is setup +const useTypeScript = fs.existsSync(paths.appTsConfig); + // style files regexes const cssRegex = /\.css$/; const cssModuleRegex = /\.module\.css$/; @@ -224,7 +227,9 @@ module.exports = { // https://github.com/facebook/create-react-app/issues/290 // `web` extension prefixes have been added for better support // for React Native Web. - extensions: paths.moduleFileExtensions.map(ext => `.${ext}`), + extensions: paths.moduleFileExtensions + .map(ext => `.${ext}`) + .filter(ext => useTypeScript || !ext.includes('ts')), alias: { // Support React Native Web // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ diff --git a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js index 50491825da3..b1f1d49c926 100644 --- a/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js +++ b/packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js @@ -15,16 +15,33 @@ const path = require('path'); const paths = require('../../config/paths'); const os = require('os'); const immer = require('react-dev-utils/immer').produce; +const globby = require('react-dev-utils/globby').sync; function writeJson(fileName, object) { fs.writeFileSync(fileName, JSON.stringify(object, null, 2) + os.EOL); } +function verifyNoTypeScript() { + const typescriptFiles = globby('**/*.(ts|tsx)', { cwd: paths.appSrc }); + if (typescriptFiles.length > 0) { + console.warn( + chalk.yellow( + `We detected TypeScript in your project (${chalk.bold( + `src${path.sep}${typescriptFiles[0]}` + )}) and created a ${chalk.bold('tsconfig.json')} file for you.` + ) + ); + console.warn(); + return false; + } + return true; +} + function verifyTypeScriptSetup() { let firstTimeSetup = false; if (!fs.existsSync(paths.appTsConfig)) { - if (!paths.appIndexJs.match(/\.tsx?$/)) { + if (verifyNoTypeScript()) { return; } writeJson(paths.appTsConfig, {}); @@ -41,14 +58,12 @@ function verifyTypeScriptSetup() { })); } catch (_) { console.error( - chalk.red( - 'We detected a', - chalk.bold('tsconfig.json'), - "in your package root but couldn't find an installation of", - chalk.bold('typescript') + '.' + chalk.bold.red( + `It looks like you're trying to use TypeScript but do not have ${chalk.bold( + 'typescript' + )} installed.` ) ); - console.error(); console.error( chalk.bold( 'Please install', @@ -60,9 +75,11 @@ function verifyTypeScriptSetup() { ) ); console.error( - 'If you are not trying to use TypeScript, please remove the ' + - chalk.cyan('tsconfig.json') + - ' file from your package root.' + chalk.bold( + 'If you are not trying to use TypeScript, please remove the ' + + chalk.cyan('tsconfig.json') + + ' file from your package root (and any TypeScript files).' + ) ); console.error(); process.exit(1); diff --git a/test/fixtures/typescript/package.json b/test/fixtures/typescript/package.json index 0967ef424bc..c001bab2cd1 100644 --- a/test/fixtures/typescript/package.json +++ b/test/fixtures/typescript/package.json @@ -1 +1,5 @@ -{} +{ + "dependencies": { + "typescript": "3.1.3" + } +}