| Server IP : 217.154.3.148 / Your IP : 216.73.216.90 Web Server : Apache System : Linux blissful-wright.217-154-3-148.plesk.page 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 User : gracious-boyd_hfhh1h8vo9n ( 10000) PHP Version : 8.3.31 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/vhosts/gracious-boyd.217-154-3-148.plesk.page/nextjs/ |
Upload File : |
#!/usr/bin/env node
const { cp, mkdir, rm, stat, writeFile, readFile } = require('fs/promises');
const path = require('path');
const projectRoot = process.cwd();
const standaloneDir = path.join(projectRoot, '.next', 'standalone');
const standaloneNextDir = path.join(standaloneDir, '.next');
const staticSrc = path.join(projectRoot, '.next', 'static');
const staticDest = path.join(standaloneNextDir, 'static');
const publicSrc = path.join(projectRoot, 'public');
const publicDest = path.join(standaloneDir, 'public');
const buildDir = path.join(projectRoot, '.next');
const serverChunksDir = path.join(buildDir, 'server', 'chunks');
const opencvSource = path.join(projectRoot, 'node_modules', 'opencv-wasm', 'opencv.wasm');
const opencvTarget = path.join(serverChunksDir, 'opencv.wasm');
const buildIdPath = path.join(buildDir, 'BUILD_ID');
const routesManifestPath = path.join(buildDir, 'routes-manifest.json');
const prerenderManifestPath = path.join(buildDir, 'prerender-manifest.json');
const functionsConfigManifestPath = path.join(buildDir, 'server', 'functions-config-manifest.json');
const appPathRoutesManifestPath = path.join(buildDir, 'app-path-routes-manifest.json');
const requiredServerFilesPath = path.join(buildDir, 'required-server-files.json');
const runtimeBasePath = process.env.NEXT_RUNTIME_BASE_PATH ?? '/nextjs';
async function exists(dir) {
try {
await stat(dir);
return true;
} catch (error) {
if (error && error.code === 'ENOENT') {
return false;
}
throw error;
}
}
async function copyDir(src, dest, { label }) {
if (!(await exists(src))) {
console.warn(`[postbuild] Skipping ${label}; not found at ${src}`);
return;
}
if (!(await exists(path.dirname(dest)))) {
await mkdir(path.dirname(dest), { recursive: true });
}
if (await exists(dest)) {
await rm(dest, { recursive: true, force: true });
}
await cp(src, dest, { recursive: true });
console.log(`[postbuild] Copied ${label} to ${dest}`);
}
const main = async () => {
if (!(await exists(standaloneDir))) {
console.warn('[postbuild] Standalone output not found; nothing to copy.');
} else {
await copyDir(staticSrc, staticDest, { label: 'Next.js static assets' });
await copyDir(publicSrc, publicDest, { label: 'public assets' });
}
// Ensure runtime has the wasm bundle available where the server expects it
if (await exists(opencvSource)) {
if (!(await exists(serverChunksDir))) {
await mkdir(serverChunksDir, { recursive: true });
}
await cp(opencvSource, opencvTarget).catch((error) => {
console.warn('[postbuild] Failed to copy opencv.wasm to server chunks:', error);
});
} else {
console.warn('[postbuild] opencv.wasm source not found; skipping copy.');
}
// Next.js 15 + app router occasionally omits legacy manifests when using custom basePath.
// Generate minimal fallbacks so `next start` keeps working in PM2.
if (!(await exists(buildIdPath))) {
const buildId = Date.now().toString(36);
await writeFile(buildIdPath, `${buildId}\n`, 'utf8');
console.warn(`[postbuild] BUILD_ID missing; generated ${buildId}.`);
}
if (!(await exists(routesManifestPath))) {
const { normalizeAppPath } = require('next/dist/shared/lib/router/utils/app-paths');
const { escapeStringRegexp } = require('next/dist/shared/lib/escape-regexp');
const appPathsManifestPath = path.join(buildDir, 'server', 'app-paths-manifest.json');
const pagesManifestPath = path.join(buildDir, 'server', 'pages-manifest.json');
const staticRoutes = new Map();
const appPathRoutes = {};
const addStaticRoute = (routePath) => {
if (!routePath) return;
if (!routePath.startsWith('/')) routePath = `/${routePath}`;
const normalized = routePath === '' ? '/' : routePath;
if (!staticRoutes.has(normalized)) {
const escaped = escapeStringRegexp(normalized === '/' ? '/' : normalized.replace(/\/$/, ''));
const pattern = normalized === '/' ? '^/$' : `^${escaped}(?:/)?$`;
staticRoutes.set(normalized, {
page: normalized,
regex: pattern,
routeKeys: {},
namedRegex: pattern,
});
}
};
try {
const appPathsRaw = await readFile(appPathsManifestPath, 'utf8');
const appPaths = JSON.parse(appPathsRaw);
for (const originalPath of Object.keys(appPaths || {})) {
const route = normalizeAppPath(originalPath);
addStaticRoute(route);
if (!appPathRoutes[route]) appPathRoutes[route] = [];
appPathRoutes[route].push(originalPath);
}
} catch (error) {
console.warn('[postbuild] Unable to read app-paths-manifest.json:', error);
}
try {
const pagesRaw = await readFile(pagesManifestPath, 'utf8');
const pagesManifest = JSON.parse(pagesRaw);
for (const page of Object.keys(pagesManifest || {})) {
if (!page.startsWith('/api')) addStaticRoute(page);
}
} catch {
// Optional manifest; ignore if missing
}
const manifest = {
version: 5,
pages404: false,
basePath: runtimeBasePath,
redirects: [],
rewrites: { beforeFiles: [], afterFiles: [], fallback: [] },
headers: [
{
source: '/_next/static/:path*',
headers: [
{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
],
},
{
source: '/visualizer',
headers: [
{ key: 'Cache-Control', value: 'no-store' },
],
},
{
source: '/:path*',
has: [
{ type: 'header', key: 'accept', value: '.*text/html.*' },
],
headers: [
{ key: 'Cache-Control', value: 'no-store' },
],
},
],
dynamicRoutes: [],
staticRoutes: Array.from(staticRoutes.values()),
dataRoutes: [],
rscRoutes: [],
appPathRoutes,
};
await writeFile(routesManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.warn('[postbuild] routes-manifest.json missing; generated from app manifest.');
}
if (!(await exists(appPathRoutesManifestPath))) {
try {
const { normalizeAppPath } = require('next/dist/shared/lib/router/utils/app-paths');
const appPathsRaw = await readFile(path.join(buildDir, 'server', 'app-paths-manifest.json'), 'utf8');
const appPaths = JSON.parse(appPathsRaw);
const manifest = {};
for (const key of Object.keys(appPaths || {})) {
manifest[key] = normalizeAppPath ? normalizeAppPath(key) : key;
}
await writeFile(appPathRoutesManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.warn('[postbuild] app-path-routes-manifest.json missing; generated from app manifest.');
} catch (error) {
console.warn('[postbuild] Unable to generate app-path-routes-manifest.json:', error);
}
}
if (!(await exists(prerenderManifestPath))) {
const manifest = {
version: 5,
basePath: runtimeBasePath,
notFoundRoutes: [],
routes: {},
dynamicRoutes: {},
preview: {
previewModeId: '',
previewModeSigningKey: '',
previewModeEncryptionKey: '',
},
};
await writeFile(prerenderManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.warn('[postbuild] prerender-manifest.json missing; wrote minimal stub.');
}
if (!(await exists(functionsConfigManifestPath))) {
const manifest = {
version: 1,
functions: {},
};
await writeFile(functionsConfigManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.warn('[postbuild] functions-config-manifest.json missing; wrote minimal stub.');
}
if (!(await exists(requiredServerFilesPath))) {
const manifest = {
version: 4,
config: {
basePath: runtimeBasePath,
distDir: '.next',
appDir: true,
trailingSlash: false,
publicRuntimeConfig: {},
serverRuntimeConfig: {},
},
files: [
'.next/server/app/page.js',
'.next/server/app/visualizer/page.js',
'.next/server/app/visualizer2/page.js',
'.next/server/app/calibrate/page.js',
],
ignore: [],
};
await writeFile(requiredServerFilesPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
console.warn('[postbuild] required-server-files.json missing; wrote minimal stub.');
}
};
main().catch((error) => {
console.error('[postbuild] Failed to finalize standalone bundle:', error);
process.exitCode = 1;
});