Skip to content

Commit e6078b5

Browse files
authored
refactor: shuffle code around (#258)
1 parent d39bff2 commit e6078b5

File tree

9 files changed

+324
-313
lines changed

9 files changed

+324
-313
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { cpSync } from "node:fs";
2+
import { createRequire } from "node:module";
3+
import { dirname, join } from "node:path";
4+
5+
import { buildNextjsApp, setStandaloneBuildMode } from "@opennextjs/aws/build/buildNextApp.js";
6+
import { compileCache } from "@opennextjs/aws/build/compileCache.js";
7+
import { compileOpenNextConfig } from "@opennextjs/aws/build/compileConfig.js";
8+
import { createCacheAssets, createStaticAssets } from "@opennextjs/aws/build/createAssets.js";
9+
import { createMiddleware } from "@opennextjs/aws/build/createMiddleware.js";
10+
import * as buildHelper from "@opennextjs/aws/build/helper.js";
11+
import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js";
12+
import logger from "@opennextjs/aws/logger.js";
13+
14+
import type { ProjectOptions } from "../config.js";
15+
import { containsDotNextDir, getConfig } from "../config.js";
16+
import { bundleServer } from "./bundle-server.js";
17+
import { compileEnvFiles } from "./open-next/compile-env-files.js";
18+
import { copyCacheAssets } from "./open-next/copyCacheAssets.js";
19+
import { createServerBundle } from "./open-next/createServerBundle.js";
20+
import {
21+
createOpenNextConfigIfNotExistent,
22+
createWranglerConfigIfNotExistent,
23+
ensureCloudflareConfig,
24+
} from "./utils/index.js";
25+
26+
/**
27+
* Builds the application in a format that can be passed to workerd
28+
*
29+
* It saves the output in a `.worker-next` directory
30+
*
31+
* @param projectOpts The options for the project
32+
*/
33+
export async function build(projectOpts: ProjectOptions): Promise<void> {
34+
printHeader("Cloudflare build");
35+
36+
showWarningOnWindows();
37+
38+
const baseDir = projectOpts.sourceDir;
39+
const require = createRequire(import.meta.url);
40+
const openNextDistDir = dirname(require.resolve("@opennextjs/aws/index.js"));
41+
42+
await createOpenNextConfigIfNotExistent(projectOpts);
43+
44+
const { config, buildDir } = await compileOpenNextConfig(baseDir);
45+
46+
ensureCloudflareConfig(config);
47+
48+
// Initialize options
49+
const options = buildHelper.normalizeOptions(config, openNextDistDir, buildDir);
50+
logger.setLevel(options.debug ? "debug" : "info");
51+
52+
// Do not minify the code so that we can apply string replacement patch.
53+
// Note that wrangler will still minify the bundle.
54+
options.minify = false;
55+
56+
// Pre-build validation
57+
buildHelper.checkRunningInsideNextjsApp(options);
58+
logger.info(`App directory: ${options.appPath}`);
59+
buildHelper.printNextjsVersion(options);
60+
ensureNextjsVersionSupported(options);
61+
buildHelper.printOpenNextVersion(options);
62+
63+
if (projectOpts.skipNextBuild) {
64+
logger.warn("Skipping Next.js build");
65+
} else {
66+
// Build the next app
67+
printHeader("Building Next.js app");
68+
setStandaloneBuildMode(options);
69+
buildNextjsApp(options);
70+
}
71+
72+
if (!containsDotNextDir(projectOpts.sourceDir)) {
73+
throw new Error(`.next folder not found in ${projectOpts.sourceDir}`);
74+
}
75+
76+
// Generate deployable bundle
77+
printHeader("Generating bundle");
78+
buildHelper.initOutputDir(options);
79+
80+
// Compile cache.ts
81+
compileCache(options);
82+
83+
// Compile .env files
84+
compileEnvFiles(options);
85+
86+
// Compile middleware
87+
await createMiddleware(options, { forceOnlyBuildOnce: true });
88+
89+
createStaticAssets(options);
90+
91+
if (config.dangerous?.disableIncrementalCache !== true) {
92+
createCacheAssets(options);
93+
copyCacheAssets(options);
94+
}
95+
96+
await createServerBundle(options);
97+
98+
// TODO: drop this copy.
99+
// Copy the .next directory to the output directory so it can be mutated.
100+
cpSync(join(projectOpts.sourceDir, ".next"), join(projectOpts.outputDir, ".next"), { recursive: true });
101+
102+
const projConfig = getConfig(projectOpts);
103+
104+
// TODO: rely on options only.
105+
await bundleServer(projConfig, options);
106+
107+
if (!projectOpts.skipWranglerConfigCheck) {
108+
await createWranglerConfigIfNotExistent(projectOpts);
109+
}
110+
111+
logger.info("OpenNext build complete.");
112+
}
113+
114+
function ensureNextjsVersionSupported(options: buildHelper.BuildOptions) {
115+
if (buildHelper.compareSemver(options.nextVersion, "14.0.0") < 0) {
116+
logger.error("Next.js version unsupported, please upgrade to version 14 or greater.");
117+
process.exit(1);
118+
}
119+
}

packages/cloudflare/src/cli/build/bundle-server.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { build, Plugin } from "esbuild";
88

99
import { Config } from "../config.js";
1010
import * as patches from "./patches/index.js";
11-
import { normalizePath } from "./utils/index.js";
11+
import { normalizePath, patchCodeWithValidations } from "./utils/index.js";
1212

1313
/** The dist directory of the Cloudflare adapter package */
1414
const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "../..");
@@ -190,37 +190,6 @@ function createFixRequiresESBuildPlugin(config: Config): Plugin {
190190
};
191191
}
192192

193-
/**
194-
* Applies multiple code patches in order to a given piece of code, at each step it validates that the code
195-
* has actually been patched/changed, if not an error is thrown
196-
*
197-
* @param code the code to apply the patches to
198-
* @param patches array of tuples, containing a string indicating the target of the patching (for logging) and
199-
* a patching function that takes a string (pre-patch code) and returns a string (post-patch code)
200-
* @returns the patched code
201-
*/
202-
async function patchCodeWithValidations(
203-
code: string,
204-
patches: [string, (code: string) => string | Promise<string>, opts?: { isOptional?: boolean }][]
205-
): Promise<string> {
206-
console.log(`Applying code patches:`);
207-
let patchedCode = code;
208-
209-
for (const [target, patchFunction, opts] of patches) {
210-
console.log(` - patching ${target}`);
211-
212-
const prePatchCode = patchedCode;
213-
patchedCode = await patchFunction(patchedCode);
214-
215-
if (!opts?.isOptional && prePatchCode === patchedCode) {
216-
throw new Error(`Failed to patch ${target}`);
217-
}
218-
}
219-
220-
console.log(`All ${patches.length} patches applied\n`);
221-
return patchedCode;
222-
}
223-
224193
/**
225194
* Gets the path of the worker.js file generated by the build process
226195
*

0 commit comments

Comments
 (0)