Files
soul-yongping/scripts/prepare-standalone.js

104 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* 构建后准备 standalone 目录:
* - 复制 .next/static 和 public 到 .next/standalone
* - 同步 BUILD_ID / manifest 等索引文件
*
* 用途:
* - 本地pnpm build 之后,可直接 node .next/standalone/server.js
* - 宝塔:若项目路径指向 .next/standalone用 node server.js 即可
*/
const fs = require('fs');
const path = require('path');
const rootDir = path.join(__dirname, '..');
const standaloneDir = path.join(rootDir, '.next', 'standalone');
const staticSrc = path.join(rootDir, '.next', 'static');
const staticDst = path.join(standaloneDir, '.next', 'static');
const publicSrc = path.join(rootDir, 'public');
const publicDst = path.join(standaloneDir, 'public');
function copyDir(src, dst) {
if (!fs.existsSync(src)) {
console.warn(`⚠️ 跳过复制:${src} 不存在`);
return;
}
if (fs.existsSync(dst)) {
fs.rmSync(dst, { recursive: true, force: true });
}
fs.mkdirSync(dst, { recursive: true });
const entries = fs.readdirSync(src, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const dstPath = path.join(dst, entry.name);
if (entry.isDirectory()) {
copyDir(srcPath, dstPath);
} else {
fs.copyFileSync(srcPath, dstPath);
}
}
}
console.log('🔧 准备 standalone 目录(复制静态资源和索引)...');
if (!fs.existsSync(standaloneDir)) {
console.error('❌ 错误:未找到 .next/standalone 目录,请先执行 pnpm build');
process.exit(1);
}
if (!fs.existsSync(staticSrc)) {
console.error('❌ 错误:.next/static 不存在,请先执行 pnpm build');
process.exit(1);
}
console.log(' .next/static → .next/standalone/.next/static');
copyDir(staticSrc, staticDst);
const chunksDir = path.join(staticDst, 'chunks');
if (!fs.existsSync(chunksDir)) {
console.error('❌ 错误:复制后 .next/standalone/.next/static/chunks 不存在,本地/宝塔都会 404');
process.exit(1);
}
// 禁止把开发态 Turbopack 产物打进 standalone否则线上会 500 / Failed to load chunk
const chunkFiles = fs.readdirSync(chunksDir);
const turbopackChunk = chunkFiles.find((f) => f.startsWith('turbopack-') && f.endsWith('.js'));
if (turbopackChunk) {
console.error('❌ 错误:检测到开发态产物 ' + turbopackChunk);
console.error(' 当前 .next/static 来自 next dev不能用于线上。请在本机执行');
console.error(' pnpm run clean && pnpm build');
console.error(' 然后重新部署 .next/standalone 整个目录。');
process.exit(1);
}
console.log(' public → .next/standalone/public');
copyDir(publicSrc, publicDst);
// 同步构建索引(与 devlop 打包一致)
const nextRoot = path.join(rootDir, '.next');
const nextStandalone = path.join(standaloneDir, '.next');
const indexFiles = [
'BUILD_ID',
'build-manifest.json',
'app-path-routes-manifest.json',
'routes-manifest.json',
'prerender-manifest.json',
'required-server-files.json',
'fallback-build-manifest.json',
];
for (const name of indexFiles) {
const src = path.join(nextRoot, name);
const dst = path.join(nextStandalone, name);
if (fs.existsSync(src)) {
try {
fs.copyFileSync(src, dst);
} catch (e) {
console.warn(' [警告] 复制索引失败 %s: %s', name, e.message);
}
}
}
console.log('✅ standalone 目录已就绪(可直接 node .next/standalone/server.js');