Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Honour distDir in type generation #44207

Merged
merged 2 commits into from Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/next/build/index.ts
Expand Up @@ -171,6 +171,7 @@ type SingleCompilerResult = {
*/
function verifyTypeScriptSetup(
dir: string,
distDir: string,
intentDirs: string[],
typeCheckPreflight: boolean,
tsconfigPath: string,
Expand All @@ -197,6 +198,7 @@ function verifyTypeScriptSetup(
return typeCheckWorker
.verifyTypeScriptSetup({
dir,
distDir,
intentDirs,
typeCheckPreflight,
tsconfigPath,
Expand Down Expand Up @@ -409,6 +411,7 @@ export default async function build(
.traceAsyncFn(() =>
verifyTypeScriptSetup(
dir,
config.distDir,
[pagesDir, appDir].filter(Boolean) as string[],
!ignoreTypeScriptErrors,
config.typescript.tsconfigPath,
Expand Down
8 changes: 7 additions & 1 deletion packages/next/build/webpack-config.ts
Expand Up @@ -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 &&
Expand Down
16 changes: 14 additions & 2 deletions packages/next/build/webpack/plugins/flight-types-plugin.ts
Expand Up @@ -8,6 +8,7 @@ const PLUGIN_NAME = 'FlightTypesPlugin'

interface Options {
dir: string
distDir: string
appDir: string
dev: boolean
isEdgeServer: boolean
Expand Down Expand Up @@ -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 + '/..', '.')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're not the same I believe.


// 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
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion packages/next/lib/typescript/diagnosticFormatter.ts
Expand Up @@ -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<string> {
// 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.startsWith(path.join(baseDir, distDir, 'types'))

let message = ''

Expand Down
13 changes: 11 additions & 2 deletions packages/next/lib/typescript/runTypeCheck.ts
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
18 changes: 9 additions & 9 deletions packages/next/lib/typescript/writeConfigurationDefaults.ts
Expand Up @@ -103,7 +103,8 @@ export async function writeConfigurationDefaults(
ts: typeof import('typescript'),
tsConfigPath: string,
isFirstTimeSetup: boolean,
isAppDirEnabled: boolean
isAppDirEnabled: boolean,
distDir: string
): Promise<void> {
if (isFirstTimeSetup) {
await fs.writeFile(tsConfigPath, '{}' + os.EOL)
Expand Down Expand Up @@ -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}'`)
)
}

Expand Down
6 changes: 5 additions & 1 deletion packages/next/lib/verifyTypeScriptSetup.ts
Expand Up @@ -39,6 +39,7 @@ const requiredPackages = [

export async function verifyTypeScriptSetup({
dir,
distDir,
cacheDir,
intentDirs,
tsconfigPath,
Expand All @@ -47,6 +48,7 @@ export async function verifyTypeScriptSetup({
isAppDirEnabled,
}: {
dir: string
distDir: string
cacheDir?: string
tsconfigPath: string
intentDirs: string[]
Expand Down Expand Up @@ -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:
Expand All @@ -137,6 +140,7 @@ export async function verifyTypeScriptSetup({
result = await runTypeCheck(
ts,
dir,
distDir,
resolvedTsConfigPath,
cacheDir,
isAppDirEnabled
Expand Down
1 change: 1 addition & 0 deletions packages/next/server/dev/next-dev-server.ts
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions test/e2e/app-dir/app-typescript/next.config.js
@@ -1,4 +1,5 @@
module.exports = {
distDir: 'dist/.next',
experimental: {
appDir: true,
},
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/app-dir/app-typescript/tsconfig.json
Expand Up @@ -20,6 +20,6 @@
}
]
},
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}