Skip to content

Commit

Permalink
refactor: pass config to build function
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx committed Oct 10, 2024
1 parent 8d18ca4 commit 24ec9c0
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 40 deletions.
8 changes: 4 additions & 4 deletions packages/cloudflare/src/cli/build/build-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ export async function buildWorker(config: Config): Promise<void> {
// Copy over client-side generated files
await cp(
path.join(config.paths.dotNext, "static"),
path.join(config.paths.builderOutput, "assets", "_next", "static"),
path.join(config.paths.outputDir, "assets", "_next", "static"),
{
recursive: true,
}
);

// Copy over any static files (e.g. images) from the source project
const publicDir = path.join(config.paths.nextApp, "public");
const publicDir = path.join(config.paths.sourceDir, "public");
if (existsSync(publicDir)) {
await cp(publicDir, path.join(config.paths.builderOutput, "assets"), {
await cp(publicDir, path.join(config.paths.outputDir, "assets"), {
recursive: true,
});
}
Expand All @@ -52,7 +52,7 @@ export async function buildWorker(config: Config): Promise<void> {
copyPackageCliFiles(packageDistDir, config);

const workerEntrypoint = path.join(config.paths.internalTemplates, "worker.ts");
const workerOutputFile = path.join(config.paths.builderOutput, "index.mjs");
const workerOutputFile = path.join(config.paths.outputDir, "index.mjs");

const nextConfigStr =
readFileSync(path.join(config.paths.standaloneApp, "/server.js"), "utf8")?.match(
Expand Down
29 changes: 11 additions & 18 deletions packages/cloudflare/src/cli/build/index.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
import { containsDotNextDir, getConfig } from "../config";
import type { ProjectOptions } from "../config";
import { buildNextjsApp } from "./build-next-app";
import { buildWorker } from "./build-worker";
import { cpSync } from "node:fs";
import path from "node:path";
import { join } from "node:path";
import { rm } from "node:fs/promises";

/**
* Builds the application in a format that can be passed to workerd
*
* It saves the output in a `.worker-next` directory
*
* @param appDir the directory of the Next.js app to build
* @param opts.outputDir the directory where to save the output (defaults to the app's directory)
* @param opts.skipBuild boolean indicating whether the Next.js build should be skipped (i.e. if the `.next` dir is already built)
* @param options The options for the project
*/
export async function build(appDir: string, opts: BuildOptions): Promise<void> {
export async function build(opts: ProjectOptions): Promise<void> {
if (!opts.skipBuild) {
// Build the next app
await buildNextjsApp(appDir);
await buildNextjsApp(opts.sourceDir);
}

if (!containsDotNextDir(appDir)) {
throw new Error(`.next folder not found in ${appDir}`);
if (!containsDotNextDir(opts.sourceDir)) {
throw new Error(`.next folder not found in ${opts.sourceDir}`);
}

// Create a clean output directory
const outputDir = path.resolve(opts.outputDir ?? appDir, ".worker-next");
await cleanDirectory(outputDir);
// Clean the output directory
await cleanDirectory(opts.outputDir);

// Copy the .next directory to the output directory so it can be mutated.
cpSync(path.join(appDir, ".next"), path.join(outputDir, ".next"), { recursive: true });
cpSync(join(opts.sourceDir, ".next"), join(opts.outputDir, ".next"), { recursive: true });

const config = getConfig(appDir, outputDir);
const config = getConfig(opts);

await buildWorker(config);
}

type BuildOptions = {
skipBuild: boolean;
outputDir?: string;
};

async function cleanDirectory(path: string): Promise<void> {
return await rm(path, { recursive: true, force: true });
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export async function patchCache(code: string, config: Config): Promise<string>

const cacheHandlerFileName = "cache-handler.mjs";
const cacheHandlerEntrypoint = join(config.paths.internalTemplates, "cache-handler", "index.ts");
const cacheHandlerOutputFile = join(config.paths.builderOutput, cacheHandlerFileName);
const cacheHandlerOutputFile = join(config.paths.outputDir, cacheHandlerFileName);

await build({
entryPoints: [cacheHandlerEntrypoint],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function copyPrerenderedRoutes(config: Config) {

const serverAppDirPath = join(config.paths.standaloneAppServer, "app");
const prerenderManifestPath = join(config.paths.standaloneAppDotNext, "prerender-manifest.json");
const outputPath = join(config.paths.builderOutput, "assets", SEED_DATA_DIR);
const outputPath = join(config.paths.outputDir, "assets", SEED_DATA_DIR);

const prerenderManifest: PrerenderManifest = existsSync(prerenderManifestPath)
? JSON.parse(readFileSync(prerenderManifestPath, "utf8"))
Expand All @@ -38,7 +38,7 @@ export function copyPrerenderedRoutes(config: Config) {

if (fullPath.endsWith(NEXT_META_SUFFIX)) {
const data = JSON.parse(readFileSync(fullPath, "utf8"));
writeFileSync(destPath, JSON.stringify({ ...data, lastModified: config.buildTimestamp }));
writeFileSync(destPath, JSON.stringify({ ...data, lastModified: config.build.timestamp }));
} else {
copyFileSync(fullPath, destPath);
}
Expand Down
38 changes: 26 additions & 12 deletions packages/cloudflare/src/cli/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ const UserConfig = {
};

export type Config = {
// Timestamp for when the build was started
buildTimestamp: number;
build: {
// Timestamp for when the build was started
timestamp: number;
// Whether to skip building the Next.js app or not
shouldSkip: boolean;
};

paths: {
// Path to the next application
nextApp: string;
sourceDir: string;
// Path to the output folder
builderOutput: string;
outputDir: string;
// Path to the app's `.next` directory (where `next build` saves the build output)
dotNext: string;
// Path to the application standalone root directory
Expand Down Expand Up @@ -46,13 +50,14 @@ export type Config = {
/**
* Computes the configuration.
*
* @param appDir Next app root folder
* @param outputDir Output of the cloudflare builder
* @param opts.sourceDir Next app root folder
* @param opts.outputDir The directory where to save the output (defaults to the app's directory)
* @param opts.skipBuild Whether the Next.js build should be skipped (i.e. if the `.next` dir is already built)
*
* @returns the configuration, see `Config`
* @returns The configuration, see `Config`
*/
export function getConfig(appDir: string, outputDir: string): Config {
const dotNext = path.join(outputDir, ".next");
export function getConfig(opts: ProjectOptions): Config {
const dotNext = path.join(opts.outputDir, ".next");
const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, "");
const standaloneRoot = path.join(dotNext, "standalone");
const standaloneApp = path.join(standaloneRoot, appPath);
Expand All @@ -64,11 +69,14 @@ export function getConfig(appDir: string, outputDir: string): Config {
const internalTemplates = path.join(internalPackage, "cli", "templates");

return {
buildTimestamp: Date.now(),
build: {
timestamp: Date.now(),
shouldSkip: !!opts.skipBuild,
},

paths: {
nextApp: appDir,
builderOutput: outputDir,
sourceDir: opts.sourceDir,
outputDir: opts.outputDir,
dotNext,
standaloneRoot,
standaloneApp,
Expand All @@ -94,6 +102,12 @@ export function containsDotNextDir(folder: string): boolean {
}
}

export type ProjectOptions = {
sourceDir: string;
outputDir: string;
skipBuild?: boolean;
};

/**
* It basically tries to find the path that the application is under inside the `.next/standalone` directory, using the `.next/server` directory
* presence as the condition that needs to be met.
Expand Down
7 changes: 4 additions & 3 deletions packages/cloudflare/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ if (!["js", "cjs", "mjs", "ts"].some((ext) => existsSync(`./next.config.${ext}`)

const { skipBuild, outputDir } = getArgs();

await build(nextAppDir, {
outputDir,
skipBuild: !!skipBuild,
await build({
sourceDir: nextAppDir,
outputDir: resolve(outputDir ?? nextAppDir, ".worker-next"),
skipBuild,
});

0 comments on commit 24ec9c0

Please sign in to comment.