[cli][next][build-utils] Variants (#10549)

Co-authored-by: Ethan Arrowood <ethan.arrowood@vercel.com>
This commit is contained in:
Andy
2023-09-20 19:42:20 +02:00
committed by GitHub
parent 4b376a564a
commit decdf27fb5
6 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
---
'@vercel/build-utils': patch
'@vercel/next': patch
'vercel': patch
---
Internal variants

View File

@@ -434,6 +434,13 @@ export interface Cron {
schedule: string;
}
// TODO: Proper description once complete
export interface Flag {
key: string;
defaultValue?: unknown;
metadata: Record<string, unknown>;
}
/** The framework which created the function */
export interface FunctionFramework {
slug: string;
@@ -458,6 +465,7 @@ export interface BuildResultV2Typical {
framework?: {
version: string;
};
flags?: Flag[];
}
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;

View File

@@ -21,6 +21,7 @@ import {
NowBuildError,
Cron,
validateNpmrc,
Flag,
} from '@vercel/build-utils';
import {
detectBuilders,
@@ -93,6 +94,7 @@ interface BuildOutputConfig {
version: string;
};
crons?: Cron[];
flags?: Flag[];
}
/**
@@ -627,6 +629,7 @@ async function doBuild(
const mergedWildcard = mergeWildcard(buildResults.values());
const mergedOverrides: Record<string, PathOverride> =
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
const mergedFlags = mergeFlags(buildResults.values());
const framework = await getFramework(cwd, buildResults);
@@ -640,6 +643,7 @@ async function doBuild(
overrides: mergedOverrides,
framework,
crons: mergedCrons,
flags: mergedFlags,
};
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
@@ -774,3 +778,15 @@ function mergeWildcard(
}
return wildcard;
}
function mergeFlags(
buildResults: Iterable<BuildResult | BuildOutputConfig>
): BuildResultV2Typical['flags'] {
return Array.from(buildResults).flatMap(result => {
if ('flags' in result) {
return result.flags ?? [];
}
return [];
});
}

View File

@@ -76,6 +76,7 @@ import {
getRoutesManifest,
getSourceFilePathFromPage,
getStaticFiles,
getVariantsManifest,
isDynamicRoute,
localizeDynamicRoutes,
normalizeIndexOutput,
@@ -496,6 +497,11 @@ export const build: BuildV2 = async ({
outputDirectory
);
const variantsManifest = await getVariantsManifest(
entryPath,
outputDirectory
);
const routesManifest = await getRoutesManifest(
entryPath,
outputDirectory,
@@ -1365,6 +1371,7 @@ export const build: BuildV2 = async ({
privateOutputs,
hasIsr404Page,
hasIsr500Page,
variantsManifest,
});
}

View File

@@ -12,6 +12,7 @@ import {
debug,
glob,
Files,
Flag,
BuildResultV2Typical as BuildResult,
} from '@vercel/build-utils';
import { Route, RouteWithHandle } from '@vercel/routing-utils';
@@ -45,6 +46,7 @@ import {
UnwrapPromise,
getOperationType,
FunctionsConfigManifestV1,
VariantsManifest,
RSC_CONTENT_TYPE,
RSC_PREFETCH_SUFFIX,
} from './utils';
@@ -111,6 +113,7 @@ export async function serverBuild({
isCorrectLocaleAPIRoutes,
lambdaCompressedByteLimit,
requiredServerFilesManifest,
variantsManifest,
}: {
appPathRoutesManifest?: Record<string, string>;
dynamicPages: string[];
@@ -151,6 +154,7 @@ export async function serverBuild({
imagesManifest?: NextImagesManifest;
prerenderManifest: NextPrerenderedRoutes;
requiredServerFilesManifest: NextRequiredServerFilesManifest;
variantsManifest: VariantsManifest | null;
}): Promise<BuildResult> {
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
@@ -1345,6 +1349,14 @@ export async function serverBuild({
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
const appNotFoundPath = path.posix.join('.', entryDirectory, '_not-found');
const flags: Flag[] = variantsManifest
? Object.entries(variantsManifest).map(([key, value]) => ({
key,
...value,
metadata: value.metadata ?? {},
}))
: [];
return {
wildcard: wildcardConfig,
images: getImagesConfig(imagesManifest),
@@ -2046,5 +2058,6 @@ export async function serverBuild({
]),
],
framework: { version: nextVersion },
flags,
};
}

View File

@@ -3025,3 +3025,35 @@ export function isApiPage(page: string | undefined) {
.replace(/\\/g, '/')
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
}
export type VariantsManifest = Record<
string,
{
defaultValue?: unknown;
metadata?: Record<string, unknown>;
}
>;
export async function getVariantsManifest(
entryPath: string,
outputDirectory: string
): Promise<null | VariantsManifest> {
const pathVariantsManifest = path.join(
entryPath,
outputDirectory,
'variants-manifest.json'
);
const hasVariantsManifest = await fs
.access(pathVariantsManifest)
.then(() => true)
.catch(() => false);
if (!hasVariantsManifest) return null;
const variantsManifest: VariantsManifest = await fs.readJSON(
pathVariantsManifest
);
return variantsManifest;
}