diff --git a/.vscode/settings.json b/.vscode/settings.json index ad92582b..acd5051e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "cSpell.words": ["nextjs"] } diff --git a/packages/cloudflare/src/build/build-worker.ts b/packages/cloudflare/src/build/build-worker.ts index 349482a2..2594cfe8 100644 --- a/packages/cloudflare/src/build/build-worker.ts +++ b/packages/cloudflare/src/build/build-worker.ts @@ -2,6 +2,8 @@ import { NextjsAppPaths } from "../nextjs-paths"; import { build, Plugin } from "esbuild"; import { existsSync, readFileSync } from "node:fs"; import { cp, readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; import { patchRequire } from "./patches/investigated/patch-require"; import { copyTemplates } from "./patches/investigated/copy-templates"; @@ -13,6 +15,9 @@ import { inlineEvalManifest } from "./patches/to-investigate/inline-eval-manifes import { patchWranglerDeps } from "./patches/to-investigate/wrangler-deps"; import { updateWebpackChunksFile } from "./patches/investigated/update-webpack-chunks-file"; +/** The directory containing the Cloudflare template files. */ +const templateSrcDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "templates"); + /** * Using the Next.js build output in the `.next` directory builds a workerd compatible output * @@ -20,10 +25,9 @@ import { updateWebpackChunksFile } from "./patches/investigated/update-webpack-c * @param nextjsAppPaths */ export async function buildWorker( - inputNextAppDir: string, + appDir: string, outputDir: string, - nextjsAppPaths: NextjsAppPaths, - templateSrcDir: string + nextjsAppPaths: NextjsAppPaths ): Promise { const templateDir = copyTemplates(templateSrcDir, nextjsAppPaths); @@ -132,8 +136,8 @@ Request = globalThis.Request; }); // Copy over any static files (e.g. images) from the source project - if (existsSync(`${inputNextAppDir}/public`)) { - await cp(`${inputNextAppDir}/public`, `${outputDir}/assets`, { + if (existsSync(`${appDir}/public`)) { + await cp(`${appDir}/public`, `${outputDir}/assets`, { recursive: true, }); } diff --git a/packages/cloudflare/src/build/build.ts b/packages/cloudflare/src/build/build.ts index add90c5d..5f70a9a9 100644 --- a/packages/cloudflare/src/build/build.ts +++ b/packages/cloudflare/src/build/build.ts @@ -2,48 +2,33 @@ import { rm } from "node:fs/promises"; import { buildNextjsApp } from "./build-next-app"; import { buildWorker } from "./build-worker"; import { getNextjsAppPaths } from "../nextjs-paths"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import { cpSync, rmSync } from "node:fs"; - -const SAVE_DIR = ".save.next"; +import { cpSync } from "node:fs"; +import { resolve } from "node:path"; /** * Builds the application in a format that can be passed to workerd * * It saves the output in a `.worker-next` directory * - * @param inputNextAppDir the directory of the Next.js app to build + * @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) */ -export async function build(inputNextAppDir: string, opts: BuildOptions): Promise { +export async function build(appDir: string, opts: BuildOptions): Promise { if (!opts.skipBuild) { - // Build the next app and save a copy in .save.next - buildNextjsApp(inputNextAppDir); - rmSync(`${inputNextAppDir}/${SAVE_DIR}`, { - recursive: true, - force: true, - }); - cpSync(`${inputNextAppDir}/.next`, `${inputNextAppDir}/${SAVE_DIR}`, { - recursive: true, - }); - } else { - // Skip the next build and restore the copy from .next.save - rmSync(`${inputNextAppDir}/.next`, { recursive: true, force: true }); - cpSync(`${inputNextAppDir}/${SAVE_DIR}`, `${inputNextAppDir}/.next`, { - recursive: true, - }); + // Build the next app + buildNextjsApp(appDir); } - const outputDir = `${opts.outputDir ?? inputNextAppDir}/.worker-next`; + // Create a clean output directory + const outputDir = resolve(opts.outputDir ?? appDir, ".worker-next"); await cleanDirectory(outputDir); - const nextjsAppPaths = getNextjsAppPaths(inputNextAppDir); - - const templateDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "templates"); + // Copy the .next directory to the output directory so it can be mutated. + cpSync(resolve(`${appDir}/.next`), resolve(`${outputDir}/.next`), { recursive: true }); + const nextjsAppPaths = getNextjsAppPaths(outputDir); - await buildWorker(inputNextAppDir, outputDir, nextjsAppPaths, templateDir); + await buildWorker(appDir, outputDir, nextjsAppPaths); } type BuildOptions = { diff --git a/packages/cloudflare/src/nextjs-paths.ts b/packages/cloudflare/src/nextjs-paths.ts index 999330cc..050164bd 100644 --- a/packages/cloudflare/src/nextjs-paths.ts +++ b/packages/cloudflare/src/nextjs-paths.ts @@ -7,7 +7,6 @@ import path, { relative } from "node:path"; * NOTE: WIP, we still need to discern which paths are relevant here! */ export type NextjsAppPaths = { - appDir: string; /** * The path to the application's `.next` directory (where `next build` saves the build output) */ @@ -32,18 +31,17 @@ export type NextjsAppPaths = { /** * Collects all the paths necessary for dealing with the Next.js applications output * - * @param nextAppDir The path to the Next.js app + * @param baseDir The path to the directory that contains the .next directory * @returns the various paths. */ -export function getNextjsAppPaths(nextAppDir: string): NextjsAppPaths { - const dotNextDir = getDotNextDirPath(nextAppDir); +export function getNextjsAppPaths(baseDir: string): NextjsAppPaths { + const dotNextDir = getDotNextDirPath(baseDir); const appPath = getNextjsApplicationPath(dotNextDir).replace(/\/$/, ""); const standaloneAppDir = path.join(dotNextDir, "standalone", appPath); return { - appDir: nextAppDir, dotNextDir, standaloneAppDir, standaloneAppDotNextDir: path.join(standaloneAppDir, ".next"),