#!/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;
}