Skip to content

Commit

Permalink
Merge branch 'main' into vercel-blog-example
Browse files Browse the repository at this point in the history
  • Loading branch information
shashankboosi committed Oct 12, 2024
2 parents 2d48c79 + e7311df commit ab5f1f7
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 52 deletions.
18 changes: 18 additions & 0 deletions packages/cloudflare/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# @opennextjs/cloudflare

## 0.2.0

### Minor Changes

- 6acf0fd: feat: cli arg to disable minification

The cache handler currently forces minification. There is now a CLI arg to disable minification for the build. At the moment, this only applies to the cache handler but may be used for other parts of the build in the future when minification is introduced to them. By default, minification is enabled, but can be disabled by passing `--noMinify`.

## 0.1.1

### Patch Changes

- 66ba0ff: enhancement: Expand missing next.config error message

Found out that next dev can run the a Next.js app without next.config but
if we are using the adapter we throw an error if we don't find the config.
So expanded the error for users.

## 0.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ DONE:
- figure out the assets
- copy the template folders

## Open next [example app](https://github.com/sst/open-next/tree/main/example)
## Open next [example app](https://github.com/opennextjs/opennextjs-aws/tree/main/example)

Changes:

Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@opennextjs/cloudflare",
"description": "Cloudflare builder for next apps",
"version": "0.1.0",
"version": "0.2.0",
"scripts": {
"build": "tsup",
"build:watch": "tsup --watch src",
Expand Down
12 changes: 9 additions & 3 deletions packages/cloudflare/src/cli/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { parseArgs } from "node:util";
import { resolve } from "node:path";

export function getArgs(): {
skipBuild: boolean;
skipNextBuild: boolean;
outputDir?: string;
minify: boolean;
} {
const {
values: { skipBuild, output },
values: { skipBuild, output, noMinify },
} = parseArgs({
options: {
skipBuild: {
Expand All @@ -19,6 +20,10 @@ export function getArgs(): {
type: "string",
short: "o",
},
noMinify: {
type: "boolean",
default: false,
},
},
allowPositionals: false,
});
Expand All @@ -31,7 +36,8 @@ export function getArgs(): {

return {
outputDir,
skipBuild: skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)),
skipNextBuild: skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)),
minify: !noMinify,
};
}

Expand Down
4 changes: 2 additions & 2 deletions packages/cloudflare/src/cli/build/build-next-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ export async function buildNextjsApp(nextAppDir: string): Promise<void> {
runNextBuildCommand(pm.name, nextAppDir);
}

// equivalent to: https://github.com/sst/open-next/blob/f61b0e94/packages/open-next/src/build.ts#L175-L186
// equivalent to: https://github.com/opennextjs/opennextjs-aws/blob/f61b0e94/packages/open-next/src/build.ts#L175-L186
function runNextBuildCommand(packager: PackageManager, nextAppDir: string) {
const command = `${packager === "npm" ? "npx" : packager} next build`;
execSync(command, {
stdio: "inherit",
cwd: nextAppDir,
env: {
...process.env,
// equivalent to: https://github.com/sst/open-next/blob/f61b0e9/packages/open-next/src/build.ts#L168-L173
// equivalent to: https://github.com/opennextjs/opennextjs-aws/blob/f61b0e9/packages/open-next/src/build.ts#L168-L173
// Equivalent to setting `output: "standalone"` in next.config.js
NEXT_PRIVATE_STANDALONE: "true",
},
Expand Down
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
31 changes: 12 additions & 19 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 projectOpts The options for the project
*/
export async function build(appDir: string, opts: BuildOptions): Promise<void> {
if (!opts.skipBuild) {
export async function build(projectOpts: ProjectOptions): Promise<void> {
if (!projectOpts.skipNextBuild) {
// Build the next app
await buildNextjsApp(appDir);
await buildNextjsApp(projectOpts.sourceDir);
}

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

// Create a clean output directory
const outputDir = path.resolve(opts.outputDir ?? appDir, ".worker-next");
await cleanDirectory(outputDir);
// Clean the output directory
await cleanDirectory(projectOpts.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(projectOpts.sourceDir, ".next"), join(projectOpts.outputDir, ".next"), { recursive: true });

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

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 @@ -18,15 +18,15 @@ 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],
bundle: true,
outfile: cacheHandlerOutputFile,
format: "esm",
target: "esnext",
minify: true,
minify: config.build.shouldMinify,
define: {
"process.env.__OPENNEXT_KV_BINDING_NAME": `"${config.cache.kvBindingName}"`,
},
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
45 changes: 32 additions & 13 deletions packages/cloudflare/src/cli/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@ import { readdirSync, statSync } from "node:fs";
const PACKAGE_NAME = "@opennextjs/cloudflare";

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
skipNextBuild: boolean;
// Whether minification should be enabled or not
shouldMinify: 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 @@ -39,13 +45,11 @@ export type Config = {
/**
* Computes the configuration.
*
* @param appDir Next app root folder
* @param outputDir Output of the cloudflare builder
*
* @returns the configuration, see `Config`
* @param projectOpts The options for the project
* @returns The configuration, see `Config`
*/
export function getConfig(appDir: string, outputDir: string): Config {
const dotNext = path.join(outputDir, ".next");
export function getConfig(projectOpts: ProjectOptions): Config {
const dotNext = path.join(projectOpts.outputDir, ".next");
const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, "");
const standaloneRoot = path.join(dotNext, "standalone");
const standaloneApp = path.join(standaloneRoot, appPath);
Expand All @@ -59,11 +63,15 @@ export function getConfig(appDir: string, outputDir: string): Config {
process.env.__OPENNEXT_KV_BINDING_NAME ??= "NEXT_CACHE_WORKERS_KV";

return {
buildTimestamp: Date.now(),
build: {
timestamp: Date.now(),
skipNextBuild: projectOpts.skipNextBuild,
shouldMinify: projectOpts.minify,
},

paths: {
nextApp: appDir,
builderOutput: outputDir,
sourceDir: projectOpts.sourceDir,
outputDir: projectOpts.outputDir,
dotNext,
standaloneRoot,
standaloneApp,
Expand All @@ -89,6 +97,17 @@ export function containsDotNextDir(folder: string): boolean {
}
}

export type ProjectOptions = {
// Next app root folder
sourceDir: string;
// The directory to save the output to (defaults to the app's directory)
outputDir: string;
// Whether the Next.js build should be skipped (i.e. if the `.next` dir is already built)
skipNextBuild: boolean;
// Whether minification of the worker should be enabled
minify: 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
15 changes: 10 additions & 5 deletions packages/cloudflare/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ console.log(`Building the Next.js app in the current folder (${nextAppDir})`);

if (!["js", "cjs", "mjs", "ts"].some((ext) => existsSync(`./next.config.${ext}`))) {
// TODO: we can add more validation later
throw new Error("Error: Not in a Next.js app project");
console.error(
"Error: next.config file not found. Please make sure you run the command inside a Next.js app"
);
process.exit(1);
}

const { skipBuild, outputDir } = getArgs();
const { skipNextBuild, outputDir, minify } = getArgs();

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

0 comments on commit ab5f1f7

Please sign in to comment.