From fb2351ffe7b5b6a1b89baa0548358db1fee52bfb Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sat, 28 Feb 2026 00:54:23 -0300 Subject: [PATCH] fix: sanitize hardcoded build-machine paths in standalone output (#147) Next.js standalone bakes absolute build-time paths (outputFileTracingRoot, appDir, turbopack root) into server.js and required-server-files.json. When installed via npm on a different machine, these paths don't exist, causing ENOENT errors. The prepublish script now replaces build-machine absolute paths with '.' (relative) so they resolve correctly wherever the package is installed. --- scripts/prepublish.mjs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/prepublish.mjs b/scripts/prepublish.mjs index 55b5ec1075..381181e41e 100644 --- a/scripts/prepublish.mjs +++ b/scripts/prepublish.mjs @@ -51,6 +51,38 @@ console.log(" ๐Ÿ“‹ Copying standalone build to app/..."); mkdirSync(APP_DIR, { recursive: true }); cpSync(standaloneDir, APP_DIR, { recursive: true }); +// โ”€โ”€ Step 5.5: Sanitize hardcoded build-machine paths โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +// Next.js standalone bakes absolute build-time paths into server.js and +// required-server-files.json (outputFileTracingRoot, appDir, turbopack root). +// Replace the build machine's absolute path with "." (current directory) +// so paths resolve relative to wherever the standalone app/ is installed. +console.log(" ๐Ÿงน Sanitizing build-machine paths..."); +const buildRoot = ROOT.replace(/\\/g, "/"); // normalise for regex safety +const sanitizeTargets = [ + join(APP_DIR, "server.js"), + join(APP_DIR, ".next", "required-server-files.json"), +]; +let sanitisedCount = 0; +for (const filePath of sanitizeTargets) { + if (!existsSync(filePath)) continue; + let content = readFileSync(filePath, "utf8"); + // Escape special regex characters in the path + const escaped = buildRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const re = new RegExp(escaped, "g"); + const matches = content.match(re); + if (matches) { + // Replace with "." so Next.js resolves paths relative to the standalone dir + content = content.replace(re, "."); + writeFileSync(filePath, content); + sanitisedCount += matches.length; + } +} +if (sanitisedCount > 0) { + console.log(` โœ… Sanitised ${sanitisedCount} hardcoded path references`); +} else { + console.log(" โ„น๏ธ No hardcoded paths found to sanitise"); +} + // โ”€โ”€ Step 6: Copy static assets โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const staticSrc = join(ROOT, ".next", "static"); const staticDest = join(APP_DIR, ".next", "static");