-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace
fork-ts-checker-webpack-plugin
with faster alternative (#13529
) This removes `fork-ts-checker-webpack-plugin` and instead directly calls the TypeScript API. This is approximately 10x faster. Base build: 7s (no TypeScript features enabled) - `[email protected]`: 90s, computer sounds like an airplane - `[email protected]`: 84s, computer did **not** sound like an airplane - `[email protected]`: 90s, regressed - `npx tsc -p tsconfig.json --noEmit`: 12s (time: `18.57s user 0.97s system 169% cpu 11.525 total`) - **This PR**: 22s, expected to get better when we run this as a side-car All of these tests were run 3 times and repeat-accurate within +/- 0.5s.
- Loading branch information
Showing
12 changed files
with
186 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export class TypeScriptCompileError extends Error {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { codeFrameColumns } from '@babel/code-frame' | ||
import chalk from 'next/dist/compiled/chalk' | ||
import path from 'path' | ||
|
||
export enum DiagnosticCategory { | ||
Warning = 0, | ||
Error = 1, | ||
Suggestion = 2, | ||
Message = 3, | ||
} | ||
|
||
export async function getFormattedDiagnostic( | ||
ts: typeof import('typescript'), | ||
baseDir: string, | ||
diagnostic: import('typescript').Diagnostic | ||
): Promise<string> { | ||
let message = '' | ||
|
||
const reason = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') | ||
const category = diagnostic.category | ||
switch (category) { | ||
// Warning | ||
case DiagnosticCategory.Warning: { | ||
message += chalk.yellow.bold('Type warning') + ': ' | ||
break | ||
} | ||
// Error | ||
case DiagnosticCategory.Error: { | ||
message += chalk.red.bold('Type error') + ': ' | ||
break | ||
} | ||
// 2 = Suggestion, 3 = Message | ||
case DiagnosticCategory.Suggestion: | ||
case DiagnosticCategory.Message: | ||
default: { | ||
message += chalk.cyan.bold(category === 2 ? 'Suggestion' : 'Info') + ': ' | ||
break | ||
} | ||
} | ||
message += reason + '\n' | ||
|
||
if (diagnostic.file) { | ||
const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!) | ||
const line = pos.line + 1 | ||
const character = pos.character + 1 | ||
|
||
let fileName = path.posix.normalize( | ||
path.relative(baseDir, diagnostic.file.fileName).replace(/\\/, '/') | ||
) | ||
if (!fileName.startsWith('.')) { | ||
fileName = './' + fileName | ||
} | ||
|
||
message = | ||
chalk.cyan(fileName) + | ||
':' + | ||
chalk.yellow(line.toString()) + | ||
':' + | ||
chalk.yellow(character.toString()) + | ||
'\n' + | ||
message | ||
|
||
message += | ||
'\n' + | ||
codeFrameColumns( | ||
diagnostic.file.getFullText(diagnostic.file.getSourceFile()), | ||
{ | ||
start: { line: line, column: character }, | ||
}, | ||
{ forceColor: true } | ||
) | ||
} | ||
|
||
return message | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { | ||
DiagnosticCategory, | ||
getFormattedDiagnostic, | ||
} from './diagnosticFormatter' | ||
import { getTypeScriptConfiguration } from './getTypeScriptConfiguration' | ||
import { TypeScriptCompileError } from './TypeScriptCompileError' | ||
import { getRequiredConfiguration } from './writeConfigurationDefaults' | ||
|
||
export interface TypeCheckResult { | ||
hasWarnings: boolean | ||
warnings?: string[] | ||
} | ||
|
||
export async function runTypeCheck( | ||
ts: typeof import('typescript'), | ||
baseDir: string, | ||
tsConfigPath: string | ||
): Promise<TypeCheckResult> { | ||
const effectiveConfiguration = await getTypeScriptConfiguration( | ||
ts, | ||
tsConfigPath | ||
) | ||
|
||
if (effectiveConfiguration.fileNames.length < 1) { | ||
return { hasWarnings: false } | ||
} | ||
const requiredConfig = getRequiredConfiguration(ts) | ||
|
||
const program = ts.createProgram(effectiveConfiguration.fileNames, { | ||
...effectiveConfiguration.options, | ||
...requiredConfig, | ||
noEmit: true, | ||
}) | ||
const result = program.emit() | ||
|
||
const regexIgnoredFile = /[\\/]__(?:tests|mocks)__[\\/]|(?:spec|test)\.[^\\/]+$/ | ||
const allDiagnostics = ts | ||
.getPreEmitDiagnostics(program) | ||
.concat(result.diagnostics) | ||
.filter((d) => !(d.file && regexIgnoredFile.test(d.file.fileName))) | ||
|
||
const firstError = | ||
allDiagnostics.find( | ||
(d) => d.category === DiagnosticCategory.Error && Boolean(d.file) | ||
) ?? allDiagnostics.find((d) => d.category === DiagnosticCategory.Error) | ||
|
||
if (firstError) { | ||
throw new TypeScriptCompileError( | ||
await getFormattedDiagnostic(ts, baseDir, firstError) | ||
) | ||
} | ||
|
||
const warnings = await Promise.all( | ||
allDiagnostics | ||
.filter((d) => d.category === DiagnosticCategory.Warning) | ||
.map((d) => getFormattedDiagnostic(ts, baseDir, d)) | ||
) | ||
return { hasWarnings: true, warnings } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.