#!/usr/bin/env node /** * 构建前清理 .next/standalone、.next/static、.next/cache * - 避免 Next.js build 时 EBUSY(目录被占用) * - 避免混入 next dev 的 Turbopack 产物,导致打包后加载 chunk 500 / Failed to load chunk * 若曾运行 pnpm start,请先 Ctrl+C 停掉再 build */ const fs = require('fs'); const path = require('path'); const rootDir = path.join(__dirname, '..'); const nextDir = path.join(rootDir, '.next'); const dirsToClean = [ path.join(nextDir, 'standalone'), path.join(nextDir, 'static'), path.join(nextDir, 'cache'), ]; const RETRIES = 5; const DELAY_MS = 2000; function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } function removeDir(dirPath) { if (!fs.existsSync(dirPath)) return true; try { fs.rmSync(dirPath, { recursive: true, force: true, maxRetries: 3 }); return true; } catch (e) { throw e; } } async function main() { for (const dirPath of dirsToClean) { if (!fs.existsSync(dirPath)) continue; for (let attempt = 1; attempt <= RETRIES; attempt++) { try { removeDir(dirPath); const name = path.relative(nextDir, dirPath) || dirPath; console.log('[clean-standalone] 已删除 .next/' + name); break; } catch (e) { if (e.code === 'EBUSY' || e.code === 'EPERM' || e.code === 'ENOTEMPTY') { if (attempt < RETRIES) { console.warn('[clean-standalone] 目录被占用,%ds 后重试 (%d/%d)...', DELAY_MS / 1000, attempt, RETRIES); await sleep(DELAY_MS); } else { console.error('[clean-standalone] 无法删除:', dirPath); console.error(' 请先关闭:pnpm start / next dev、或占用该目录的其它程序'); console.error(' 然后重新执行:pnpm build'); process.exit(1); } } else { throw e; } } } } } main().catch((e) => { console.error(e); process.exit(1); });