From c7ead151f55247df23ca0611130c2907a1332d77 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 16 Oct 2020 17:56:14 -0400 Subject: [PATCH] [next] Add support for Image Optimization (#5296) This PR sends the results of the image optimization config from next.config.js to the build output. x-ref: https://github.com/vercel/next.js/pull/17749 --- packages/now-next/src/index.ts | 54 ++++++++++++++++++++++++++++++++++ packages/now-next/src/utils.ts | 32 ++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/packages/now-next/src/index.ts b/packages/now-next/src/index.ts index 7014dedb115..1ae4f020e46 100644 --- a/packages/now-next/src/index.ts +++ b/packages/now-next/src/index.ts @@ -39,6 +39,7 @@ import { getDynamicRoutes, getExportIntent, getExportStatus, + getImagesManifest, getNextConfig, getPathsInside, getPrerenderManifest, @@ -219,6 +220,7 @@ export const build = async ({ meta = {} as BuildParamsMeta, }: BuildParamsType): Promise<{ routes: Route[]; + images?: { domains: string[]; sizes: number[] }; output: Files; watch?: string[]; childProcesses: ChildProcess[]; @@ -302,6 +304,7 @@ export const build = async ({ return { output: {}, + images: undefined, routes: await getRoutes( entryPath, entryDirectory, @@ -420,6 +423,7 @@ export const build = async ({ outputDirectory, nextVersion ); + const imagesManifest = await getImagesManifest(entryPath, outputDirectory); const prerenderManifest = await getPrerenderManifest(entryPath); const headers: Route[] = []; const rewrites: Route[] = []; @@ -519,6 +523,44 @@ export const build = async ({ } } + if (imagesManifest) { + switch (imagesManifest.version) { + case 1: { + if (!imagesManifest.images) { + throw new NowBuildError({ + code: 'NEXT_IMAGES_MISSING', + message: + 'image-manifest.json "images" is required. Contact support if this continues to happen.', + }); + } + const { images } = imagesManifest; + if (!Array.isArray(images.domains)) { + throw new NowBuildError({ + code: 'NEXT_IMAGES_DOMAINS', + message: + 'image-manifest.json "images.domains" must be an array. Contact support if this continues to happen.', + }); + } + if (!Array.isArray(images.sizes)) { + throw new NowBuildError({ + code: 'NEXT_IMAGES_DOMAINS', + message: + 'image-manifest.json "images.sizes" must be an array. Contact support if this continues to happen.', + }); + } + break; + } + default: { + throw new NowBuildError({ + code: 'NEXT_IMAGES_VERSION_UNKNOWN', + message: + 'This version of `@vercel/next` does not support the version of Next.js you are trying to deploy.\n' + + 'Please upgrade your `@vercel/next` builder and try again. Contact support if this continues to happen.', + }); + } + } + } + const userExport = await getExportStatus(entryPath); if (userExport) { @@ -564,6 +606,12 @@ export const build = async ({ return { output, + images: imagesManifest?.images + ? { + domains: imagesManifest.images.domains, + sizes: imagesManifest.images.sizes, + } + : undefined, routes: [ // User headers ...headers, @@ -1736,6 +1784,12 @@ export const build = async ({ ...staticFiles, ...staticDirectoryFiles, }, + images: imagesManifest?.images + ? { + domains: imagesManifest.images.domains, + sizes: imagesManifest.images.sizes, + } + : undefined, /* Desired routes order - Runtime headers diff --git a/packages/now-next/src/utils.ts b/packages/now-next/src/utils.ts index f764dad4d44..85abf23b991 100644 --- a/packages/now-next/src/utils.ts +++ b/packages/now-next/src/utils.ts @@ -502,6 +502,38 @@ export async function getDynamicRoutes( return routes; } +type ImagesManifest = { + version: number; + images: { + sizes: number[]; + domains: string[]; + }; +}; + +export async function getImagesManifest( + entryPath: string, + outputDirectory: string +): Promise { + const pathImagesManifest = path.join( + entryPath, + outputDirectory, + 'images-manifest.json' + ); + + const hasImagesManifest = await fs + .access(pathImagesManifest) + .then(() => true) + .catch(() => false); + + if (!hasImagesManifest) { + return undefined; + } + + // eslint-disable-next-line @typescript-eslint/no-var-requires + const imagesManifest: ImagesManifest = require(pathImagesManifest); + return imagesManifest; +} + function syncEnvVars(base: EnvConfig, removeEnv: EnvConfig, addEnv: EnvConfig) { // Remove any env vars from `removeEnv` // that are not present in the `addEnv`