#!/usr/bin/env node /** * This script fixes the "Maximum call stack size exceeded" error * that occurs during Next.js build on Vercel, specifically in the * micromatch module used by Next.js. */ const fs = require('fs'); const path = require('path'); // Only run this fix in Vercel environment if (process.env.VERCEL !== '1') { console.log('Not in Vercel environment, skipping fix'); process.exit(0); } console.log('Applying critical fixes for Vercel build...'); // Set Node.js options to increase memory limit process.env.NODE_OPTIONS = process.env.NODE_OPTIONS || ''; if (!process.env.NODE_OPTIONS.includes('--max-old-space-size')) { process.env.NODE_OPTIONS += ' --max-old-space-size=3072'; console.log(`Increased Node.js memory limit: ${process.env.NODE_OPTIONS}`); } // Modify next.config.js to disable problematic optimizations try { const nextConfigPath = path.join(process.cwd(), 'next.config.js'); if (fs.existsSync(nextConfigPath)) { // Create a backup if it doesn't exist const nextConfigBackup = `${nextConfigPath}.original`; if (!fs.existsSync(nextConfigBackup)) { fs.copyFileSync(nextConfigPath, nextConfigBackup); console.log(`Created backup of next.config.js at ${nextConfigBackup}`); } // Read the current config let nextConfig = fs.readFileSync(nextConfigPath, 'utf8'); // Simplify complex regexes in the config nextConfig = nextConfig.replace( /source: '\/\(.*\)\\+\.\((?:[^()]*\|)+[^()]*\)\$'/g, 'source: \'/(.*)\'' ); // Disable problematic experimental features if (nextConfig.includes('experimental:')) { console.log('Disabling problematic experimental features in next.config.js...'); // Disable optimizeCss experimental feature if (nextConfig.includes('optimizeCss:')) { nextConfig = nextConfig.replace(/optimizeCss:\s*true/, 'optimizeCss: false'); } // Disable memoryBasedWorkersCount if (nextConfig.includes('memoryBasedWorkersCount:')) { nextConfig = nextConfig.replace(/memoryBasedWorkersCount:\s*true/, 'memoryBasedWorkersCount: false'); } } // Simplify webpack configuration if it exists if (nextConfig.includes('webpack:')) { console.log('Simplifying webpack configuration in next.config.js...'); // Replace the complex webpack config with a simpler one nextConfig = nextConfig.replace( /webpack:\s*\(config,\s*\{[^}]*\}\)\s*=>\s*\{[\s\S]*?(?=return config|config\.resolve)[\s\S]*?return config;?\s*\}/, `webpack: (config) => { // Simplified webpack config to avoid call stack issues return config; }` ); } // Write the simplified config fs.writeFileSync(nextConfigPath, nextConfig); console.log('Successfully simplified next.config.js'); } } catch (err) { console.error('Warning: Could not modify next.config.js:', err.message); } // Create a temporary .env.production.local file to disable certain features try { const envPath = path.join(process.cwd(), '.env.production.local'); // Add environment variables to disable problematic features const envContent = ` # Temporary fixes to prevent Maximum call stack size exceeded NEXT_DISABLE_SOURCEMAPS=true NEXT_DISABLE_OPTIMIZATION=1 NEXT_TELEMETRY_DISABLED=1 NODE_ENV=production `; fs.writeFileSync(envPath, envContent, { flag: 'a' }); console.log('Added environment variables to disable problematic features'); } catch (err) { console.error('Warning: Could not create .env.production.local file:', err.message); } // Override the micromatch module if it exists try { const micromatchPath = path.join( process.cwd(), 'node_modules/next/dist/compiled/micromatch/index.js' ); if (fs.existsSync(micromatchPath)) { // Create a backup if it doesn't exist const micromatchBackup = `${micromatchPath}.original`; if (!fs.existsSync(micromatchBackup)) { fs.copyFileSync(micromatchPath, micromatchBackup); console.log(`Created backup of micromatch at ${micromatchBackup}`); } // Read the file content const content = fs.readFileSync(micromatchPath, 'utf8'); // Skip if already patched if (content.includes('// PATCHED TO PREVENT CALL STACK OVERFLOW')) { console.log('Micromatch module already patched'); } else { // Patch known problematic functions const patchedContent = content // Add patched flag .replace('!function(', '// PATCHED TO PREVENT CALL STACK OVERFLOW\n!function(') // Patch the create function to prevent deep recursion .replace( /(function create\(glob, options\) \{)/, `$1 // Handle recursion depth if (!options) options = {}; options._depth = (options._depth || 0) + 1; if (options._depth > 50) { return { pattern: glob, regex: new RegExp('.*') }; }` ) // Patch the makeRe function .replace( /(makeRe: function\(string, options\) \{)/, `$1 // Prevent excessive pattern complexity if (string && string.length > 100) { return /.*/; }` ); // Write the patched file fs.writeFileSync(micromatchPath, patchedContent); console.log('Successfully patched micromatch to prevent stack overflow'); } } } catch (err) { console.error('Warning: Could not patch micromatch module:', err.message); } console.log('Vercel build fixes completed successfully!');