Skip to content

Commit

Permalink
do Next.js version verification earlier and make it easy to grab the …
Browse files Browse the repository at this point in the history
…version after build command finished
  • Loading branch information
pieh committed Jun 14, 2024
1 parent c60ac69 commit 01168ef
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 25 deletions.
20 changes: 3 additions & 17 deletions src/build/content/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { prerelease, lt as semverLowerThan, lte as semverLowerThanOrEqual } from

import { RUN_CONFIG } from '../../run/constants.js'
import { PluginContext } from '../plugin-context.js'
import { verifyNextVersion } from '../verification.js'

const tracer = wrapTracer(trace.getTracer('Next runtime'))

Expand Down Expand Up @@ -292,26 +291,13 @@ export const copyNextDependencies = async (ctx: PluginContext): Promise<void> =>

await Promise.all(promises)

// detect if it might lead to a runtime issue and throw an error upfront on build time instead of silently failing during runtime
const serverHandlerRequire = createRequire(posixJoin(ctx.serverHandlerDir, ':internal:'))

let nextVersion: string | undefined
try {
const { version } = serverHandlerRequire('next/package.json')
if (version) {
nextVersion = version as string
}
} catch {
// failed to resolve package.json - currently this is resolvable in all known next versions, but if next implements
// exports map it still might be a problem in the future, so we are not breaking here
}

if (nextVersion) {
verifyNextVersion(ctx, nextVersion)

await patchNextModules(ctx, nextVersion, serverHandlerRequire.resolve)
if (ctx.nextVersion) {
await patchNextModules(ctx, ctx.nextVersion, serverHandlerRequire.resolve)
}

// detect if it might lead to a runtime issue and throw an error upfront on build time instead of silently failing during runtime
try {
const nextEntryAbsolutePath = serverHandlerRequire.resolve('next')
const nextRequire = createRequire(nextEntryAbsolutePath)
Expand Down
21 changes: 21 additions & 0 deletions src/build/plugin-context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { existsSync, readFileSync } from 'node:fs'
import { readFile } from 'node:fs/promises'
import { createRequire } from 'node:module'
import { join, relative, resolve } from 'node:path'
import { join as posixJoin } from 'node:path/posix'
import { fileURLToPath } from 'node:url'

import type {
Expand Down Expand Up @@ -313,6 +315,25 @@ export class PluginContext {
return JSON.parse(await readFile(join(this.publishDir, 'routes-manifest.json'), 'utf-8'))
}

#nextVersion: string | null | undefined = undefined

/**
* Get Next.js version that was used to build the site
*/
get nextVersion(): string | null {
if (this.#nextVersion === undefined) {
try {
const serverHandlerRequire = createRequire(posixJoin(this.standaloneRootDir, ':internal:'))
const { version } = serverHandlerRequire('next/package.json')
this.#nextVersion = version as string
} catch {
this.#nextVersion = null
}
}

return this.#nextVersion
}

/** Fails a build with a message and an optional error */
failBuild(message: string, error?: unknown): never {
return this.utils.build.failBuild(message, error instanceof Error ? { error } : undefined)
Expand Down
17 changes: 9 additions & 8 deletions src/build/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ export function verifyPublishDir(ctx: PluginContext) {
`Your publish directory does not contain expected Next.js build output. Please make sure you are using Next.js version (${SUPPORTED_NEXT_VERSIONS})`,
)
}

if (
ctx.nextVersion &&
!satisfies(ctx.nextVersion, SUPPORTED_NEXT_VERSIONS, { includePrerelease: true })
) {
ctx.failBuild(
`@netlify/plugin-next@5 requires Next.js version ${SUPPORTED_NEXT_VERSIONS}, but found ${ctx.nextVersion}. Please upgrade your project's Next.js version.`,
)
}
}
if (ctx.buildConfig.output === 'export') {
if (!ctx.exportDetail?.success) {
Expand All @@ -60,14 +69,6 @@ export function verifyPublishDir(ctx: PluginContext) {
}
}

export function verifyNextVersion(ctx: PluginContext, nextVersion: string): void | never {
if (!satisfies(nextVersion, SUPPORTED_NEXT_VERSIONS, { includePrerelease: true })) {
ctx.failBuild(
`@netlify/plugin-next@5 requires Next.js version ${SUPPORTED_NEXT_VERSIONS}, but found ${nextVersion}. Please upgrade your project's Next.js version.`,
)
}
}

export async function verifyNoAdvancedAPIRoutes(ctx: PluginContext) {
const apiRoutesConfigs = await getAPIRoutesConfigs(ctx)

Expand Down

0 comments on commit 01168ef

Please sign in to comment.