From 7f99f892b3db7a828495b2e5d397299780d5fb0a Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 17 May 2023 13:12:57 +0200 Subject: [PATCH 1/4] refactor: only evaluate flag once --- packages/runtime/src/helpers/config.ts | 7 +++---- packages/runtime/src/index.ts | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/runtime/src/helpers/config.ts b/packages/runtime/src/helpers/config.ts index da916c2447..596a610dec 100644 --- a/packages/runtime/src/helpers/config.ts +++ b/packages/runtime/src/helpers/config.ts @@ -8,7 +8,6 @@ import slash from 'slash' import { HANDLER_FUNCTION_NAME, IMAGE_FUNCTION_NAME, ODB_FUNCTION_NAME } from '../constants' -import { splitApiRoutes } from './flags' import type { APILambda } from './functions' import type { RoutesManifest } from './types' import { escapeStringRegexp } from './utils' @@ -102,13 +101,13 @@ export const configureHandlerFunctions = async ({ publish, ignore = [], apiLambdas, - featureFlags, + splitApiRoutes, }: { netlifyConfig: NetlifyConfig publish: string ignore: Array apiLambdas: APILambda[] - featureFlags: Record + splitApiRoutes: boolean }) => { const config = await getRequiredServerFiles(publish) const files = config.files || [] @@ -168,7 +167,7 @@ export const configureHandlerFunctions = async ({ configureFunction(HANDLER_FUNCTION_NAME) configureFunction(ODB_FUNCTION_NAME) - if (splitApiRoutes(featureFlags)) { + if (splitApiRoutes) { for (const apiLambda of apiLambdas) { const { functionName, includedFiles } = apiLambda netlifyConfig.functions[functionName] ||= { included_files: [] } diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 07b160e24d..f82e69550c 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -180,7 +180,7 @@ const plugin: NetlifyPlugin = { ignore, publish: relative(process.cwd(), publish), apiLambdas, - featureFlags, + splitApiRoutes: splitApiRoutes(featureFlags), }) await movePublicFiles({ appDir, outdir, publish, basePath }) From 3b2def80e84aa8f1cd303ef3df8f555a4c2efada Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 17 May 2023 13:26:49 +0200 Subject: [PATCH 2/4] fix: add activation guard for splitApiRoutes --- packages/runtime/src/helpers/flags.ts | 18 ++++++++++++++++-- packages/runtime/src/index.ts | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/runtime/src/helpers/flags.ts b/packages/runtime/src/helpers/flags.ts index fe0755fa32..71e4ee0545 100644 --- a/packages/runtime/src/helpers/flags.ts +++ b/packages/runtime/src/helpers/flags.ts @@ -1,4 +1,6 @@ import destr from 'destr' +import { existsSync } from 'fs-extra' +import { join } from 'pathe' /** * If this flag is enabled, we generate individual Lambda functions for API Routes. @@ -11,7 +13,19 @@ import destr from 'destr' * If disabled, we bundle all API Routes into a single function. * This is can lead to large bundle sizes. * + * Relies on `next-server.js.nft.json`, which is only supported in Next.js 12+. + * * Disabled by default. Can be overriden using the NEXT_SPLIT_API_ROUTES env var. */ -export const splitApiRoutes = (featureFlags: Record): boolean => - destr(process.env.NEXT_SPLIT_API_ROUTES) ?? featureFlags.next_split_api_routes ?? false +export const splitApiRoutes = (featureFlags: Record, publish: string): boolean => { + const isEnabled = destr(process.env.NEXT_SPLIT_API_ROUTES) ?? featureFlags.next_split_api_routes ?? false + + if (isEnabled && !existsSync(join(publish, 'next-server.js.nft.json'))) { + console.warn( + 'Trace-based bundling not possible on this version of Next.js. Speed up your builds significantly by upgrading to Next.js v12.', + ) + return false + } + + return isEnabled +} diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index f82e69550c..1444e0163e 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -166,7 +166,7 @@ const plugin: NetlifyPlugin = { const buildId = readFileSync(join(publish, 'BUILD_ID'), 'utf8').trim() - const apiLambdas: APILambda[] = splitApiRoutes(featureFlags) + const apiLambdas: APILambda[] = splitApiRoutes(featureFlags, publish) ? await getAPILambdas(publish, appDir, pageExtensions) : await getExtendedApiRouteConfigs(publish, appDir, pageExtensions).then((extendedRoutes) => extendedRoutes.map(packSingleFunction), @@ -180,7 +180,7 @@ const plugin: NetlifyPlugin = { ignore, publish: relative(process.cwd(), publish), apiLambdas, - splitApiRoutes: splitApiRoutes(featureFlags), + splitApiRoutes: splitApiRoutes(featureFlags, publish), }) await movePublicFiles({ appDir, outdir, publish, basePath }) From efa9787fd2c4adae4df8341ee545b4abb7596f9f Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 17 May 2023 16:34:27 +0200 Subject: [PATCH 3/4] fix: add test for behaviour --- test/index.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/index.spec.ts b/test/index.spec.ts index ec81feb12a..1ec2dd369b 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -727,6 +727,16 @@ describe('onBuild()', () => { expect(existsSync(publicFile)).toBe(true) expect(await readJson(publicFile)).toMatchObject(expect.any(Array)) }) + + it('does not split APIs when .nft.json files are unavailable', async () => { + await moveNextDist() + + await unlink(path.join(process.cwd(), '.next', 'next-server.js.nft.json')) + + await nextRuntime.onBuild(defaultArgs) + + expect(netlifyConfig.functions['_api_*'].node_bundler).toEqual('nft') + }) }) describe('onPostBuild', () => { From 9b582394543a67567a7098a03e2885bfdaa4cca3 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 17 May 2023 16:37:32 +0200 Subject: [PATCH 4/4] Update packages/runtime/src/helpers/flags.ts Co-authored-by: Lennart --- packages/runtime/src/helpers/flags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/src/helpers/flags.ts b/packages/runtime/src/helpers/flags.ts index 71e4ee0545..69f633ee03 100644 --- a/packages/runtime/src/helpers/flags.ts +++ b/packages/runtime/src/helpers/flags.ts @@ -22,7 +22,7 @@ export const splitApiRoutes = (featureFlags: Record, publish: s if (isEnabled && !existsSync(join(publish, 'next-server.js.nft.json'))) { console.warn( - 'Trace-based bundling not possible on this version of Next.js. Speed up your builds significantly by upgrading to Next.js v12.', + 'Trace-based bundling not possible on this version of Next.js. Speed up your builds significantly by upgrading to Next.js v12 or newer.', ) return false }