Skip to content

Commit

Permalink
refactor: use join instead of path.join
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx authored and vicb committed Oct 14, 2024
1 parent 2d4d9bc commit 081098b
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 66 deletions.
34 changes: 15 additions & 19 deletions packages/cloudflare/src/cli/build/build-worker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Plugin, build } from "esbuild";
import { cp, readFile, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { existsSync, readFileSync } from "node:fs";
import { Config } from "../config";
import { copyPackageCliFiles } from "./patches/investigated/copy-package-cli-files";
Expand All @@ -14,11 +15,10 @@ import { patchFindDir } from "./patches/to-investigate/patch-find-dir";
import { patchReadFile } from "./patches/to-investigate/patch-read-file";
import { patchRequire } from "./patches/investigated/patch-require";
import { patchWranglerDeps } from "./patches/to-investigate/wrangler-deps";
import path from "node:path";
import { updateWebpackChunksFile } from "./patches/investigated/update-webpack-chunks-file";

/** The dist directory of the Cloudflare adapter package */
const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
const packageDistDir = join(dirname(fileURLToPath(import.meta.url)), "..");

/**
* Using the Next.js build output in the `.next` directory builds a workerd compatible output
Expand All @@ -30,18 +30,14 @@ export async function buildWorker(config: Config): Promise<void> {
console.log(`\x1b[35m⚙️ Copying files...\n\x1b[0m`);

// Copy over client-side generated files
await cp(
path.join(config.paths.dotNext, "static"),
path.join(config.paths.outputDir, "assets", "_next", "static"),
{
recursive: true,
}
);
await cp(join(config.paths.dotNext, "static"), 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.sourceDir, "public");
const publicDir = join(config.paths.sourceDir, "public");
if (existsSync(publicDir)) {
await cp(publicDir, path.join(config.paths.outputDir, "assets"), {
await cp(publicDir, join(config.paths.outputDir, "assets"), {
recursive: true,
});
}
Expand All @@ -51,11 +47,11 @@ 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.outputDir, "index.mjs");
const workerEntrypoint = join(config.paths.internalTemplates, "worker.ts");
const workerOutputFile = join(config.paths.outputDir, "index.mjs");

const nextConfigStr =
readFileSync(path.join(config.paths.standaloneApp, "/server.js"), "utf8")?.match(
readFileSync(join(config.paths.standaloneApp, "/server.js"), "utf8")?.match(
/const nextConfig = ({.+?})\n/
)?.[1] ?? {};

Expand All @@ -76,15 +72,15 @@ export async function buildWorker(config: Config): Promise<void> {
// Note: we apply an empty shim to next/dist/compiled/ws because it generates two `eval`s:
// eval("require")("bufferutil");
// eval("require")("utf-8-validate");
"next/dist/compiled/ws": path.join(config.paths.internalTemplates, "shims", "empty.ts"),
"next/dist/compiled/ws": join(config.paths.internalTemplates, "shims", "empty.ts"),
// Note: we apply an empty shim to next/dist/compiled/edge-runtime since (amongst others) it generated the following `eval`:
// eval(getModuleCode)(module, module.exports, throwingRequire, params.context, ...Object.values(params.scopedContext));
// which comes from https://github.com/vercel/edge-runtime/blob/6e96b55f/packages/primitives/src/primitives/load.js#L57-L63
// QUESTION: Why did I encountered this but mhart didn't?
"next/dist/compiled/edge-runtime": path.join(config.paths.internalTemplates, "shims", "empty.ts"),
"next/dist/compiled/edge-runtime": join(config.paths.internalTemplates, "shims", "empty.ts"),
// `@next/env` is a library Next.js uses for loading dotenv files, for obvious reasons we need to stub it here
// source: https://github.com/vercel/next.js/tree/0ac10d79720/packages/next-env
"@next/env": path.join(config.paths.internalTemplates, "shims", "env.ts"),
"@next/env": join(config.paths.internalTemplates, "shims", "env.ts"),
},
define: {
// config file used by Next.js, see: https://github.com/vercel/next.js/blob/68a7128/packages/next/src/build/utils.ts#L2137-L2139
Expand Down Expand Up @@ -178,10 +174,10 @@ function createFixRequiresESBuildPlugin(config: Config): Plugin {
setup(build) {
// Note: we (empty) shim require-hook modules as they generate problematic code that uses requires
build.onResolve({ filter: /^\.\/require-hook$/ }, () => ({
path: path.join(config.paths.internalTemplates, "shims", "empty.ts"),
path: join(config.paths.internalTemplates, "shims", "empty.ts"),
}));
build.onResolve({ filter: /\.\/lib\/node-fs-methods$/ }, () => ({
path: path.join(config.paths.internalTemplates, "shims", "empty.ts"),
path: join(config.paths.internalTemplates, "shims", "empty.ts"),
}));
},
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Config } from "../../../config";
import { cpSync } from "node:fs";
import path from "node:path";
import { join } from "node:path";

/**
* Copies the template files present in the cloudflare adapter package into the standalone node_modules folder
*/
export function copyPackageCliFiles(packageDistDir: string, config: Config) {
console.log("# copyPackageTemplateFiles");
const sourceDir = path.join(packageDistDir, "cli");
const destinationDir = path.join(config.paths.internalPackage, "cli");
const sourceDir = join(packageDistDir, "cli");
const destinationDir = join(config.paths.internalPackage, "cli");

cpSync(sourceDir, destinationDir, { recursive: true });
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
import { Config } from "../../../../config";
import { getUpdatedWebpackChunksFileContent } from "./get-updated-webpack-chunks-file-content";
import path from "node:path";
import { join } from "node:path";

/**
* Fixes the webpack-runtime.js file by removing its webpack dynamic requires.
Expand All @@ -11,11 +11,11 @@ import path from "node:path";
*/
export async function updateWebpackChunksFile(config: Config) {
console.log("# updateWebpackChunksFile");
const webpackRuntimeFile = path.join(config.paths.standaloneAppServer, "webpack-runtime.js");
const webpackRuntimeFile = join(config.paths.standaloneAppServer, "webpack-runtime.js");

const fileContent = readFileSync(webpackRuntimeFile, "utf-8");

const chunks = readdirSync(path.join(config.paths.standaloneAppServer, "chunks"))
const chunks = readdirSync(join(config.paths.standaloneAppServer, "chunks"))
.filter((chunk) => /^\d+\.js$/.test(chunk))
.map((chunk) => {
console.log(` - chunk ${chunk}`);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { join, posix } from "node:path";
import { Config } from "../../../config";
import { globSync } from "glob";
import path from "node:path";
import { normalizePath } from "../../utils";

/**
Expand All @@ -13,18 +13,16 @@ import { normalizePath } from "../../utils";
export function inlineEvalManifest(code: string, config: Config): string {
console.log("# inlineEvalManifest");
const manifestJss = globSync(
normalizePath(path.join(config.paths.standaloneAppDotNext, "**", "*_client-reference-manifest.js"))
).map((file) =>
normalizePath(file).replace(normalizePath(config.paths.standaloneApp) + path.posix.sep, "")
);
normalizePath(join(config.paths.standaloneAppDotNext, "**", "*_client-reference-manifest.js"))
).map((file) => normalizePath(file).replace(normalizePath(config.paths.standaloneApp) + posix.sep, ""));
return code.replace(
/function evalManifest\((.+?), .+?\) {/,
`$&
${manifestJss
.map(
(manifestJs) => `
if ($1.endsWith("${manifestJs}")) {
require(${JSON.stringify(path.join(config.paths.standaloneApp, manifestJs))});
require(${JSON.stringify(join(config.paths.standaloneApp, manifestJs))});
return {
__RSC_MANIFEST: {
"${manifestJs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { existsSync, readFileSync } from "node:fs";
import { Config } from "../../../config";
import path from "node:path";
import { join } from "node:path";

/**
* Inlines the middleware manifest from the build output to prevent a dynamic require statement
Expand All @@ -9,7 +9,7 @@ import path from "node:path";
export function inlineMiddlewareManifestRequire(code: string, config: Config) {
console.log("# inlineMiddlewareManifestRequire");

const middlewareManifestPath = path.join(config.paths.standaloneAppServer, "middleware-manifest.json");
const middlewareManifestPath = join(config.paths.standaloneAppServer, "middleware-manifest.json");

const middlewareManifest = existsSync(middlewareManifestPath)
? JSON.parse(readFileSync(middlewareManifestPath, "utf-8"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { existsSync, readFileSync } from "node:fs";
import { Config } from "../../../config";
import path from "node:path";
import { join } from "node:path";

/**
* The following avoid various Next.js specific files `require`d at runtime since we can just read
* and inline their content during build time
*/
export function inlineNextRequire(code: string, config: Config) {
console.log("# inlineNextRequire");
const pagesManifestFile = path.join(config.paths.standaloneAppServer, "pages-manifest.json");
const appPathsManifestFile = path.join(config.paths.standaloneAppServer, "app-paths-manifest.json");
const pagesManifestFile = join(config.paths.standaloneAppServer, "pages-manifest.json");
const appPathsManifestFile = join(config.paths.standaloneAppServer, "app-paths-manifest.json");

const pagesManifestFiles = existsSync(pagesManifestFile)
? Object.values(JSON.parse(readFileSync(pagesManifestFile, "utf-8"))).map(
Expand All @@ -33,7 +33,7 @@ export function inlineNextRequire(code: string, config: Config) {
.map(
(htmlPage) => `
if (pagePath.endsWith("${htmlPage}")) {
return ${JSON.stringify(readFileSync(path.join(config.paths.standaloneApp, htmlPage), "utf-8"))};
return ${JSON.stringify(readFileSync(join(config.paths.standaloneApp, htmlPage), "utf-8"))};
}
`
)
Expand All @@ -42,7 +42,7 @@ export function inlineNextRequire(code: string, config: Config) {
.map(
(module) => `
if (pagePath.endsWith("${module}")) {
return require(${JSON.stringify(path.join(config.paths.standaloneApp, module))});
return require(${JSON.stringify(join(config.paths.standaloneApp, module))});
}
`
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Config } from "../../../config";
import { existsSync } from "node:fs";
import path from "node:path";
import { join } from "node:path";

/**
* Here we patch `findDir` so that the next server can detect whether the `app` or `pages` directory exists
Expand All @@ -15,10 +15,10 @@ export function patchFindDir(code: string, config: Config): string {
`function findDir(dir, name) {
if (dir.endsWith(".next/server")) {
if (name === "app") {
return ${existsSync(`${path.join(config.paths.standaloneAppServer, "app")}`)};
return ${existsSync(`${join(config.paths.standaloneAppServer, "app")}`)};
}
if (name === "pages") {
return ${existsSync(`${path.join(config.paths.standaloneAppServer, "pages")}`)};
return ${existsSync(`${join(config.paths.standaloneAppServer, "pages")}`)};
}
}
throw new Error("Unknown findDir call: " + dir + " " + name);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { join, posix } from "node:path";
import { Config } from "../../../config";
import { globSync } from "glob";
import path from "node:path";
import { normalizePath } from "../../utils";
import { readFileSync } from "node:fs";

Expand All @@ -13,26 +13,24 @@ export function patchReadFile(code: string, config: Config): string {
code = code.replace(
"getBuildId() {",
`getBuildId() {
return ${JSON.stringify(readFileSync(path.join(config.paths.standaloneAppDotNext, "BUILD_ID"), "utf-8"))};
return ${JSON.stringify(readFileSync(join(config.paths.standaloneAppDotNext, "BUILD_ID"), "utf-8"))};
`
);

// Same as above, the next-server code loads the manifests with `readFileSync` and we want to avoid that
// (source: https://github.com/vercel/next.js/blob/15aeb92e/packages/next/src/server/load-manifest.ts#L34-L56)
// Note: we could/should probably just patch readFileSync here or something!
const manifestJsons = globSync(
normalizePath(path.join(config.paths.standaloneAppDotNext, "**", "*-manifest.json"))
).map((file) =>
normalizePath(file).replace(normalizePath(config.paths.standaloneApp) + path.posix.sep, "")
);
normalizePath(join(config.paths.standaloneAppDotNext, "**", "*-manifest.json"))
).map((file) => normalizePath(file).replace(normalizePath(config.paths.standaloneApp) + posix.sep, ""));
code = code.replace(
/function loadManifest\((.+?), .+?\) {/,
`$&
${manifestJsons
.map(
(manifestJson) => `
if ($1.endsWith("${manifestJson}")) {
return ${readFileSync(path.join(config.paths.standaloneApp, manifestJson), "utf-8")};
return ${readFileSync(join(config.paths.standaloneApp, manifestJson), "utf-8")};
}
`
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFileSync, statSync, writeFileSync } from "node:fs";
import { Config } from "../../../config";
import path from "node:path";
import { join } from "node:path";

export function patchWranglerDeps(config: Config) {
console.log("# patchWranglerDeps");
Expand All @@ -13,7 +13,7 @@ export function patchWranglerDeps(config: Config) {
// [alias]
// # critters is `require`d from `pages.runtime.prod.js` when running wrangler dev, so we need to stub it out
// "critters" = "./.next/standalone/node_modules/cf/templates/shims/empty.ts"
const pagesRuntimeFile = path.join(distPath, "compiled", "next-server", "pages.runtime.prod.js");
const pagesRuntimeFile = join(distPath, "compiled", "next-server", "pages.runtime.prod.js");

const patchedPagesRuntime = readFileSync(pagesRuntimeFile, "utf-8").replace(
`e.exports=require("critters")`,
Expand All @@ -32,7 +32,7 @@ export function patchWranglerDeps(config: Config) {
// # try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31
// # causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works)
// #"@opentelemetry/api" = "./.next/standalone/node_modules/cf/templates/shims/throw.ts"
const tracerFile = path.join(distPath, "server", "lib", "trace", "tracer.js");
const tracerFile = join(distPath, "server", "lib", "trace", "tracer.js");

const patchedTracer = readFileSync(tracerFile, "utf-8").replaceAll(
/\w+\s*=\s*require\([^/]*opentelemetry.*\)/g,
Expand All @@ -57,7 +57,7 @@ export function patchWranglerDeps(config: Config) {
function getDistPath(config: Config): string {
for (const root of [config.paths.standaloneApp, config.paths.standaloneRoot]) {
try {
const distPath = path.join(root, "node_modules", "next", "dist");
const distPath = join(root, "node_modules", "next", "dist");
if (statSync(distPath).isDirectory()) return distPath;
} catch {
/* empty */
Expand Down
28 changes: 14 additions & 14 deletions packages/cloudflare/src/cli/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import path, { relative } from "node:path";
import { join, relative } from "node:path";
import { readdirSync, statSync } from "node:fs";

const PACKAGE_NAME = "@opennextjs/cloudflare";
Expand Down Expand Up @@ -49,16 +49,16 @@ export type Config = {
* @returns The configuration, see `Config`
*/
export function getConfig(projectOpts: ProjectOptions): Config {
const dotNext = path.join(projectOpts.outputDir, ".next");
const dotNext = join(projectOpts.outputDir, ".next");
const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, "");
const standaloneRoot = path.join(dotNext, "standalone");
const standaloneApp = path.join(standaloneRoot, appPath);
const standaloneAppDotNext = path.join(standaloneApp, ".next");
const standaloneAppServer = path.join(standaloneAppDotNext, "server");
const standaloneRoot = join(dotNext, "standalone");
const standaloneApp = join(standaloneRoot, appPath);
const standaloneAppDotNext = join(standaloneApp, ".next");
const standaloneAppServer = join(standaloneAppDotNext, "server");

const nodeModules = path.join(standaloneApp, "node_modules");
const internalPackage = path.join(nodeModules, ...PACKAGE_NAME.split("/"));
const internalTemplates = path.join(internalPackage, "cli", "templates");
const nodeModules = join(standaloneApp, "node_modules");
const internalPackage = join(nodeModules, ...PACKAGE_NAME.split("/"));
const internalTemplates = join(internalPackage, "cli", "templates");

process.env.__OPENNEXT_KV_BINDING_NAME ??= "NEXT_CACHE_WORKERS_KV";

Expand Down Expand Up @@ -91,7 +91,7 @@ export function getConfig(projectOpts: ProjectOptions): Config {

export function containsDotNextDir(folder: string): boolean {
try {
return statSync(path.join(folder, ".next")).isDirectory();
return statSync(join(folder, ".next")).isDirectory();
} catch {
return false;
}
Expand Down Expand Up @@ -124,12 +124,12 @@ function getNextjsApplicationPath(dotNextDir: string): string {
throw new Error(`Unexpected Error: no \`.next/server\` folder could be found in \`${serverPath}\``);
}

return relative(path.join(dotNextDir, "standalone"), serverPath);
return relative(join(dotNextDir, "standalone"), serverPath);
}

function findServerParentPath(parentPath: string): string | undefined {
try {
if (statSync(path.join(parentPath, ".next", "server")).isDirectory()) {
if (statSync(join(parentPath, ".next", "server")).isDirectory()) {
return parentPath;
}
} catch {
Expand All @@ -139,8 +139,8 @@ function findServerParentPath(parentPath: string): string | undefined {
const folders = readdirSync(parentPath);

for (const folder of folders) {
const subFolder = path.join(parentPath, folder);
if (statSync(path.join(parentPath, folder)).isDirectory()) {
const subFolder = join(parentPath, folder);
if (statSync(join(parentPath, folder)).isDirectory()) {
const dirServerPath = findServerParentPath(subFolder);
if (dirServerPath) {
return dirServerPath;
Expand Down

0 comments on commit 081098b

Please sign in to comment.