From 883426e9377887ddb3b99fc6f207144f61e627d2 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 20 Dec 2022 20:11:39 +0100 Subject: [PATCH 1/2] honour distDir for type generation --- packages/next/build/index.ts | 3 +++ .../next/lib/typescript/diagnosticFormatter.ts | 3 ++- packages/next/lib/typescript/runTypeCheck.ts | 13 +++++++++++-- .../typescript/writeConfigurationDefaults.ts | 18 +++++++++--------- packages/next/lib/verifyTypeScriptSetup.ts | 6 +++++- packages/next/server/dev/next-dev-server.ts | 1 + 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index b67e9ad45615fdb..ba851acde5aef7a 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -171,6 +171,7 @@ type SingleCompilerResult = { */ function verifyTypeScriptSetup( dir: string, + distDir: string, intentDirs: string[], typeCheckPreflight: boolean, tsconfigPath: string, @@ -197,6 +198,7 @@ function verifyTypeScriptSetup( return typeCheckWorker .verifyTypeScriptSetup({ dir, + distDir, intentDirs, typeCheckPreflight, tsconfigPath, @@ -409,6 +411,7 @@ export default async function build( .traceAsyncFn(() => verifyTypeScriptSetup( dir, + config.distDir, [pagesDir, appDir].filter(Boolean) as string[], !ignoreTypeScriptErrors, config.typescript.tsconfigPath, diff --git a/packages/next/lib/typescript/diagnosticFormatter.ts b/packages/next/lib/typescript/diagnosticFormatter.ts index d5f8ef5c9e976dd..b4e914f34e38940 100644 --- a/packages/next/lib/typescript/diagnosticFormatter.ts +++ b/packages/next/lib/typescript/diagnosticFormatter.ts @@ -155,13 +155,14 @@ function getFormattedLayoutAndPageDiagnosticMessageText( export async function getFormattedDiagnostic( ts: typeof import('typescript'), baseDir: string, + distDir: string, diagnostic: import('typescript').Diagnostic, isAppDirEnabled?: boolean ): Promise { // If the error comes from .next/types/, we handle it specially. const isLayoutOrPageError = isAppDirEnabled && - diagnostic.file?.fileName.includes(path.join(baseDir, '.next', 'types')) + diagnostic.file?.fileName.includes(path.join(baseDir, distDir, 'types')) let message = '' diff --git a/packages/next/lib/typescript/runTypeCheck.ts b/packages/next/lib/typescript/runTypeCheck.ts index 561ff160f1a0ee8..51ba2b1722373e7 100644 --- a/packages/next/lib/typescript/runTypeCheck.ts +++ b/packages/next/lib/typescript/runTypeCheck.ts @@ -20,6 +20,7 @@ export interface TypeCheckResult { export async function runTypeCheck( ts: typeof import('typescript'), baseDir: string, + distDir: string, tsConfigPath: string, cacheDir?: string, isAppDirEnabled?: boolean @@ -97,14 +98,22 @@ export async function runTypeCheck( if (firstError) { throw new CompileError( - await getFormattedDiagnostic(ts, baseDir, firstError, isAppDirEnabled) + await getFormattedDiagnostic( + ts, + baseDir, + distDir, + firstError, + isAppDirEnabled + ) ) } const warnings = await Promise.all( allDiagnostics .filter((d) => d.category === DiagnosticCategory.Warning) - .map((d) => getFormattedDiagnostic(ts, baseDir, d, isAppDirEnabled)) + .map((d) => + getFormattedDiagnostic(ts, baseDir, distDir, d, isAppDirEnabled) + ) ) return { hasWarnings: true, diff --git a/packages/next/lib/typescript/writeConfigurationDefaults.ts b/packages/next/lib/typescript/writeConfigurationDefaults.ts index 4cc3bb2e25dc4e6..fc25ba0480498b0 100644 --- a/packages/next/lib/typescript/writeConfigurationDefaults.ts +++ b/packages/next/lib/typescript/writeConfigurationDefaults.ts @@ -103,7 +103,8 @@ export async function writeConfigurationDefaults( ts: typeof import('typescript'), tsConfigPath: string, isFirstTimeSetup: boolean, - isAppDirEnabled: boolean + isAppDirEnabled: boolean, + distDir: string ): Promise { if (isFirstTimeSetup) { await fs.writeFile(tsConfigPath, '{}' + os.EOL) @@ -162,28 +163,27 @@ export async function writeConfigurationDefaults( } } + const nextAppTypes = `${distDir}/types/**/*.ts` + if (!('include' in rawConfig)) { userTsConfig.include = isAppDirEnabled - ? ['next-env.d.ts', '.next/types/**/*.ts', '**/*.ts', '**/*.tsx'] + ? ['next-env.d.ts', nextAppTypes, '**/*.ts', '**/*.tsx'] : ['next-env.d.ts', '**/*.ts', '**/*.tsx'] suggestedActions.push( chalk.cyan('include') + ' was set to ' + chalk.bold( isAppDirEnabled - ? `['next-env.d.ts', '.next/types/**/*.ts', '**/*.ts', '**/*.tsx']` + ? `['next-env.d.ts', '${nextAppTypes}', '**/*.ts', '**/*.tsx']` : `['next-env.d.ts', '**/*.ts', '**/*.tsx']` ) ) - } else if ( - isAppDirEnabled && - !rawConfig.include.includes('.next/types/**/*.ts') - ) { - userTsConfig.include.push('.next/types/**/*.ts') + } else if (isAppDirEnabled && !rawConfig.include.includes(nextAppTypes)) { + userTsConfig.include.push(nextAppTypes) suggestedActions.push( chalk.cyan('include') + ' was updated to add ' + - chalk.bold(`'.next/types/**/*.ts'`) + chalk.bold(`'${nextAppTypes}'`) ) } diff --git a/packages/next/lib/verifyTypeScriptSetup.ts b/packages/next/lib/verifyTypeScriptSetup.ts index 2daa8b9ab1767d4..aefc72cea702808 100644 --- a/packages/next/lib/verifyTypeScriptSetup.ts +++ b/packages/next/lib/verifyTypeScriptSetup.ts @@ -39,6 +39,7 @@ const requiredPackages = [ export async function verifyTypeScriptSetup({ dir, + distDir, cacheDir, intentDirs, tsconfigPath, @@ -47,6 +48,7 @@ export async function verifyTypeScriptSetup({ isAppDirEnabled, }: { dir: string + distDir: string cacheDir?: string tsconfigPath: string intentDirs: string[] @@ -119,7 +121,8 @@ export async function verifyTypeScriptSetup({ ts, resolvedTsConfigPath, intent.firstTimeSetup, - isAppDirEnabled + isAppDirEnabled, + distDir ) // Write out the necessary `next-env.d.ts` file to correctly register // Next.js' types: @@ -137,6 +140,7 @@ export async function verifyTypeScriptSetup({ result = await runTypeCheck( ts, dir, + distDir, resolvedTsConfigPath, cacheDir, isAppDirEnabled diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 6741856f069b5be..5bb59120df523b1 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -674,6 +674,7 @@ export default class DevServer extends Server { this.verifyingTypeScript = true const verifyResult = await verifyTypeScriptSetup({ dir: this.dir, + distDir: this.nextConfig.distDir, intentDirs: [this.pagesDir, this.appDir].filter(Boolean) as string[], typeCheckPreflight: false, tsconfigPath: this.nextConfig.typescript.tsconfigPath, From 0caebacf8a466a9419fee16b9cbc8383580132ed Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 20 Dec 2022 22:49:14 +0100 Subject: [PATCH 2/2] honour distDir for type generation --- packages/next/build/webpack-config.ts | 8 +++++++- .../build/webpack/plugins/flight-types-plugin.ts | 16 ++++++++++++++-- .../next/lib/typescript/diagnosticFormatter.ts | 2 +- test/e2e/app-dir/app-typescript/next.config.js | 1 + test/e2e/app-dir/app-typescript/tsconfig.json | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index ad3220b0de6eb76..a323a2593497440 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -2115,7 +2115,13 @@ export default async function getBaseWebpackConfig( hasAppDir && !isClient && !dev && - new FlightTypesPlugin({ dir, appDir, dev, isEdgeServer }), + new FlightTypesPlugin({ + dir, + distDir: config.distDir, + appDir, + dev, + isEdgeServer, + }), !dev && isClient && !!config.experimental.sri?.algorithm && diff --git a/packages/next/build/webpack/plugins/flight-types-plugin.ts b/packages/next/build/webpack/plugins/flight-types-plugin.ts index aff833983aa69a0..3f41c5818adf1df 100644 --- a/packages/next/build/webpack/plugins/flight-types-plugin.ts +++ b/packages/next/build/webpack/plugins/flight-types-plugin.ts @@ -8,6 +8,7 @@ const PLUGIN_NAME = 'FlightTypesPlugin' interface Options { dir: string + distDir: string appDir: string dev: boolean isEdgeServer: boolean @@ -93,19 +94,29 @@ async function collectNamedSlots(layoutPath: string) { export class FlightTypesPlugin { dir: string + distDir: string appDir: string dev: boolean isEdgeServer: boolean constructor(options: Options) { this.dir = options.dir + this.distDir = options.distDir this.appDir = options.appDir this.dev = options.dev this.isEdgeServer = options.isEdgeServer } apply(compiler: webpack.Compiler) { - const assetPrefix = this.dev ? '..' : this.isEdgeServer ? '..' : '../..' + // From dist root to project root + const distDirRelative = path.relative(this.distDir + '/..', '.') + + // From asset root to dist root + const assetDirRelative = this.dev + ? '..' + : this.isEdgeServer + ? '..' + : '../..' const handleModule = async (_mod: webpack.Module, assets: any) => { if (_mod.layer !== WEBPACK_LAYERS.server) return @@ -127,11 +138,12 @@ export class FlightTypesPlugin { ) const relativeImportPath = path .join( + distDirRelative, path.relative(typePath, ''), relativePathToRoot.replace(/\.(js|jsx|ts|tsx|mjs)$/, '') ) .replace(/\\/g, '/') - const assetPath = assetPrefix + '/' + typePath.replace(/\\/g, '/') + const assetPath = assetDirRelative + '/' + typePath.replace(/\\/g, '/') if (IS_LAYOUT) { const slots = await collectNamedSlots(mod.resource) diff --git a/packages/next/lib/typescript/diagnosticFormatter.ts b/packages/next/lib/typescript/diagnosticFormatter.ts index b4e914f34e38940..390a5fe319485cc 100644 --- a/packages/next/lib/typescript/diagnosticFormatter.ts +++ b/packages/next/lib/typescript/diagnosticFormatter.ts @@ -162,7 +162,7 @@ export async function getFormattedDiagnostic( // If the error comes from .next/types/, we handle it specially. const isLayoutOrPageError = isAppDirEnabled && - diagnostic.file?.fileName.includes(path.join(baseDir, distDir, 'types')) + diagnostic.file?.fileName.startsWith(path.join(baseDir, distDir, 'types')) let message = '' diff --git a/test/e2e/app-dir/app-typescript/next.config.js b/test/e2e/app-dir/app-typescript/next.config.js index cfa3ac3d7aa94b3..add4f1eaf0a6073 100644 --- a/test/e2e/app-dir/app-typescript/next.config.js +++ b/test/e2e/app-dir/app-typescript/next.config.js @@ -1,4 +1,5 @@ module.exports = { + distDir: 'dist/.next', experimental: { appDir: true, }, diff --git a/test/e2e/app-dir/app-typescript/tsconfig.json b/test/e2e/app-dir/app-typescript/tsconfig.json index 67524906ed056de..3c68d5117f0be85 100644 --- a/test/e2e/app-dir/app-typescript/tsconfig.json +++ b/test/e2e/app-dir/app-typescript/tsconfig.json @@ -20,6 +20,6 @@ } ] }, - "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] }