Next.js 16 fails to build
Getting some weird copy errors from files that do not exist:
[WebServer] Error: ENOENT: no such file or directory, copyfile '/home/runner/work/nodejs.org/nodejs.org/apps/site/.next/standalone/apps/site/.next/server/chunks/ssr/[root-of-the-server]__92b48411._.js' -> '/home/runner/work/nodejs.org/nodejs.org/apps/site/.open-next/server-functions/default/apps/site/.next/server/chunks/ssr/[root-of-the-server]__92b48411._.js'
[WebServer] at copyFileSync (node:fs:3086:11)
[WebServer] at file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected]/node_modules/@opennextjs/aws/dist/build/copyTracedFiles.js:196:13
[WebServer] at Map.forEach (<anonymous>)
[WebServer] at copyTracedFiles (file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected]/node_modules/@opennextjs/aws/dist/build/copyTracedFiles.js:169:17)
[WebServer] at generateBundle (file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected][email protected]/node_modules/@opennextjs/cloudflare/dist/cli/build/open-next/createServerBundle.js:120:60)
[WebServer] at createServerBundle (file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected][email protected]/node_modules/@opennextjs/cloudflare/dist/cli/build/open-next/createServerBundle.js:74:11)
[WebServer] at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
[WebServer] at async build (file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected][email protected]/node_modules/@opennextjs/cloudflare/dist/cli/build/build.js:64:5)
[WebServer] at async buildCommand (file:///home/runner/work/nodejs.org/nodejs.org/node_modules/.pnpm/@[email protected][email protected]/node_modules/@opennextjs/cloudflare/dist/cli/commands/build.js:13:5) {
[WebServer] errno: -2,
[WebServer] code: 'ENOENT',
[WebServer] syscall: 'copyfile',
[WebServer] path: '/home/runner/work/nodejs.org/nodejs.org/apps/site/.next/standalone/apps/site/.next/server/chunks/ssr/[root-of-the-server]__92b48411._.js',
[WebServer] dest: '/home/runner/work/nodejs.org/nodejs.org/apps/site/.open-next/server-functions/default/apps/site/.next/server/chunks/ssr/[root-of-the-server]__92b48411._.js'
[WebServer] }
[WebServer] ELIFECYCLE Command failed with exit code 1.
Ref PR: https://github.com/nodejs/nodejs.org/pull/8218
cc @vicb @dario-piotrowicz
Could that be a turbopack build?
You have to explicitly use next build --webpack with Next 16 to opt-out of the now default turbopack which is not yet supported
Could that be a turbopack build?
You have to explicitly use
next build --webpackwith Next 16 to opt-out of the now default turbopack which is not yet supported
Weren't Turbopack builds working with OpenNext on Next.js 15? Or was it just that it was using Webpack by default?
15 was using webpack by default. turbopack builds never worked - should hopefully be fixed in a few weeks.
My personal advice is to hold off on upgrading your app to 16 until a couple months after release, as Vercel usually rushes out the release for their October conference. Like the prior years, the Major.0 releases have some major bugs. Eg for 16, the default turbopack breaks Portals...
The issue is turbopack moving the css files to a different directory. You can fix this by having the following script move them to the directory opennext expects them to be in :
update your package.json to include this script to run post build:
next build --turbopack && node scripts/fix-css-paths.js
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Define paths
const buildDir = '.next';
const standaloneDir = path.join(buildDir, 'standalone/engagement/frontend/.next/static');
const mainStaticDir = path.join(buildDir, 'static');
const mainChunksDir = path.join(mainStaticDir, 'chunks');
const standaloneChunksDir = path.join(standaloneDir, 'chunks');
const standaloneCssDir = path.join(standaloneDir, 'css');
/**
* Copy CSS files from source to destination directory
*/
function copyCssFiles(sourceDir, destDir, label) {
if (!fs.existsSync(sourceDir)) {
return { files: [], count: 0 };
}
// Create destination directory if it doesn't exist
if (!fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true });
}
const files = fs.readdirSync(sourceDir);
const cssFiles = files.filter((file) => file.endsWith('.css'));
if (cssFiles.length === 0) {
return { files: [], count: 0 };
}
const copiedFiles = [];
cssFiles.forEach((file) => {
const sourcePath = path.join(sourceDir, file);
const destPath = path.join(destDir, file);
// Only copy if file doesn't exist in destination
if (!fs.existsSync(destPath)) {
try {
fs.copyFileSync(sourcePath, destPath);
console.log(`Copied: ${file}`);
copiedFiles.push(file);
} catch (error) {
console.error(`Failed to copy ${file}:`, error.message);
}
}
});
return { files: copiedFiles, count: copiedFiles.length };
}
/**
* Update manifest files to reference CSS files in the correct location
*/
function updateManifests() {
const manifestPaths = [
path.join(buildDir, 'build-manifest.json'),
path.join(standaloneDir, '../build-manifest.json'),
path.join(buildDir, 'app-build-manifest.json'),
path.join(standaloneDir, '../app-build-manifest.json'),
];
manifestPaths.forEach((manifestPath) => {
if (fs.existsSync(manifestPath)) {
try {
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
let updated = false;
// Function to update paths in manifest
function updatePaths(obj) {
if (Array.isArray(obj)) {
return obj.map((item) => {
if (typeof item === 'string' && item.includes('static/chunks/') && item.endsWith('.css')) {
updated = true;
return item.replace('static/chunks/', 'static/css/');
}
return typeof item === 'object' ? updatePaths(item) : item;
});
} else if (obj && typeof obj === 'object') {
const result = {};
for (const [key, value] of Object.entries(obj)) {
result[key] = updatePaths(value);
}
return result;
}
return obj;
}
const updatedManifest = updatePaths(manifest);
if (updated) {
fs.writeFileSync(manifestPath, JSON.stringify(updatedManifest, null, 2));
console.log(`Updated manifest: ${path.basename(manifestPath)}`);
}
} catch (error) {
console.error(`Failed to update manifest ${manifestPath}:`, error.message);
}
}
});
}
// Main execution
try {
let totalCopied = 0;
// Copy CSS files from main chunks directory to standalone css directory
const mainResult = copyCssFiles(mainChunksDir, standaloneCssDir, 'Main chunks');
totalCopied += mainResult.count;
// Also copy from standalone chunks directory if it exists (backup)
const standaloneResult = copyCssFiles(standaloneChunksDir, standaloneCssDir, 'Standalone chunks');
totalCopied += standaloneResult.count;
// Update manifest files to reference CSS files in the correct location
updateManifests();
if (totalCopied > 0) {
console.log(`Successfully organized ${totalCopied} CSS file(s) for OpenNext compatibility`);
} else {
console.log('No new CSS files to organize');
}
} catch (error) {
console.error('Error during CSS file organization:', error.message);
process.exit(1);
}
@vicb it seems to fail even on Webpack mode. Since it tries to search for middleware.js
[custom build] Running: wrangler-build-time-fs-assets-polyfilling --assets pages --assets snippets --assets-output-dir .open-next/assets
[custom build] 🛠️ Setting up Wrangler fs polyfills (v0.0.0)
[custom build]
[custom build]
[custom build]
✘ [ERROR] Custom build failed: Error: Build failed with 1 error:
.open-next/middleware/handler.mjs:562:34: ERROR: Could not resolve "./.next/server/middleware.js"
at failureErrorWithLog
(/home/cwunder/GitHub/nodejs.org/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1463:15)
at
/home/cwunder/GitHub/nodejs.org/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:924:25
at
/home/cwunder/GitHub/nodejs.org/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1341:9
at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
errors: [Getter/Setter],
warnings: [Getter/Setter]
}
✘ [ERROR] Build failed with 1 error:
✘ [ERROR] Could not resolve
"./.next/server/middleware.js"
.open-next/middleware/handler.mjs:562:34:
562 │ ...e = await (await import("./.next/server/middleware.js")).default;
Can you rename your proxy.ts back to middleware.ts. It's deprecated but it should still work?
Can you rename your
proxy.tsback tomiddleware.ts. It's deprecated but it should still work?
Right, or, I could make a PR upstream (OpenNext) to add support to proxy.ts? Let me know if that's a sound alternative :)
My personal advice is to hold off on upgrading your app to 16 until a couple months after release, as
Vercelusually rushes out the release for their October conference. Like the prior years, the Major.0 releases have some major bugs. Eg for 16, the default turbopack breaks Portals...
I missed this, but we're not aiming to migrate now, but we often do early builds with Node for new releases of Next.js to see early compatibility problems.
Can you rename your
proxy.tsback tomiddleware.ts. It's deprecated but it should still work?Right, or, I could make a PR upstream (OpenNext) to add support to proxy.ts? Let me know if that's a sound alternative :)
Conico is working on https://github.com/opennextjs/opennextjs-aws/pulls. Perhaps you can check out that branch and see if the proxy changes works.