Skip to content

Commit

Permalink
Nextjs use spec (#253)
Browse files Browse the repository at this point in the history
* add output bundle spec to common module

* bump common module version

* use new output bundle spec

* resolve merge

* copy over all resources

* add packagejson update

* fix lint

* swap import to common

* add packagejson update

* fix e2e test

* bump version
  • Loading branch information
Yuangwang authored Sep 26, 2024
1 parent 4534609 commit 717eded
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 187 deletions.
12 changes: 5 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/@apphosting/adapter-nextjs/e2e/run-local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ await promiseSpawn("node", [buildScript], {

const bundleYaml = parseYaml(readFileSync(join(cwd, ".apphosting/bundle.yaml")).toString());

const runCommand = bundleYaml.runCommand;
const runCommand = bundleYaml.serverConfig.runCommand;

if (typeof runCommand !== "string") {
throw new Error("runCommand must be a string");
Expand Down
2 changes: 1 addition & 1 deletion packages/@apphosting/adapter-nextjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@apphosting/adapter-nextjs",
"version": "14.0.7",
"version": "14.0.8",
"main": "dist/index.js",
"description": "Experimental addon to the Firebase CLI to add web framework support",
"repository": {
Expand Down
178 changes: 70 additions & 108 deletions packages/@apphosting/adapter-nextjs/src/bin/build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ describe("build commands", () => {
beforeEach(() => {
tmpDir = generateTmpDir();
outputBundleOptions = {
bundleYamlPath: path.join(tmpDir, ".apphosting/bundle.yaml"),
bundleYamlPath: path.join(tmpDir, ".apphosting", "bundle.yaml"),
outputDirectoryBasePath: path.join(tmpDir, ".apphosting"),
outputDirectoryAppPath: path.join(tmpDir, ".apphosting"),
outputPublicDirectoryPath: path.join(tmpDir, ".apphosting/public"),
outputStaticDirectoryPath: path.join(tmpDir, ".apphosting/.next/static"),
serverFilePath: path.join(tmpDir, ".apphosting/server.js"),
outputDirectoryAppPath: path.join(tmpDir, ".next", "standalone"),
outputPublicDirectoryPath: path.join(tmpDir, ".next", "standalone", "public"),
outputStaticDirectoryPath: path.join(tmpDir, ".next", "standalone", ".next", "static"),
serverFilePath: path.join(tmpDir, ".next", "standalone", "server.js"),
};
defaultNextVersion = "14.0.3";
});

it("expects all output bundle files to be generated", async () => {
const { generateOutputDirectory, validateOutputDirectory, createMetadata } = await importUtils;
const { generateBuildOutput, validateOutputDirectory, createMetadata } = await importUtils;
const files = {
".next/standalone/server.js": "",
".next/static/staticfile": "",
Expand All @@ -36,27 +36,21 @@ describe("build commands", () => {
};
const packageVersion = createMetadata(defaultNextVersion).adapterVersion;
generateTestFiles(tmpDir, files);
await generateOutputDirectory(
await generateBuildOutput(
tmpDir,
tmpDir,
outputBundleOptions,
path.join(tmpDir, ".next"),
defaultNextVersion,
);
await validateOutputDirectory(outputBundleOptions);
await validateOutputDirectory(outputBundleOptions, path.join(tmpDir, ".next"));

const expectedFiles = {
".apphosting/.next/static/staticfile": "",
".apphosting/server.js": "",
".apphosting/bundle.yaml": `headers: []
redirects: []
rewrites: []
runCommand: node .apphosting/server.js
neededDirs:
- .apphosting
staticAssets:
- .apphosting/public
env: []
".next/standalone/.next/static/staticfile": "",
".next/standalone/server.js": "",
".apphosting/bundle.yaml": `version: v1
serverConfig:
runCommand: node .next/standalone/server.js
metadata:
adapterPackageName: "@apphosting/adapter-nextjs"
adapterVersion: ${packageVersion}
Expand All @@ -68,155 +62,123 @@ metadata:
});

it("moves files into correct location in a monorepo setup", async () => {
const { generateOutputDirectory } = await importUtils;
const { generateBuildOutput } = await importUtils;
const files = {
".next/standalone/apps/next-app/standalonefile": "",
".next/static/staticfile": "",
"public/publicfile": "",
".next/routes-manifest.json": `{
"headers":[],
"rewrites":[],
"redirects":[]
}`,
};
generateTestFiles(tmpDir, files);
await generateOutputDirectory(
await generateBuildOutput(
tmpDir,
"apps/next-app",
{
bundleYamlPath: path.join(tmpDir, ".apphosting/bundle.yaml"),
bundleYamlPath: path.join(tmpDir, ".apphosting", "bundle.yaml"),
outputDirectoryBasePath: path.join(tmpDir, ".apphosting"),
outputDirectoryAppPath: path.join(tmpDir, ".apphosting/apps/next-app"),
outputPublicDirectoryPath: path.join(tmpDir, ".apphosting/apps/next-app/public"),
outputStaticDirectoryPath: path.join(tmpDir, ".apphosting/apps/next-app/.next/static"),
serverFilePath: path.join(tmpDir, ".apphosting/apps/next-app/server.js"),
outputDirectoryAppPath: path.join(tmpDir, ".next", "standalone", "apps", "next-app"),
outputPublicDirectoryPath: path.join(
tmpDir,
".next",
"standalone",
"apps",
"next-app",
"public",
),
outputStaticDirectoryPath: path.join(
tmpDir,
".next",
"standalone",
"apps",
"next-app",
".next",
"static",
),
serverFilePath: path.join(tmpDir, ".next", "standalone", "apps", "next-app", "server.js"),
},
path.join(tmpDir, ".next"),
defaultNextVersion,
);

const expectedFiles = {
".apphosting/apps/next-app/.next/static/staticfile": "",
".apphosting/apps/next-app/standalonefile": "",
".next/standalone/apps/next-app/.next/static/staticfile": "",
".next/standalone/apps/next-app/standalonefile": "",
};
const expectedPartialYaml = {
headers: [],
rewrites: [],
redirects: [],
runCommand: "node .apphosting/apps/next-app/server.js",
neededDirs: [".apphosting"],
staticAssets: [".apphosting/apps/next-app/public"],
version: "v1",
serverConfig: { runCommand: "node .next/standalone/apps/next-app/server.js" },
};
validateTestFiles(tmpDir, expectedFiles);
validatePartialYamlContents(tmpDir, ".apphosting/bundle.yaml", expectedPartialYaml);
});

it("expects directories and other files to be copied over", async () => {
const { generateOutputDirectory, validateOutputDirectory } = await importUtils;
it("test failed validateOutputDirectory", async () => {
const { generateBuildOutput, validateOutputDirectory } = await importUtils;
const files = {
".next/standalone/server.js": "",
".next/standalone/notserver.js": "",
".next/static/staticfile": "",
"public/publicfile": "",
extrafile: "",
".next/routes-manifest.json": `{
"headers":[],
"rewrites":[],
"redirects":[]
"headers":[{"source":"source", "headers":["header1"]}],
"rewrites":[{"source":"source", "destination":"destination"}],
"redirects":[{"source":"source", "destination":"destination"}]
}`,
};
generateTestFiles(tmpDir, files);
await generateOutputDirectory(
await generateBuildOutput(
tmpDir,
tmpDir,
outputBundleOptions,
path.join(tmpDir, ".next"),
defaultNextVersion,
);
await validateOutputDirectory(outputBundleOptions);

const expectedFiles = {
".apphosting/.next/static/staticfile": "",
".apphosting/server.js": "",
".apphosting/public/publicfile": "",
".apphosting/extrafile": "",
};
const expectedPartialYaml = {
headers: [],
rewrites: [],
redirects: [],
runCommand: "node .apphosting/server.js",
neededDirs: [".apphosting"],
staticAssets: [".apphosting/public"],
};
validateTestFiles(tmpDir, expectedFiles);
validatePartialYamlContents(tmpDir, ".apphosting/bundle.yaml", expectedPartialYaml);
assert.rejects(
async () => await validateOutputDirectory(outputBundleOptions, path.join(tmpDir, ".next")),
);
});

it("expects bundle.yaml headers/rewrites/redirects to be generated", async () => {
const { generateOutputDirectory, validateOutputDirectory } = await importUtils;
it("expects directories and other files to be copied over", async () => {
const { generateBuildOutput, validateOutputDirectory } = await importUtils;
const files = {
".next/standalone/server.js": "",
".next/static/staticfile": "",
"public/publicfile": "",
extrafile: "",
".next/routes-manifest.json": `{
"headers":[{"source":"source", "headers":["header1"]}],
"rewrites":[{"source":"source", "destination":"destination"}],
"redirects":[{"source":"source", "destination":"destination"}]
"headers":[],
"rewrites":[],
"redirects":[]
}`,
};
generateTestFiles(tmpDir, files);
await generateOutputDirectory(
await generateBuildOutput(
tmpDir,
tmpDir,
outputBundleOptions,
path.join(tmpDir, ".next"),
defaultNextVersion,
);
await validateOutputDirectory(outputBundleOptions);
await validateOutputDirectory(outputBundleOptions, path.join(tmpDir, ".next"));

const expectedFiles = {
".apphosting/.next/static/staticfile": "",
".apphosting/server.js": "",
};
const expectedPartialYaml = {
headers: [{ source: "source", headers: ["header1"] }],
rewrites: [{ source: "source", destination: "destination" }],
redirects: [{ source: "source", destination: "destination" }],
".next/standalone/.next/static/staticfile": "",
".next/standalone/server.js": "",
".next/standalone/public/publicfile": "",
".next/standalone/extrafile": "",
};
validateTestFiles(tmpDir, expectedFiles);
validatePartialYamlContents(tmpDir, ".apphosting/bundle.yaml", expectedPartialYaml);
});
it("test failed validateOutputDirectory", async () => {
const { generateOutputDirectory, validateOutputDirectory } = await importUtils;
const files = {
".next/standalone/notserver.js": "",
".next/static/staticfile": "",
".next/routes-manifest.json": `{
"headers":[{"source":"source", "headers":["header1"]}],
"rewrites":[{"source":"source", "destination":"destination"}],
"redirects":[{"source":"source", "destination":"destination"}]
}`,
};
generateTestFiles(tmpDir, files);
await generateOutputDirectory(
tmpDir,
tmpDir,
outputBundleOptions,
path.join(tmpDir, ".next"),
defaultNextVersion,
);
assert.rejects(async () => await validateOutputDirectory(outputBundleOptions));
});
it("test populate output bundle options", async () => {
const { populateOutputBundleOptions } = await importUtils;
const expectedOutputBundleOptions = {
bundleYamlPath: "test/.apphosting/bundle.yaml",
outputDirectoryBasePath: "test/.apphosting",
outputDirectoryAppPath: "test/.apphosting",
outputPublicDirectoryPath: "test/.apphosting/public",
outputStaticDirectoryPath: "test/.apphosting/.next/static",
serverFilePath: "test/.apphosting/server.js",
outputDirectoryAppPath: "test/.next/standalone",
outputPublicDirectoryPath: "test/.next/standalone/public",
outputStaticDirectoryPath: "test/.next/standalone/.next/static",
serverFilePath: "test/.next/standalone/server.js",
};
assert.deepEqual(populateOutputBundleOptions("test", "test"), expectedOutputBundleOptions);
assert.deepEqual(
populateOutputBundleOptions("test", "test", "test/.next"),
expectedOutputBundleOptions,
);
});
afterEach(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
Expand Down
13 changes: 9 additions & 4 deletions packages/@apphosting/adapter-nextjs/src/bin/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {
loadConfig,
populateOutputBundleOptions,
generateOutputDirectory,
generateBuildOutput,
validateOutputDirectory,
} from "../utils.js";
import { join } from "path";
Expand All @@ -20,15 +20,20 @@ if (!process.env.FRAMEWORK_VERSION) {
}
await runBuild();

const outputBundleOptions = populateOutputBundleOptions(root, opts.projectDirectory);
const { distDir } = await loadConfig(root, opts.projectDirectory);
const nextBuildDirectory = join(opts.projectDirectory, distDir);

await generateOutputDirectory(
const outputBundleOptions = populateOutputBundleOptions(
root,
opts.projectDirectory,
nextBuildDirectory,
);

await generateBuildOutput(
root,
opts.projectDirectory,
outputBundleOptions,
nextBuildDirectory,
process.env.FRAMEWORK_VERSION,
);
await validateOutputDirectory(outputBundleOptions);
await validateOutputDirectory(outputBundleOptions, nextBuildDirectory);
Loading

0 comments on commit 717eded

Please sign in to comment.