#!/usr/bin/env node /** * This is an ultra-minimal build script for Vercel * that creates a temporary minimal Next.js config * to avoid common build issues. */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); console.log('šŸš€ Starting minimal build process...'); // Function to patch the require-hook.js file to fix the __non_webpack_require__ error function patchRequireHook() { const hookPath = path.join(process.cwd(), 'node_modules/next/dist/server/require-hook.js'); if (fs.existsSync(hookPath)) { // Backup the original file if not already backed up const backupPath = `${hookPath}.original`; if (!fs.existsSync(backupPath)) { fs.copyFileSync(hookPath, backupPath); console.log('āœ… Backed up original require-hook.js'); } // Read the current content let content = fs.readFileSync(hookPath, 'utf8'); // Check if the file is already patched if (content.includes('// PATCHED TO FIX __non_webpack_require__ ERROR')) { console.log('āœ… require-hook.js already patched'); return true; } // Add a patch at the beginning of the file to define __non_webpack_require__ const patchedContent = `// PATCHED TO FIX __non_webpack_require__ ERROR if (typeof __non_webpack_require__ === 'undefined') { global.__non_webpack_require__ = require; } // Make sure eval is available (sometimes used by next) if (typeof globalThis.eval !== 'function') { globalThis.eval = eval; } ${content}`; // Write the patched file fs.writeFileSync(hookPath, patchedContent); console.log('āœ… Patched require-hook.js to fix __non_webpack_require__ error'); // Also create a global patch file to ensure these definitions are available createGlobalNextPatch(); return true; } else { console.error('āŒ Could not find require-hook.js at', hookPath); return false; } } // Create a global patch file for Next.js modules function createGlobalNextPatch() { try { // Create a directory for our patches const patchDir = path.join(process.cwd(), 'patches'); if (!fs.existsSync(patchDir)) { fs.mkdirSync(patchDir, { recursive: true }); } // Create a patch file that will be loaded before anything else const patchPath = path.join(patchDir, 'next-globals.js'); const patchContent = ` // Global patches for Next.js to fix common build errors console.log('Applying Next.js global patches...'); // Fix for __non_webpack_require__ not defined if (typeof global.__non_webpack_require__ === 'undefined') { global.__non_webpack_require__ = require; console.log('Patched global.__non_webpack_require__'); } // Fix for missing process.env in some contexts if (typeof process.env !== 'object') { process.env = {}; console.log('Patched process.env'); } // Fix for missing globalThis if (typeof globalThis === 'undefined') { global.globalThis = global; console.log('Patched globalThis'); } // Fix for eval not being available if (typeof globalThis.eval !== 'function') { globalThis.eval = eval; console.log('Patched globalThis.eval'); } // Other potential fixes can be added here console.log('Next.js global patches applied successfully'); `; fs.writeFileSync(patchPath, patchContent); console.log('āœ… Created global Next.js patch file'); // Also patch the node_options to preload our patch process.env.NODE_OPTIONS = process.env.NODE_OPTIONS || ''; if (!process.env.NODE_OPTIONS.includes('-r')) { process.env.NODE_OPTIONS += ` -r ${patchPath}`; console.log(`āœ… Updated NODE_OPTIONS to preload patch: ${process.env.NODE_OPTIONS}`); } return true; } catch (err) { console.error('āŒ Failed to create global patch:', err.message); return false; } } // Create temporary minimal next.config.js function createMinimalNextConfig() { const nextConfigPath = path.join(process.cwd(), 'next.config.js'); // Backup original config if not already backed up const backupPath = path.join(process.cwd(), 'next.config.js.original'); if (fs.existsSync(nextConfigPath) && !fs.existsSync(backupPath)) { fs.copyFileSync(nextConfigPath, backupPath); console.log('āœ… Backed up original next.config.js'); } // Create a simplified next.config.js that works with dynamic routes const minimalConfig = ` /** @type {import('next').NextConfig} */ const nextConfig = { // Use standalone output instead of export for dynamic routes output: 'standalone', // Basic image configuration images: { formats: ['image/webp'], deviceSizes: [640, 750, 828, 1080, 1200, 1920], imageSizes: [16, 32, 48, 64, 96, 128, 256], dangerouslyAllowSVG: true, remotePatterns: [], }, // Disable problematic experimental features experimental: { // Disable features that might cause stack issues optimizeCss: false, memoryBasedWorkersCount: false, }, // Simplified webpack config webpack: (config) => { return config; } }; module.exports = nextConfig; `; // Write minimal config fs.writeFileSync(nextConfigPath, minimalConfig); console.log('āœ… Created minimal next.config.js with standalone output'); return true; } // Create temporary env file to disable problematic features function createTempEnv() { const envPath = path.join(process.cwd(), '.env.production.local'); const envContent = ` # Disable problematic Next.js features for build NEXT_DISABLE_SOURCEMAPS=true NEXT_TELEMETRY_DISABLED=1 NEXT_DISABLE_OPTIMIZATION=1 NEXT_MINIMAL=1 `; fs.writeFileSync(envPath, envContent); console.log('āœ… Created temporary environment variables'); return true; } // Create a patched bootstrap file to handle non-webpack require function createBootstrapPatch() { const patchDir = path.join(process.cwd(), 'patches'); if (!fs.existsSync(patchDir)) { fs.mkdirSync(patchDir, { recursive: true }); } const bootstrapPath = path.join(patchDir, 'next-bootstrap.js'); const bootstrapContent = ` // This is a patched bootstrap file to be used in place of Next.js's default bootstrap // It fixes the __non_webpack_require__ error // Define __non_webpack_require__ globally global.__non_webpack_require__ = require; // Now load the actual Next.js bootstrap require('next/dist/bin/next'); `; fs.writeFileSync(bootstrapPath, bootstrapContent); console.log('āœ… Created bootstrap patch file'); return bootstrapPath; } // Run the actual build function runBuild() { console.log('šŸ—ļø Running minimal Next.js build...'); try { // Set a higher memory limit process.env.NODE_OPTIONS = `--max-old-space-size=3072 ${process.env.NODE_OPTIONS || ''}`; // Try to run the build using our patched bootstrap const bootstrapPath = createBootstrapPatch(); // Try different build approaches in sequence const buildApproaches = [ { name: "Patched bootstrap build", command: `node ${bootstrapPath} build`, env: { SKIP_POSTINSTALL: 'true' } }, { name: "Standard Next.js build", command: "next build", env: { SKIP_POSTINSTALL: 'true' } }, { name: "Direct server build", command: "node node_modules/next/dist/bin/next build", env: { SKIP_POSTINSTALL: 'true', NODE_OPTIONS: process.env.NODE_OPTIONS } } ]; // Try each approach in sequence for (const approach of buildApproaches) { console.log(`\nšŸ”„ Trying build approach: ${approach.name}`); try { execSync(approach.command, { stdio: 'inherit', env: { ...process.env, ...approach.env } }); console.log(`āœ… Build successful with approach: ${approach.name}`); return true; } catch (err) { console.error(`āŒ Build failed with approach: ${approach.name}`); console.error(` Error: ${err.message}`); // If this is the last approach, we'll exit with failure if (approach === buildApproaches[buildApproaches.length - 1]) { return false; } // Otherwise, continue to the next approach console.log(`Trying next build approach...`); } } return false; } catch (err) { console.error('āŒ All build approaches failed:', err.message); return false; } } // Execute the build process (async function main() { try { console.log('šŸ”§ Applying build fixes...'); // Apply patches to fix require-hook.js and other issues patchRequireHook(); // Apply configuration changes createMinimalNextConfig(); createTempEnv(); // Patch known problematic modules patchProblemModules(); console.log('šŸ”§ All patches and fixes applied successfully'); // Run the build console.log('\nšŸš€ Starting build process...'); if (runBuild()) { console.log('\nāœ… Build completed successfully!'); process.exit(0); } else { console.error('\nāŒ Build failed after trying all approaches.'); console.log('Falling back to static export...'); // Try to import and run the static export script as a last resort try { require('./static-export.js'); // If we reach here, the static export was successful console.log('\nāœ… Fallback static export completed successfully!'); process.exit(0); } catch (exportErr) { console.error('\nāŒ Even static export failed:', exportErr.message); process.exit(1); } } } catch (err) { console.error('\nāŒ Critical error:', err); process.exit(1); } })(); // Function to patch other known problematic modules function patchProblemModules() { // List of other modules to patch const modulesToPatch = [ { path: 'node_modules/next/dist/server/lib/patch-fetch.js', check: '// PATCHED', patch: (content) => `// PATCHED ${content}` }, { path: 'node_modules/next/dist/compiled/react-server-dom-webpack/client.edge.js', check: '// PATCHED FOR __non_webpack_require__', patch: (content) => { if (!content.includes('__non_webpack_require__')) return content; return `// PATCHED FOR __non_webpack_require__ if (typeof __non_webpack_require__ === 'undefined') { global.__non_webpack_require__ = require; } ${content}`; } }, { path: 'node_modules/next/dist/compiled/react-server-dom-webpack/server.edge.js', check: '// PATCHED FOR __non_webpack_require__', patch: (content) => { if (!content.includes('__non_webpack_require__')) return content; return `// PATCHED FOR __non_webpack_require__ if (typeof __non_webpack_require__ === 'undefined') { global.__non_webpack_require__ = require; } ${content}`; } } ]; // Apply patches to each module for (const moduleInfo of modulesToPatch) { const modulePath = path.join(process.cwd(), moduleInfo.path); if (fs.existsSync(modulePath)) { try { // Backup the file if it's not already backed up const backupPath = `${modulePath}.original`; if (!fs.existsSync(backupPath)) { fs.copyFileSync(modulePath, backupPath); } // Read the current content const content = fs.readFileSync(modulePath, 'utf8'); // Check if already patched if (content.includes(moduleInfo.check)) { console.log(`āœ… Module ${moduleInfo.path} already patched`); continue; } // Apply the patch const patchedContent = moduleInfo.patch(content); fs.writeFileSync(modulePath, patchedContent); console.log(`āœ… Patched module ${moduleInfo.path}`); } catch (err) { console.error(`āš ļø Failed to patch ${moduleInfo.path}:`, err.message); } } } return true; }