diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md index 6a6ab28b32..262b9a5168 100644 --- a/packages/react-dev-utils/README.md +++ b/packages/react-dev-utils/README.md @@ -231,11 +231,11 @@ var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); var compiler = webpack(config); -compiler.hooks.invalid.tap('invalid', function() { +compiler.hooks.invalid.tap('invalid', function () { console.log('Compiling...'); }); -compiler.hooks.done.tap('done', function(stats) { +compiler.hooks.done.tap('done', function (stats) { var rawMessages = stats.toJson({}, true); var messages = formatWebpackMessages(rawMessages); if (!messages.errors.length && !messages.warnings.length) { @@ -338,11 +338,9 @@ The `args` object accepts a number of properties: - **appName** `string`: The name that will be printed to the terminal. - **config** `Object`: The webpack configuration options to be provided to the webpack constructor. -- **devSocket** `Object`: Required if `useTypeScript` is `true`. This object should include `errors` and `warnings` which are functions accepting an array of errors or warnings emitted by the type checking. This is useful when running `fork-ts-checker-webpack-plugin` with `async: true` to report errors that are emitted after the webpack build is complete. - **urls** `Object`: To provide the `urls` argument, use `prepareUrls()` described below. - **useYarn** `boolean`: If `true`, yarn instructions will be emitted in the terminal instead of npm. - **useTypeScript** `boolean`: If `true`, TypeScript type checking will be enabled. Be sure to provide the `devSocket` argument above if this is set to `true`. -- **tscCompileOnError** `boolean`: If `true`, errors in TypeScript type checking will not prevent start script from running app, and will not cause build script to exit unsuccessfully. Also downgrades all TypeScript type checking error messages to warning messages. - **webpack** `function`: A reference to the webpack constructor. ##### `prepareProxy(proxySetting: string, appPublicFolder: string, servedPathname: string): Object` diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index a4aafedd0a..579124724f 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -17,7 +17,6 @@ const inquirer = require('inquirer'); const clearConsole = require('./clearConsole'); const formatWebpackMessages = require('./formatWebpackMessages'); const getProcessForPort = require('./getProcessForPort'); -const typescriptFormatter = require('./typescriptFormatter'); const forkTsCheckerWebpackPlugin = require('./ForkTsCheckerWebpackPlugin'); const isInteractive = process.stdout.isTTY; @@ -104,11 +103,9 @@ function printInstructions(appName, urls, useYarn) { function createCompiler({ appName, config, - devSocket, urls, useYarn, useTypeScript, - tscCompileOnError, webpack, }) { // "Compiler" is a low-level interface to webpack. @@ -137,28 +134,16 @@ function createCompiler({ let isFirstCompile = true; let tsMessagesPromise; - let tsMessagesResolver; if (useTypeScript) { - compiler.hooks.beforeCompile.tap('beforeCompile', () => { - tsMessagesPromise = new Promise(resolve => { - tsMessagesResolver = msgs => resolve(msgs); - }); - }); - forkTsCheckerWebpackPlugin .getCompilerHooks(compiler) - .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => { - const allMsgs = [...diagnostics, ...lints]; - const format = message => - `${message.file}\n${typescriptFormatter(message, true)}`; - - tsMessagesResolver({ - errors: allMsgs.filter(msg => msg.severity === 'error').map(format), - warnings: allMsgs - .filter(msg => msg.severity === 'warning') - .map(format), - }); + .waiting.tap('awaitingTypeScriptCheck', () => { + console.log( + chalk.yellow( + 'Files successfully emitted, waiting for typecheck results...' + ) + ); }); } @@ -180,48 +165,6 @@ function createCompiler({ errors: true, }); - if (useTypeScript && statsData.errors.length === 0) { - const delayedMsg = setTimeout(() => { - console.log( - chalk.yellow( - 'Files successfully emitted, waiting for typecheck results...' - ) - ); - }, 100); - - const messages = await tsMessagesPromise; - clearTimeout(delayedMsg); - if (tscCompileOnError) { - statsData.warnings.push(...messages.errors); - } else { - statsData.errors.push(...messages.errors); - } - statsData.warnings.push(...messages.warnings); - - // Push errors and warnings into compilation result - // to show them after page refresh triggered by user. - if (tscCompileOnError) { - stats.compilation.warnings.push(...messages.errors); - } else { - stats.compilation.errors.push(...messages.errors); - } - stats.compilation.warnings.push(...messages.warnings); - - if (messages.errors.length > 0) { - if (tscCompileOnError) { - devSocket.warnings(messages.errors); - } else { - devSocket.errors(messages.errors); - } - } else if (messages.warnings.length > 0) { - devSocket.warnings(messages.warnings); - } - - if (isInteractive) { - clearConsole(); - } - } - const messages = formatWebpackMessages(statsData); const isSuccessful = !messages.errors.length && !messages.warnings.length; if (isSuccessful) { diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json index 972539eb17..742268da52 100644 --- a/packages/react-dev-utils/package.json +++ b/packages/react-dev-utils/package.json @@ -62,7 +62,7 @@ "escape-string-regexp": "2.0.0", "filesize": "6.1.0", "find-up": "4.1.0", - "fork-ts-checker-webpack-plugin": "4.1.6", + "fork-ts-checker-webpack-plugin": "6.0.5", "global-modules": "2.0.0", "globby": "11.0.1", "gzip-size": "5.1.1", diff --git a/packages/react-dev-utils/typescriptFormatter.js b/packages/react-dev-utils/typescriptFormatter.js deleted file mode 100644 index 1fb1276c6b..0000000000 --- a/packages/react-dev-utils/typescriptFormatter.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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'; - -const os = require('os'); -const codeFrame = require('@babel/code-frame').codeFrameColumns; -const chalk = require('chalk'); -const fs = require('fs'); - -const issueOrigins = { - typescript: 'TypeScript', - internal: 'fork-ts-checker-webpack-plugin', -}; - -function formatter(issue) { - const { origin, severity, file, line, message, code, character } = issue; - - const colors = new chalk.constructor(); - const messageColor = severity === 'warning' ? colors.yellow : colors.red; - const fileAndNumberColor = colors.bold.cyan; - - const source = file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8'); - const frame = source - ? codeFrame(source, { start: { line: line, column: character } }) - .split('\n') - .map(str => ' ' + str) - .join(os.EOL) - : ''; - - return [ - messageColor.bold(`${issueOrigins[origin]} ${severity.toLowerCase()} in `) + - fileAndNumberColor(`${file}(${line},${character})`) + - messageColor(':'), - message + ' ' + messageColor.underline(`TS${code}`), - '', - frame, - ].join(os.EOL); -} - -module.exports = formatter; diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 8efff0b96c..8c286ed356 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -32,7 +32,6 @@ const modules = require('./modules'); const getClientEnvironment = require('./env'); const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin'); -const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); // @remove-on-eject-begin const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); @@ -718,33 +717,49 @@ module.exports = function (webpackEnv) { // TypeScript type checking useTypeScript && new ForkTsCheckerWebpackPlugin({ - typescript: resolve.sync('typescript', { - basedir: paths.appNodeModules, - }), async: isEnvDevelopment, - checkSyntacticErrors: true, - resolveModuleNameModule: process.versions.pnp - ? `${__dirname}/pnpTs.js` - : undefined, - resolveTypeReferenceDirectiveModule: process.versions.pnp - ? `${__dirname}/pnpTs.js` - : undefined, - tsconfig: paths.appTsConfig, - reportFiles: [ + typescript: { + typescriptPath: resolve.sync('typescript', { + basedir: paths.appNodeModules, + }), + configOverwrite: { + compilerOptions: { + sourceMap: isEnvProduction + ? shouldUseSourceMap + : isEnvDevelopment, + skipLibCheck: true, + inlineSourceMap: false, + declarationMap: false, + noEmit: true, + incremental: true, + }, + }, + context: paths.appPath, + diagnosticOptions: { + syntactic: true, + }, + mode: 'write-references', + // profile: true, + }, + issue: { // This one is specifically to match during CI tests, // as micromatch doesn't match // '../cra-template-typescript/template/src/App.tsx' // otherwise. - '../**/src/**/*.{ts,tsx}', - '**/src/**/*.{ts,tsx}', - '!**/src/**/__tests__/**', - '!**/src/**/?(*.)(spec|test).*', - '!**/src/setupProxy.*', - '!**/src/setupTests.*', - ], - silent: true, - // The formatter is invoked directly in WebpackDevServerUtils during development - formatter: isEnvProduction ? typescriptFormatter : undefined, + include: [ + '../**/src/**/*.{ts,tsx}', + '**/src/**/*.{ts,tsx}', + ].map(file => ({ file })), + exclude: [ + '**/src/**/__tests__/**', + '**/src/**/?(*.)(spec|test).*', + '**/src/setupProxy.*', + '**/src/setupTests.*', + ].map(file => ({ file })), + }, + logger: { + infrastructure: 'silent', + }, }), new ESLintPlugin({ // Plugin options diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index ffbb15d120..4eb6ffdcf4 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -118,11 +118,9 @@ checkBrowsers(paths.appPath, isInteractive) const compiler = createCompiler({ appName, config, - devSocket, urls, useYarn, useTypeScript, - tscCompileOnError, webpack, }); // Load proxy config