mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 12:57:47 +00:00
[cli] Add Variants to Build Output API (#11098)
Makes adjustments to replace `flags` with `variants`. Also marks the current `flags` implementation as deprecated, as it should get removed soon. Which I'll do in a follow up PR.
This commit is contained in:
7
.changeset/polite-shoes-fail.md
Normal file
7
.changeset/polite-shoes-fail.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
'@vercel/build-utils': minor
|
||||||
|
'vercel': minor
|
||||||
|
'@vercel/next': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Mark `flags` as deprecated and replace them with `variants`
|
||||||
@@ -440,7 +440,9 @@ export interface Cron {
|
|||||||
schedule: string;
|
schedule: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Proper description once complete
|
/**
|
||||||
|
* @deprecated Replaced by Variants. Remove once fully replaced.
|
||||||
|
*/
|
||||||
export interface Flag {
|
export interface Flag {
|
||||||
key: string;
|
key: string;
|
||||||
defaultValue?: unknown;
|
defaultValue?: unknown;
|
||||||
@@ -471,7 +473,9 @@ export interface BuildResultV2Typical {
|
|||||||
framework?: {
|
framework?: {
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
/** @deprecated Replaced by Variants. Remove once fully replaced. */
|
||||||
flags?: Flag[];
|
flags?: Flag[];
|
||||||
|
variants?: Record<string, VariantDefinition>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
||||||
@@ -491,3 +495,28 @@ export type ShouldServe = (
|
|||||||
export type StartDevServer = (
|
export type StartDevServer = (
|
||||||
options: StartDevServerOptions
|
options: StartDevServerOptions
|
||||||
) => Promise<StartDevServerResult>;
|
) => Promise<StartDevServerResult>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: The following types will eventually be exported by a more
|
||||||
|
* relevant package.
|
||||||
|
*/
|
||||||
|
type VariantJSONArray = ReadonlyArray<VariantJSONValue>;
|
||||||
|
|
||||||
|
type VariantJSONValue =
|
||||||
|
| string
|
||||||
|
| boolean
|
||||||
|
| number
|
||||||
|
| null
|
||||||
|
| VariantJSONArray
|
||||||
|
| { [key: string]: VariantJSONValue };
|
||||||
|
|
||||||
|
type VariantOption = {
|
||||||
|
value: VariantJSONValue;
|
||||||
|
label?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface VariantDefinition {
|
||||||
|
options?: VariantOption[];
|
||||||
|
url?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
Cron,
|
Cron,
|
||||||
validateNpmrc,
|
validateNpmrc,
|
||||||
Flag,
|
Flag,
|
||||||
|
VariantDefinition,
|
||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import {
|
import {
|
||||||
detectBuilders,
|
detectBuilders,
|
||||||
@@ -95,7 +96,9 @@ interface BuildOutputConfig {
|
|||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
crons?: Cron[];
|
crons?: Cron[];
|
||||||
|
/** @deprecated Replaced by Variants. Remove once fully replaced. */
|
||||||
flags?: Flag[];
|
flags?: Flag[];
|
||||||
|
variants?: Record<string, VariantDefinition>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -678,10 +681,13 @@ async function doBuild(
|
|||||||
overrides: mergedOverrides,
|
overrides: mergedOverrides,
|
||||||
framework,
|
framework,
|
||||||
crons: mergedCrons,
|
crons: mergedCrons,
|
||||||
|
/** @deprecated Replaced by Variants. Remove once fully replaced. */
|
||||||
flags: mergedFlags,
|
flags: mergedFlags,
|
||||||
};
|
};
|
||||||
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
|
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
|
||||||
|
|
||||||
|
await writeVariantsJson(client, buildResults.values(), outputDir);
|
||||||
|
|
||||||
const relOutputDir = relative(cwd, outputDir);
|
const relOutputDir = relative(cwd, outputDir);
|
||||||
output.print(
|
output.print(
|
||||||
`${prependEmoji(
|
`${prependEmoji(
|
||||||
@@ -826,6 +832,51 @@ function mergeFlags(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the build output and writes all the variants into the `variants.json`
|
||||||
|
* file. It'll skip variants that already exist.
|
||||||
|
*/
|
||||||
|
async function writeVariantsJson(
|
||||||
|
{ output }: Client,
|
||||||
|
buildResults: Iterable<BuildResult | BuildOutputConfig>,
|
||||||
|
outputDir: string
|
||||||
|
): Promise<void> {
|
||||||
|
const variantsFilePath = join(outputDir, 'variants.json');
|
||||||
|
|
||||||
|
let hasVariants = true;
|
||||||
|
|
||||||
|
const variants = (await fs.readJSON(variantsFilePath).catch(error => {
|
||||||
|
if (error.code === 'ENOENT') {
|
||||||
|
hasVariants = false;
|
||||||
|
return { definitions: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
})) as { definitions: Record<string, VariantDefinition> };
|
||||||
|
|
||||||
|
for (const result of buildResults) {
|
||||||
|
if (!('variants' in result) || !result.variants) continue;
|
||||||
|
|
||||||
|
for (const [key, defintion] of Object.entries(result.variants)) {
|
||||||
|
if (result.variants[key]) {
|
||||||
|
output.warn(
|
||||||
|
`The variant "${key}" was found multiple times. Only its first occurrence will be considered.`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasVariants = true;
|
||||||
|
variants.definitions[key] = defintion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only create the file when there are variants to write,
|
||||||
|
// or when the file already exists.
|
||||||
|
if (hasVariants) {
|
||||||
|
await fs.writeJSON(variantsFilePath, variants, { spaces: 2 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function writeBuildJson(buildsJson: BuildsManifest, outputDir: string) {
|
async function writeBuildJson(buildsJson: BuildsManifest, outputDir: string) {
|
||||||
await fs.writeJSON(join(outputDir, 'builds.json'), buildsJson, { spaces: 2 });
|
await fs.writeJSON(join(outputDir, 'builds.json'), buildsJson, { spaces: 2 });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import {
|
|||||||
UnwrapPromise,
|
UnwrapPromise,
|
||||||
getOperationType,
|
getOperationType,
|
||||||
FunctionsConfigManifestV1,
|
FunctionsConfigManifestV1,
|
||||||
VariantsManifest,
|
VariantsManifestLegacy,
|
||||||
RSC_CONTENT_TYPE,
|
RSC_CONTENT_TYPE,
|
||||||
RSC_PREFETCH_SUFFIX,
|
RSC_PREFETCH_SUFFIX,
|
||||||
normalizePrefetches,
|
normalizePrefetches,
|
||||||
@@ -158,7 +158,7 @@ export async function serverBuild({
|
|||||||
imagesManifest?: NextImagesManifest;
|
imagesManifest?: NextImagesManifest;
|
||||||
prerenderManifest: NextPrerenderedRoutes;
|
prerenderManifest: NextPrerenderedRoutes;
|
||||||
requiredServerFilesManifest: NextRequiredServerFilesManifest;
|
requiredServerFilesManifest: NextRequiredServerFilesManifest;
|
||||||
variantsManifest: VariantsManifest | null;
|
variantsManifest: VariantsManifestLegacy | null;
|
||||||
}): Promise<BuildResult> {
|
}): Promise<BuildResult> {
|
||||||
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
|
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
|
||||||
|
|
||||||
|
|||||||
@@ -3257,7 +3257,8 @@ export function isApiPage(page: string | undefined) {
|
|||||||
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
|
.match(/(serverless|server)\/pages\/api(\/|\.js$)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VariantsManifest = Record<
|
/** @deprecated */
|
||||||
|
export type VariantsManifestLegacy = Record<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
defaultValue?: unknown;
|
defaultValue?: unknown;
|
||||||
@@ -3268,7 +3269,7 @@ export type VariantsManifest = Record<
|
|||||||
export async function getVariantsManifest(
|
export async function getVariantsManifest(
|
||||||
entryPath: string,
|
entryPath: string,
|
||||||
outputDirectory: string
|
outputDirectory: string
|
||||||
): Promise<null | VariantsManifest> {
|
): Promise<null | VariantsManifestLegacy> {
|
||||||
const pathVariantsManifest = path.join(
|
const pathVariantsManifest = path.join(
|
||||||
entryPath,
|
entryPath,
|
||||||
outputDirectory,
|
outputDirectory,
|
||||||
@@ -3282,7 +3283,7 @@ export async function getVariantsManifest(
|
|||||||
|
|
||||||
if (!hasVariantsManifest) return null;
|
if (!hasVariantsManifest) return null;
|
||||||
|
|
||||||
const variantsManifest: VariantsManifest = await fs.readJSON(
|
const variantsManifest: VariantsManifestLegacy = await fs.readJSON(
|
||||||
pathVariantsManifest
|
pathVariantsManifest
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user