Skip to content

Commit

Permalink
Automatically setup TypeScript when detected (facebook#5549)
Browse files Browse the repository at this point in the history
* Don't resolve TS files if it's not detected in the project

* Automatically create tsconfig.json file for user

* Remove always false check

* Add missing file

* Don't filter paths too early
  • Loading branch information
Timer authored and chanand committed Oct 25, 2018
1 parent d5a8065 commit 1877fd5
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 14 deletions.
12 changes: 12 additions & 0 deletions packages/react-dev-utils/globby.js
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions packages/react-dev-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"getCacheIdentifier.js",
"getCSSModuleLocalIdent.js",
"getProcessForPort.js",
"globby.js",
"ignoredFiles.js",
"immer.js",
"InlineChunkHtmlPlugin.js",
Expand Down Expand Up @@ -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",
Expand Down
9 changes: 7 additions & 2 deletions packages/react-scripts/config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -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$/;
Expand Down Expand Up @@ -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/
Expand Down Expand Up @@ -412,7 +417,7 @@ module.exports = {
publicPath: publicPath,
}),
// TypeScript type checking
fs.existsSync(paths.appTsConfig) &&
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
Expand Down
7 changes: 6 additions & 1 deletion packages/react-scripts/config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -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$/;
Expand Down Expand Up @@ -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/
Expand Down
37 changes: 27 additions & 10 deletions packages/react-scripts/scripts/utils/verifyTypeScriptSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, {});
Expand All @@ -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',
Expand All @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion test/fixtures/typescript/package.json
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{}
{
"dependencies": {
"typescript": "3.1.3"
}
}

0 comments on commit 1877fd5

Please sign in to comment.