TypeScript report on active pages only (#8703)

* TypeScript report on active pages only
The TypeScript integration needs to report on active pages only.
When inactive pages are reported, they block the compilation and prevent the user from fixing the error (because the file isn't watched).

We cannot add the file to the webpack watcher because the compilation has already been sealed.

* Remove TODO message

* Test that inactive pages are not type checked
This commit is contained in:
Joe Haddad 2019-09-11 13:06:48 -04:00 committed by GitHub
parent e5aa9614e1
commit fcadad9960
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 9 deletions

View file

@ -16,6 +16,11 @@ export function startedDevelopmentServer(appUrl: string) {
let previousClient: any = null
let previousServer: any = null
type CompilerDiagnosticsWithFile = {
errors: { file: string | undefined; message: string }[] | null
warnings: { file: string | undefined; message: string }[] | null
}
type CompilerDiagnostics = {
errors: string[] | null
warnings: string[] | null
@ -231,8 +236,8 @@ export function watchCompilers(
hasTypeChecking: boolean,
onEvent: (status: WebpackStatus) => void
) {
let tsMessagesPromise: Promise<CompilerDiagnostics> | undefined
let tsMessagesResolver: (diagnostics: CompilerDiagnostics) => void
let tsMessagesPromise: Promise<CompilerDiagnosticsWithFile> | undefined
let tsMessagesResolver: (diagnostics: CompilerDiagnosticsWithFile) => void
compiler.hooks.invalid.tap(`NextJsInvalid-${key}`, () => {
tsMessagesPromise = undefined
@ -259,10 +264,16 @@ export function watchCompilers(
const errors = allMsgs
.filter(msg => msg.severity === 'error')
.map(format)
.map(d => ({
file: d.file,
message: format(d),
}))
const warnings = allMsgs
.filter(msg => msg.severity === 'warning')
.map(format)
.map(d => ({
file: d.file,
message: format(d),
}))
tsMessagesResolver({
errors: errors.length ? errors : null,
@ -298,8 +309,29 @@ export function watchCompilers(
return
}
stats.compilation.errors.push(...(typeMessages.errors || []))
stats.compilation.warnings.push(...(typeMessages.warnings || []))
const reportFiles = stats.compilation.modules
.map((m: any) => m.resource)
.filter(Boolean)
let filteredErrors = typeMessages.errors
? typeMessages.errors
.filter(({ file }) => file && reportFiles.includes(file))
.map(({ message }) => message)
: null
if (filteredErrors && filteredErrors.length < 1) {
filteredErrors = null
}
let filteredWarnings = typeMessages.warnings
? typeMessages.warnings
.filter(({ file }) => file && reportFiles.includes(file))
.map(({ message }) => message)
: null
if (filteredWarnings && filteredWarnings.length < 1) {
filteredWarnings = null
}
stats.compilation.errors.push(...(filteredErrors || []))
stats.compilation.warnings.push(...(filteredWarnings || []))
onTypeChecked({
errors: stats.compilation.errors.length
? stats.compilation.errors
@ -312,10 +344,10 @@ export function watchCompilers(
onEvent({
loading: false,
typeChecking: false,
errors: typeMessages.errors,
errors: filteredErrors,
warnings: hasWarnings
? [...warnings, ...(typeMessages.warnings || [])]
: typeMessages.warnings,
? [...warnings, ...(filteredWarnings || [])]
: filteredWarnings,
})
})
}

View file

@ -2,6 +2,7 @@
/* global jasmine */
import { join } from 'path'
import cheerio from 'cheerio'
import { writeFile, remove } from 'fs-extra'
import {
renderViaHTTP,
nextBuild,
@ -34,6 +35,28 @@ describe('TypeScript Features', () => {
const $ = await get$('/hello')
expect($('body').text()).toMatch(/Hello World/)
})
it('should not fail to render when an inactive page has an error', async () => {
await killApp(app)
let evilFile = join(appDir, 'pages', 'evil.tsx')
try {
await writeFile(
evilFile,
`import React from 'react'
export default function EvilPage(): JSX.Element {
return <div notARealProp />
}
`
)
app = await launchApp(appDir, appPort)
const $ = await get$('/hello')
expect($('body').text()).toMatch(/Hello World/)
} finally {
await remove(evilFile)
}
})
})
it('should compile the app', async () => {