mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 12:57:47 +00:00
[cli][next][build-utils] Variants (#10549)
Co-authored-by: Ethan Arrowood <ethan.arrowood@vercel.com>
This commit is contained in:
7
.changeset/nervous-apricots-heal.md
Normal file
7
.changeset/nervous-apricots-heal.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@vercel/build-utils': patch
|
||||
'@vercel/next': patch
|
||||
'vercel': patch
|
||||
---
|
||||
|
||||
Internal variants
|
||||
@@ -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;
|
||||
|
||||
@@ -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 [];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user