Skip to content

Commit d7ce5da

Browse files
committed
add validation that override worked
1 parent 726342e commit d7ce5da

File tree

2 files changed

+53
-13
lines changed

2 files changed

+53
-13
lines changed

packages/@apphosting/adapter-nextjs/src/bin/build.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ import {
55
generateBuildOutput,
66
validateOutputDirectory,
77
getAdapterMetadata,
8+
exists,
89
} from "../utils.js";
910
import { join } from "path";
1011
import { getBuildOptions, runBuild } from "@apphosting/common";
11-
import {
12-
addRouteOverrides,
13-
overrideNextConfig,
14-
validateNextConfigOverrides,
15-
} from "../overrides.js";
12+
import { addRouteOverrides, overrideNextConfig, validateNextConfigOverride } from "../overrides.js";
1613

1714
const root = process.cwd();
1815
const opts = getBuildOptions();
@@ -27,8 +24,22 @@ if (!process.env.FRAMEWORK_VERSION) {
2724

2825
const originalConfig = await loadConfig(root, opts.projectDirectory);
2926

30-
await overrideNextConfig(root, originalConfig.configFileName);
31-
await validateNextConfigOverrides(root, opts.projectDirectory);
27+
/**
28+
* Override user's Next Config to optimize the app for Firebase App Hosting
29+
* and validate that the override resulted in a valid config that Next.js can
30+
* load.
31+
*
32+
* If the app does not have a next.config.[js|mjs|ts] file in the first place,
33+
* then can skip config override.
34+
*
35+
* Note: loadConfig always returns a fileName (default: next.config.js) even if
36+
* one does not exist in the app's root: https://github.com/vercel/next.js/blob/23681508ca34b66a6ef55965c5eac57de20eb67f/packages/next/src/server/config.ts#L1115
37+
*/
38+
const originalConfigPath = join(root, originalConfig.configFileName);
39+
if (await exists(originalConfigPath)) {
40+
await overrideNextConfig(root, originalConfig.configFileName);
41+
await validateNextConfigOverride(root, opts.projectDirectory, originalConfig.configFileName);
42+
}
3243

3344
await runBuild();
3445

packages/@apphosting/adapter-nextjs/src/overrides.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import {
99
} from "./utils.js";
1010
import { join, extname } from "path";
1111
import { rename as renamePromise } from "fs/promises";
12-
import { NextConfigComplete } from "next/dist/server/config-shared.js";
1312

1413
/**
1514
* Overrides the user's Next Config file (next.config.[ts|js|mjs]) to add configs
1615
* optimized for Firebase App Hosting.
1716
*/
1817
export async function overrideNextConfig(projectRoot: string, nextConfigFileName: string) {
18+
console.log(`Overriding Next Config to add configs optmized for Firebase App Hosting`);
1919
// Check if the file exists in the current working directory
2020
const configPath = join(projectRoot, nextConfigFileName);
2121

@@ -87,13 +87,13 @@ function getCustomNextConfig(importStatement: string, fileExtension: string) {
8787
...config,
8888
images: {
8989
...(config.images || {}),
90-
...(config.images?.unoptimized === undefined && config.images?.loader === undefined
91-
? { unoptimized: true }
90+
...(config.images?.unoptimized === undefined && config.images?.loader === undefined
91+
? { unoptimized: true }
9292
: {}),
9393
},
9494
});
9595
96-
const config = typeof originalConfig === 'function'
96+
const config = typeof originalConfig === 'function'
9797
? async (...args) => {
9898
const resolvedConfig = await originalConfig(...args);
9999
return fahOptimizedConfig(resolvedConfig);
@@ -104,12 +104,41 @@ function getCustomNextConfig(importStatement: string, fileExtension: string) {
104104
`;
105105
}
106106

107-
export async function validateNextConfigOverrides(root: string, projectRoot: string) {
107+
/**
108+
* This function is used to validate the state of an app after running the
109+
* overrideNextConfig. It validates that:
110+
* 1. original next config is preserved
111+
* 2. a new next config is created
112+
* 3. new next config can be loaded by NextJs without any issues.
113+
*/
114+
export async function validateNextConfigOverride(
115+
root: string,
116+
projectRoot: string,
117+
originalConfigFileName: string,
118+
) {
119+
const originalConfigExtension = extname(originalConfigFileName);
120+
const newConfigFileName = `next.config.original${originalConfigExtension}`;
121+
const newConfigFilePath = join(root, newConfigFileName);
122+
if (!(await exists(newConfigFilePath))) {
123+
throw new Error(
124+
`Next Config Override Failed: New Next.js config file not found at ${newConfigFilePath}`,
125+
);
126+
}
127+
128+
const originalNextConfigFilePath = join(root, originalConfigFileName);
129+
if (!(await exists(originalNextConfigFilePath))) {
130+
throw new Error(
131+
`Next Config Override Failed: Original Next.js config file not found at ${originalNextConfigFilePath}`,
132+
);
133+
}
134+
108135
try {
109136
await loadConfig(root, projectRoot);
110137
} catch (error) {
111138
throw new Error(
112-
`Invalid Next.js config: ${error instanceof Error ? error.message : "Unknown error"}`,
139+
`Resulting Next Config is invalid: ${
140+
error instanceof Error ? error.message : "Unknown error"
141+
}`,
113142
);
114143
}
115144
}

0 commit comments

Comments
 (0)