Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 21 additions & 46 deletions packages/open-next/src/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cp from "node:child_process";
import fs, { readFileSync } from "node:fs";
import fs from "node:fs";
import { createRequire as topLevelCreateRequire } from "node:module";
import os from "node:os";
import path from "node:path";
Expand Down Expand Up @@ -47,9 +47,11 @@ export async function build(
showWindowsWarning();

// Load open-next.config.ts
const tempDir = initTempDir();
const tempConfigDir = fs.mkdtempSync(
path.join(os.tmpdir(), ".open-next-temp"),
);
let configPath = compileOpenNextConfigNode(
tempDir,
tempConfigDir,
openNextConfigPath,
nodeExternals,
);
Expand All @@ -64,10 +66,10 @@ export async function build(
}
validateConfig(config);

compileOpenNextConfigEdge(tempDir, config, openNextConfigPath);
compileOpenNextConfigEdge(tempConfigDir, config, openNextConfigPath);

// Initialize options
const options = normalizeOptions(config);
const options = normalizeOptions(config, tempConfigDir);
logger.setLevel(options.debug ? "debug" : "info");

// Pre-build validation
Expand All @@ -82,7 +84,7 @@ export async function build(

// Generate deployable bundle
printHeader("Generating bundle");
initOutputDir(tempDir, options);
initOutputDir(options);

// Compile cache.ts
compileCache(options);
Expand Down Expand Up @@ -113,14 +115,6 @@ function showWindowsWarning() {
);
}

function initTempDir() {
const dir = path.join(process.cwd(), ".open-next");
const tempDir = path.join(dir, ".build");
fs.rmSync(dir, { recursive: true, force: true });
fs.mkdirSync(tempDir, { recursive: true });
return tempDir;
}

function checkRunningInsideNextjsApp(options: BuildOptions) {
const { appPath } = options;
const extension = ["js", "cjs", "mjs", "ts"].find((ext) =>
Expand Down Expand Up @@ -175,34 +169,15 @@ function printOpenNextVersion(options: BuildOptions) {
logger.info(`OpenNext v${options.openNextVersion}`);
}

function initOutputDir(srcTempDir: string, options: BuildOptions) {
function initOutputDir(options: BuildOptions) {
// We need to get the build relative to the cwd to find the compiled config
// This is needed for the case where the app is a single-version monorepo and the package.json is in the root of the monorepo
// where the build is in the app directory, but the compiled config is in the root of the monorepo.
const openNextConfig = readFileSync(
path.join(srcTempDir, "open-next.config.mjs"),
"utf8",
);
let openNextConfigEdge: string | null = null;
if (fs.existsSync(path.join(srcTempDir, "open-next.config.edge.mjs"))) {
openNextConfigEdge = readFileSync(
path.join(srcTempDir, "open-next.config.edge.mjs"),
"utf8",
);
}
fs.rmSync(options.outputDir, { recursive: true, force: true });
const destTempDir = options.tempDir;
fs.mkdirSync(destTempDir, { recursive: true });
fs.writeFileSync(
path.join(destTempDir, "open-next.config.mjs"),
openNextConfig,
);
if (openNextConfigEdge) {
fs.writeFileSync(
path.join(destTempDir, "open-next.config.edge.mjs"),
openNextConfigEdge,
);
}
const { buildDir } = options;
fs.mkdirSync(buildDir, { recursive: true });
fs.renameSync(options.tempConfigDir, buildDir);
process.exit(0);
}

async function createWarmerBundle(options: BuildOptions) {
Expand All @@ -215,7 +190,7 @@ async function createWarmerBundle(options: BuildOptions) {
fs.mkdirSync(outputPath, { recursive: true });

// Copy open-next.config.mjs into the bundle
copyOpenNextConfig(options.tempDir, outputPath);
copyOpenNextConfig(options.buildDir, outputPath);

// Build Lambda code
// note: bundle in OpenNext package b/c the adatper relys on the
Expand Down Expand Up @@ -258,7 +233,7 @@ async function createRevalidationBundle(options: BuildOptions) {
fs.mkdirSync(outputPath, { recursive: true });

//Copy open-next.config.mjs into the bundle
copyOpenNextConfig(options.tempDir, outputPath);
copyOpenNextConfig(options.buildDir, outputPath);

// Build Lambda code
await esbuildAsync(
Expand Down Expand Up @@ -297,7 +272,7 @@ async function createImageOptimizationBundle(options: BuildOptions) {
fs.mkdirSync(outputPath, { recursive: true });

// Copy open-next.config.mjs into the bundle
copyOpenNextConfig(options.tempDir, outputPath);
copyOpenNextConfig(options.buildDir, outputPath);

const plugins = [
openNextResolvePlugin({
Expand Down Expand Up @@ -636,7 +611,7 @@ async function createCacheAssets(options: BuildOptions) {
);

//Copy open-next.config.mjs into the bundle
copyOpenNextConfig(options.tempDir, providerPath);
copyOpenNextConfig(options.buildDir, providerPath);

// TODO: check if metafiles doesn't contain duplicates
fs.writeFileSync(
Expand All @@ -660,7 +635,7 @@ export function compileCache(
) {
const { config } = options;
const ext = format === "cjs" ? "cjs" : "mjs";
const outfile = path.join(options.outputDir, ".build", `cache.${ext}`);
const outfile = path.join(options.buildDir, `cache.${ext}`);

const isAfter15 = compareSemver(options.nextVersion, "15.0.0") >= 0;

Expand Down Expand Up @@ -695,7 +670,7 @@ async function createMiddleware(options: BuildOptions) {

// Get middleware manifest
const middlewareManifest = JSON.parse(
readFileSync(
fs.readFileSync(
path.join(appBuildOutputPath, ".next/server/middleware-manifest.json"),
"utf8",
),
Expand All @@ -721,7 +696,7 @@ async function createMiddleware(options: BuildOptions) {

// Copy open-next.config.mjs
copyOpenNextConfig(
options.tempDir,
options.buildDir,
outputPath,
config.middleware.override?.wrapper === "cloudflare",
);
Expand All @@ -739,7 +714,7 @@ async function createMiddleware(options: BuildOptions) {
} else {
await buildEdgeBundle({
entrypoint: path.join(__dirname, "core", "edgeFunctionHandler.js"),
outfile: path.join(outputDir, ".build", "middleware.mjs"),
outfile: path.join(options.buildDir, "middleware.mjs"),
...commonMiddlewareOptions,
onlyBuildOnce: true,
});
Expand Down
13 changes: 3 additions & 10 deletions packages/open-next/src/build/compileConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,21 @@ import { OpenNextConfig } from "types/open-next.js";
import logger from "../logger.js";

export function compileOpenNextConfigNode(
tempDir: string,
outputDir: string,
openNextConfigPath?: string,
nodeExternals?: string,
) {
const sourcePath = path.join(
process.cwd(),
openNextConfigPath ?? "open-next.config.ts",
);
const outputPath = path.join(tempDir, "open-next.config.mjs");
const outputPath = path.join(outputDir, "open-next.config.mjs");

//Check if open-next.config.ts exists
if (!fs.existsSync(sourcePath)) {
//Create a simple open-next.config.mjs file
logger.debug("Cannot find open-next.config.ts. Using default config.");
fs.writeFileSync(
outputPath,
[
"var config = { default: { } };",
"var open_next_config_default = config;",
"export { open_next_config_default as default };",
].join("\n"),
);
fs.writeFileSync(outputPath, "export default { default: { } };");
} else {
buildSync({
entryPoints: [sourcePath],
Expand Down
15 changes: 6 additions & 9 deletions packages/open-next/src/build/createServerBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ async function generateBundle(

const ext = fnOptions.runtime === "deno" ? "mjs" : "cjs";
fs.copyFileSync(
path.join(outputDir, ".build", `cache.${ext}`),
path.join(options.buildDir, `cache.${ext}`),
path.join(outputPath, packagePath, "cache.cjs"),
);

Expand All @@ -158,24 +158,21 @@ async function generateBundle(
await bundleNextServer(path.join(outputPath, packagePath), appPath);
}

// // Copy middleware
// Copy middleware
if (
!config.middleware?.external &&
existsSync(path.join(outputDir, ".build", "middleware.mjs"))
existsSync(path.join(options.buildDir, "middleware.mjs"))
) {
fs.copyFileSync(
path.join(outputDir, ".build", "middleware.mjs"),
path.join(options.buildDir, "middleware.mjs"),
path.join(outputPath, packagePath, "middleware.mjs"),
);
}

// Copy open-next.config.mjs
copyOpenNextConfig(
path.join(outputDir, ".build"),
path.join(outputPath, packagePath),
);
copyOpenNextConfig(options.buildDir, path.join(outputPath, packagePath));

//Copy env files
// Copy env files
copyEnvFile(appBuildOutputPath, packagePath, outputPath);

// Copy all necessary traced files
Expand Down
2 changes: 1 addition & 1 deletion packages/open-next/src/build/edge/createEdgeBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export async function generateEdgeBundle(
fs.mkdirSync(outputPath, { recursive: true });

// Copy open-next.config.mjs
copyOpenNextConfig(path.join(outputDir, ".build"), outputPath, true);
copyOpenNextConfig(options.buildDir, outputPath, true);

// Load middleware manifest
const middlewareManifest = JSON.parse(
Expand Down
17 changes: 11 additions & 6 deletions packages/open-next/src/build/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));

export type BuildOptions = ReturnType<typeof normalizeOptions>;

export function normalizeOptions(config: OpenNextConfig) {
export function normalizeOptions(
config: OpenNextConfig,
tempConfigDir: string,
) {
const appPath = path.join(process.cwd(), config.appPath || ".");
const buildOutputPath = path.join(
process.cwd(),
Expand All @@ -44,14 +47,15 @@ export function normalizeOptions(config: OpenNextConfig) {
appPackageJsonPath,
appPath,
appPublicPath: path.join(appPath, "public"),
buildDir: path.join(outputDir, ".build"),
config,
debug: Boolean(process.env.OPEN_NEXT_DEBUG) ?? false,
monorepoRoot,
nextVersion: getNextVersion(appPath),
openNextVersion: getOpenNextVersion(),
outputDir,
packager,
tempDir: path.join(outputDir, ".build"),
tempConfigDir,
};
}

Expand All @@ -77,6 +81,7 @@ function findMonorepoRoot(appPath: string) {
// note: a lock file (package-lock.json, yarn.lock, or pnpm-lock.yaml) is
// not found in the app's directory or any of its parent directories.
// We are going to assume that the app is not part of a monorepo.
logger.warn("No lockfile found");
return { root: appPath, packager: "npm" as const };
}

Expand Down Expand Up @@ -273,17 +278,17 @@ export function compareSemver(v1: string, v2: string): number {
}

export function copyOpenNextConfig(
tempDir: string,
outputPath: string,
inputDir: string,
outputDir: string,
isEdge = false,
) {
// Copy open-next.config.mjs
fs.copyFileSync(
path.join(
tempDir,
inputDir,
isEdge ? "open-next.config.edge.mjs" : "open-next.config.mjs",
),
path.join(outputPath, "open-next.config.mjs"),
path.join(outputDir, "open-next.config.mjs"),
);
}

Expand Down
Loading