Skip to content

Commit 4e8fac9

Browse files
sokrakodiakhq[bot]
andauthored
cache typechecking with incremental compilation (vercel#24559)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 42c4743 commit 4e8fac9

File tree

24 files changed

+113
-42
lines changed

24 files changed

+113
-42
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
"tailwindcss": "1.1.3",
125125
"taskr": "1.1.0",
126126
"tree-kill": "1.2.2",
127-
"typescript": "3.8.3",
127+
"typescript": "4.3.0-beta",
128128
"wait-port": "0.2.2",
129129
"web-streams-polyfill": "2.1.1",
130130
"webpack-bundle-analyzer": "4.3.0",

packages/next/build/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ export default async function build(
146146

147147
const { headers, rewrites, redirects } = customRoutes
148148

149+
const cacheDir = path.join(distDir, 'cache')
149150
if (ciEnvironment.isCI && !ciEnvironment.hasNextSupport) {
150-
const cacheDir = path.join(distDir, 'cache')
151151
const hasCache = await fileExists(cacheDir)
152152

153153
if (!hasCache) {
@@ -193,7 +193,7 @@ export default async function build(
193193
const verifyResult = await nextBuildSpan
194194
.traceChild('verify-typescript-setup')
195195
.traceAsyncFn(() =>
196-
verifyTypeScriptSetup(dir, pagesDir, !ignoreTypeScriptErrors)
196+
verifyTypeScriptSetup(dir, pagesDir, !ignoreTypeScriptErrors, cacheDir)
197197
)
198198

199199
const typeCheckEnd = process.hrtime(typeCheckStart)

packages/next/lib/typescript/runTypeCheck.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'path'
12
import {
23
DiagnosticCategory,
34
getFormattedDiagnostic,
@@ -18,7 +19,8 @@ export interface TypeCheckResult {
1819
export async function runTypeCheck(
1920
ts: typeof import('typescript'),
2021
baseDir: string,
21-
tsConfigPath: string
22+
tsConfigPath: string,
23+
cacheDir?: string
2224
): Promise<TypeCheckResult> {
2325
const effectiveConfiguration = await getTypeScriptConfiguration(
2426
ts,
@@ -35,11 +37,28 @@ export async function runTypeCheck(
3537
}
3638
const requiredConfig = getRequiredConfiguration(ts)
3739

38-
const program = ts.createProgram(effectiveConfiguration.fileNames, {
40+
const options = {
3941
...effectiveConfiguration.options,
4042
...requiredConfig,
4143
noEmit: true,
42-
})
44+
}
45+
46+
let program: import('typescript').Program
47+
let incremental = false
48+
if (options.incremental && cacheDir) {
49+
incremental = true
50+
const builderProgram = ts.createIncrementalProgram({
51+
rootNames: effectiveConfiguration.fileNames,
52+
options: {
53+
...options,
54+
incremental: true,
55+
tsBuildInfoFile: path.join(cacheDir, '.tsbuildinfo'),
56+
},
57+
})
58+
program = builderProgram.getProgram()
59+
} else {
60+
program = ts.createProgram(effectiveConfiguration.fileNames, options)
61+
}
4362
const result = program.emit()
4463

4564
// Intended to match:
@@ -79,6 +98,6 @@ export async function runTypeCheck(
7998
warnings,
8099
inputFilesCount: effectiveConfiguration.fileNames.length,
81100
totalFilesCount: program.getSourceFiles().length,
82-
incremental: false,
101+
incremental,
83102
}
84103
}

packages/next/lib/typescript/writeConfigurationDefaults.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { promises as fs } from 'fs'
22
import chalk from 'chalk'
33
import * as CommentJson from 'next/dist/compiled/comment-json'
4+
import semver from 'next/dist/compiled/semver'
45
import os from 'os'
56
import { getTypeScriptConfiguration } from './getTypeScriptConfiguration'
67

@@ -28,6 +29,9 @@ function getDesiredCompilerOptions(
2829
strict: { suggested: false },
2930
forceConsistentCasingInFileNames: { suggested: true },
3031
noEmit: { suggested: true },
32+
...(semver.gte(ts.version, '4.3.0-beta')
33+
? { incremental: { suggested: true } }
34+
: undefined),
3135

3236
// These values are required and cannot be changed by the user
3337
// Keep this in sync with the webpack config

packages/next/lib/verifyTypeScriptSetup.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import { writeConfigurationDefaults } from './typescript/writeConfigurationDefau
1515
export async function verifyTypeScriptSetup(
1616
dir: string,
1717
pagesDir: string,
18-
typeCheckPreflight: boolean
18+
typeCheckPreflight: boolean,
19+
cacheDir?: string
1920
): Promise<{ result?: TypeCheckResult; version: string | null }> {
2021
const tsConfigPath = path.join(dir, 'tsconfig.json')
2122

@@ -48,7 +49,7 @@ export async function verifyTypeScriptSetup(
4849
const { runTypeCheck } = require('./typescript/runTypeCheck')
4950

5051
// Verify the project passes type-checking before we go to webpack phase:
51-
result = await runTypeCheck(ts, dir, tsConfigPath)
52+
result = await runTypeCheck(ts, dir, tsConfigPath, cacheDir)
5253
}
5354
return { result, version: ts.version }
5455
} catch (err) {

packages/react-dev-overlay/src/internal/components/ShadowPortal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const ShadowPortal: React.FC<ShadowPortalProps> = function Portal({
1111
let mountNode = React.useRef<HTMLDivElement | null>(null)
1212
let portalNode = React.useRef<HTMLElement | null>(null)
1313
let shadowNode = React.useRef<ShadowRoot | null>(null)
14-
let [, forceUpdate] = React.useState()
14+
let [, forceUpdate] = React.useState<{} | undefined>()
1515

1616
React.useLayoutEffect(() => {
1717
const ownerDocument = mountNode.current!.ownerDocument!

test/integration/app-tree/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"strict": false,
88
"forceConsistentCasingInFileNames": true,
99
"noEmit": true,
10+
"incremental": true,
1011
"esModuleInterop": true,
1112
"module": "esnext",
1213
"moduleResolution": "node",

test/integration/custom-server-types/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"strict": false,
1111
"forceConsistentCasingInFileNames": true,
1212
"noEmit": true,
13+
"incremental": true,
1314
"moduleResolution": "node",
1415
"resolveJsonModule": true,
1516
"isolatedModules": true

test/integration/handle-non-page-in-pages/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"strict": false,
88
"forceConsistentCasingInFileNames": true,
99
"noEmit": true,
10+
"incremental": true,
1011
"esModuleInterop": true,
1112
"module": "esnext",
1213
"moduleResolution": "node",

test/integration/image-component/typescript-style/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"strict": true,
1111
"forceConsistentCasingInFileNames": true,
1212
"noEmit": true,
13+
"incremental": true,
1314
"moduleResolution": "node",
1415
"resolveJsonModule": true,
1516
"isolatedModules": true

0 commit comments

Comments
 (0)