Skip to content

Commit cbeec0b

Browse files
authored
Copy resources into output directory instead of moving them. (#363)
This is part of making the adapter idempotent.
1 parent 27d1cef commit cbeec0b

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ describe("build commands", () => {
3232
it("expects all output bundle files to be generated", async () => {
3333
const { generateBuildOutput, validateOutputDirectory } = await importUtils;
3434
const files = {
35+
// .next/standalone/.next/ must be created beforehand otherwise
36+
// generateBuildOutput will attempt to copy
37+
// .next/ into .next/standalone/.next
38+
".next/standalone/.next/package.json": "",
3539
".next/standalone/server.js": "",
3640
".next/static/staticfile": "",
3741
".next/routes-manifest.json": `{
@@ -53,7 +57,13 @@ describe("build commands", () => {
5357

5458
const expectedFiles = {
5559
".next/standalone/.next/static/staticfile": "",
60+
".next/static/staticfile": "",
5661
".next/standalone/server.js": "",
62+
".next/routes-manifest.json": `{
63+
"headers":[],
64+
"rewrites":[],
65+
"redirects":[]
66+
}`,
5767
".apphosting/bundle.yaml": `version: v1
5868
runConfig:
5969
runCommand: node .next/standalone/server.js
@@ -71,7 +81,7 @@ outputFiles:
7181
validateTestFiles(tmpDir, expectedFiles);
7282
});
7383

74-
it("moves files into correct location in a monorepo setup", async () => {
84+
it("copies files into correct location in a monorepo setup", async () => {
7585
const { generateBuildOutput } = await importUtils;
7686
const files = {
7787
".next/standalone/apps/next-app/standalonefile": "",
@@ -113,6 +123,7 @@ outputFiles:
113123
const expectedFiles = {
114124
".next/standalone/apps/next-app/.next/static/staticfile": "",
115125
".next/standalone/apps/next-app/standalonefile": "",
126+
".next/static/staticfile": "",
116127
};
117128
const expectedPartialYaml = {
118129
version: "v1",
@@ -125,6 +136,10 @@ outputFiles:
125136
it("test failed validateOutputDirectory", async () => {
126137
const { generateBuildOutput, validateOutputDirectory } = await importUtils;
127138
const files = {
139+
// .next/standalone/.next/ must be created beforehand otherwise
140+
// generateBuildOutput will attempt to copy
141+
// .next/ into .next/standalone/.next
142+
".next/standalone/.next/package.json": "",
128143
".next/standalone/notserver.js": "",
129144
".next/static/staticfile": "",
130145
".next/routes-manifest.json": `{
@@ -152,6 +167,10 @@ outputFiles:
152167
it("expects directories and other files to be copied over", async () => {
153168
const { generateBuildOutput, validateOutputDirectory } = await importUtils;
154169
const files = {
170+
// .next/standalone/.next/ must be created beforehand otherwise
171+
// generateBuildOutput will attempt to copy
172+
// .next/ into .next/standalone/.next
173+
".next/standalone/.next/package.json": "",
155174
".next/standalone/server.js": "",
156175
".next/static/staticfile": "",
157176
"public/publicfile": "",
@@ -178,9 +197,15 @@ outputFiles:
178197

179198
const expectedFiles = {
180199
".next/standalone/.next/static/staticfile": "",
200+
".next/static/staticfile": "",
181201
".next/standalone/server.js": "",
182202
".next/standalone/public/publicfile": "",
183203
".next/standalone/extrafile": "",
204+
".next/routes-manifest.json": `{
205+
"headers":[],
206+
"rewrites":[],
207+
"redirects":[]
208+
}`,
184209
};
185210
validateTestFiles(tmpDir, expectedFiles);
186211
});

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { NextConfigComplete } from "next/dist/server/config-shared.js";
1515
import { OutputBundleConfig } from "@apphosting/common";
1616

1717
// fs-extra is CJS, readJson can't be imported using shorthand
18-
export const { move, exists, writeFile, readJson, readdir, readFileSync, existsSync, mkdir } =
18+
export const { copy, exists, writeFile, readJson, readdir, readFileSync, existsSync, mkdir } =
1919
fsExtra;
2020

2121
// Loads the user's next.config.js file.
@@ -116,7 +116,7 @@ export function populateOutputBundleOptions(
116116
}
117117

118118
/**
119-
* Moves static assets and other resources into the standlone directory, also generates the bundle.yaml
119+
* Copy static assets and other resources into the standlone directory, also generates the bundle.yaml
120120
* @param rootDir The root directory of the uploaded source code.
121121
* @param outputBundleOptions The target location of built artifacts in the output bundle.
122122
* @param nextBuildDirectory The location of the .next directory.
@@ -131,30 +131,30 @@ export async function generateBuildOutput(
131131
): Promise<void> {
132132
const staticDirectory = join(nextBuildDirectory, "static");
133133
await Promise.all([
134-
move(staticDirectory, opts.outputStaticDirectoryPath, { overwrite: true }),
135-
moveResources(appDir, opts.outputDirectoryAppPath, opts.bundleYamlPath),
134+
copy(staticDirectory, opts.outputStaticDirectoryPath, { overwrite: true }),
135+
copyResources(appDir, opts.outputDirectoryAppPath, opts.bundleYamlPath),
136136
generateBundleYaml(opts, rootDir, nextVersion, adapterMetadata),
137137
]);
138138
return;
139139
}
140140

141-
// Move all files and directories to apphosting output directory.
141+
// Copy all files and directories to apphosting output directory.
142142
// Files are skipped if there is already a file with the same name in the output directory
143-
async function moveResources(
143+
async function copyResources(
144144
appDir: string,
145145
outputBundleAppDir: string,
146146
bundleYamlPath: string,
147147
): Promise<void> {
148148
const appDirExists = await exists(appDir);
149149
if (!appDirExists) return;
150-
const pathsToMove = await readdir(appDir);
151-
for (const path of pathsToMove) {
150+
const pathsToCopy = await readdir(appDir);
151+
for (const path of pathsToCopy) {
152152
const isbundleYamlDir = join(appDir, path) === dirname(bundleYamlPath);
153153
const existsInOutputBundle = await exists(join(outputBundleAppDir, path));
154154
// Keep apphosting.yaml files in the root directory still, as later steps expect them to be there
155155
const isApphostingYaml = path === "apphosting_preprocessed" || path === "apphosting.yaml";
156156
if (!isbundleYamlDir && !existsInOutputBundle && !isApphostingYaml) {
157-
await move(join(appDir, path), join(outputBundleAppDir, path));
157+
await copy(join(appDir, path), join(outputBundleAppDir, path));
158158
}
159159
}
160160
return;

0 commit comments

Comments
 (0)