Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Get Latest Next Version
id: get_latest_version
run: |
latest_version=$(curl -s https://api.github.com/repos/vercel/next.js/releases/latest | jq -r '.tag_name')
latest_version=$(curl -s https://registry.npmjs.org/-/package/next/dist-tags | jq -r '.latest')
echo "Latest version: $latest_version"
echo "LATEST_VERSION=$latest_version" >> $GITHUB_ENV
echo "LATEST_VERSION=$latest_version" >> $GITHUB_OUTPUT
Expand Down
64 changes: 18 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,9 @@
showWindowsWarning();

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

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

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

// Pre-build validation
Expand All @@ -82,7 +82,7 @@

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

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

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 +167,14 @@
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.cpSync(options.tempBuildDir, buildDir, { recursive: true });
}

async function createWarmerBundle(options: BuildOptions) {
Expand All @@ -215,7 +187,7 @@
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 +230,7 @@
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 +269,7 @@
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 @@ -445,7 +417,7 @@
}
}

async function createCacheAssets(options: BuildOptions) {

Check warning on line 420 in packages/open-next/src/build.ts

View workflow job for this annotation

GitHub Actions / validate

Refactor this function to reduce its Cognitive Complexity from 36 to the 35 allowed
const { config } = options;
if (config.dangerous?.disableIncrementalCache) return;

Expand Down Expand Up @@ -636,7 +608,7 @@
);

//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 +632,7 @@
) {
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 +667,7 @@

// Get middleware manifest
const middlewareManifest = JSON.parse(
readFileSync(
fs.readFileSync(
path.join(appBuildOutputPath, ".next/server/middleware-manifest.json"),
"utf8",
),
Expand All @@ -721,7 +693,7 @@

// Copy open-next.config.mjs
copyOpenNextConfig(
options.tempDir,
options.buildDir,
outputPath,
config.middleware.override?.wrapper === "cloudflare",
);
Expand All @@ -739,7 +711,7 @@
} 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
14 changes: 8 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,7 @@ 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, tempBuildDir: string) {
const appPath = path.join(process.cwd(), config.appPath || ".");
const buildOutputPath = path.join(
process.cwd(),
Expand All @@ -44,14 +44,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"),
tempBuildDir,
};
}

Expand All @@ -77,6 +78,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 +275,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