Skip to content

Commit 1c893ce

Browse files
Enhance build process with advanced memory optimization and fallback strategies
- Refactor build.js with comprehensive memory optimization techniques - Add multiple build attempts with progressive memory configurations - Implement extreme memory optimization in webpack config - Update GitHub Actions workflow with enhanced memory management - Remove .babelrc file handling and improve error logging - Add final static export fallback strategy for build process
1 parent 886fec2 commit 1c893ce

File tree

3 files changed

+137
-57
lines changed

3 files changed

+137
-57
lines changed

.github/workflows/publish.yml

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,39 +38,51 @@ jobs:
3838
3939
- name: Install dependencies 📦
4040
run: |
41-
# Clean install without development dependencies
42-
npm ci --omit=dev
43-
# Install only essential build dependencies
41+
# Clean install with only production dependencies
42+
npm ci --omit=dev --no-audit --no-fund
43+
# Install essential build tools
4444
npm install --no-save next react react-dom cross-env
4545
46-
- name: Optimize system for build
46+
- name: Extreme memory optimization
4747
run: |
48-
# Clear npm cache
48+
# Clear npm and system caches
4949
npm cache clean --force
50-
51-
# Clear system caches to free up memory
5250
sudo sysctl -w vm.drop_caches=3
5351
54-
# Create a large swap file (16GB)
55-
sudo fallocate -l 16G /swapfile
52+
# Create a massive swap file (24GB)
53+
sudo fallocate -l 24G /swapfile
5654
sudo chmod 600 /swapfile
5755
sudo mkswap /swapfile
5856
sudo swapon /swapfile
5957
58+
# Disable unnecessary services
59+
sudo service docker stop || true
60+
sudo service containerd stop || true
61+
6062
# Show available memory
6163
free -m
64+
65+
# Create temp directory for build artifacts
66+
mkdir -p /tmp/next-cache
67+
68+
# Set Node.js garbage collection settings
69+
export NODE_OPTIONS="--expose-gc --max-old-space-size=12288"
70+
node -e "console.log('Memory settings:', process.env.NODE_OPTIONS)"
6271
63-
- name: Build with custom script 🏗️
72+
- name: Build with extreme memory settings 🏗️
6473
run: |
65-
echo "Starting build process..."
66-
# Use Node.js with increased memory limit
67-
node --max-old-space-size=8192 build.js
74+
echo "Starting build process with extreme memory settings..."
75+
# Use Node.js with maximum memory limit
76+
NODE_OPTIONS="--max-old-space-size=12288" node build.js
6877
env:
6978
NEXT_TELEMETRY_DISABLED: 1
7079
GITHUB_PAGES: true
7180
NODE_ENV: production
72-
# Disable Next.js telemetry and other unnecessary features
81+
# Disable all telemetry and unnecessary features
7382
NEXT_RUNTIME: "nodejs"
83+
# Force memory optimization
84+
NEXT_MEMORY_OPTIMIZATION: true
85+
NEXT_MINIMIZE_USAGE: true
7486

7587
- name: Upload artifact 📡
7688
uses: actions/upload-pages-artifact@v3

build.js

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ function cleanDirectories() {
2121
}
2222
}
2323
}
24+
25+
// Remove any existing .babelrc file to avoid conflicts with Next.js font loader
26+
if (fs.existsSync('.babelrc')) {
27+
try {
28+
fs.unlinkSync('.babelrc');
29+
console.log('Removed existing .babelrc file');
30+
} catch (e) {
31+
console.warn('Could not remove .babelrc file:', e.message);
32+
}
33+
}
2434
}
2535

2636
// Set up environment
@@ -31,11 +41,9 @@ function setupEnvironment() {
3141
process.env.NODE_ENV = 'production';
3242
process.env.NEXT_TELEMETRY_DISABLED = '1';
3343

34-
// Create temporary .babelrc file for build optimization
35-
fs.writeFileSync('.babelrc', JSON.stringify({
36-
presets: ['next/babel'],
37-
plugins: []
38-
}, null, 2));
44+
// Set memory optimization flags
45+
process.env.NEXT_MEMORY_OPTIMIZATION = 'true';
46+
process.env.NEXT_MINIMIZE_USAGE = 'true';
3947

4048
if (process.env.GITHUB_PAGES) {
4149
console.log('Building for GitHub Pages...');
@@ -49,13 +57,13 @@ function executeCommand(command, options = {}) {
4957
execSync(command, {
5058
stdio: 'inherit',
5159
env: process.env,
52-
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
60+
maxBuffer: 1024 * 1024 * 20, // 20MB buffer
5361
...options
5462
});
5563
return true;
5664
} catch (error) {
5765
console.error(`Command failed: ${command}`);
58-
console.error(error.message);
66+
if (error.message) console.error(error.message);
5967
return false;
6068
}
6169
}
@@ -69,22 +77,22 @@ async function build() {
6977
// Step 2: Setup environment
7078
setupEnvironment();
7179

72-
// Step 3: Try the simplest build approach first
73-
console.log('Attempting build with minimal configuration...');
74-
const success = executeCommand('npx next build');
80+
// Step 3: Try with higher memory limit first
81+
console.log('Attempting build with increased memory limit...');
82+
const success = executeCommand('npx cross-env NODE_OPTIONS="--max-old-space-size=8192" next build');
7583

7684
if (success) {
7785
console.log('Build completed successfully!');
7886
} else {
79-
// Step 4: If that fails, try with explicit memory limits
80-
console.log('First build attempt failed, trying with explicit memory limits...');
81-
const fallbackSuccess = executeCommand('npx cross-env NODE_OPTIONS="--max-old-space-size=4096" next build');
87+
// Step 4: If that fails, try with a different memory configuration
88+
console.log('First build attempt failed, trying with alternative memory configuration...');
89+
const fallbackSuccess = executeCommand('npx cross-env NODE_OPTIONS="--max-old-space-size=6144 --max-semi-space-size=512 --optimize-for-size" next build');
8290

8391
if (fallbackSuccess) {
84-
console.log('Build with explicit memory limits completed successfully!');
92+
console.log('Build with alternative memory configuration completed successfully!');
8593
} else {
86-
// Step 5: If that also fails, try a more extreme approach
87-
console.log('Second build attempt failed, trying with extreme memory optimization...');
94+
// Step 5: If that also fails, try a more extreme approach with minimal config
95+
console.log('Second build attempt failed, trying with minimal configuration...');
8896

8997
// Create a temporary next.config.js with minimal settings
9098
const originalConfig = fs.existsSync('next.config.mjs') ?
@@ -93,22 +101,38 @@ async function build() {
93101
fs.writeFileSync('next.config.mjs.backup', originalConfig);
94102

95103
const minimalConfig = `
96-
/** @type {import('next').NextConfig} */
97-
const nextConfig = {
98-
output: "export",
99-
images: { unoptimized: true },
100-
distDir: '.next',
101-
typescript: { ignoreBuildErrors: true },
102-
eslint: { ignoreDuringBuilds: true },
103-
basePath: process.env.GITHUB_PAGES ? "/lucasbecker-dev" : "",
104-
}
105-
106-
export default nextConfig
107-
`;
104+
/** @type {import('next').NextConfig} */
105+
const nextConfig = {
106+
output: "export",
107+
images: { unoptimized: true },
108+
distDir: '.next',
109+
typescript: { ignoreBuildErrors: true },
110+
eslint: { ignoreDuringBuilds: true },
111+
basePath: process.env.GITHUB_PAGES ? "/lucasbecker-dev" : "",
112+
experimental: {
113+
// Keep only essential experimental features
114+
forceSwcTransforms: true
115+
},
116+
webpack: (config) => {
117+
// Extreme memory optimization
118+
config.optimization.minimize = true;
119+
config.cache = false;
120+
config.optimization.splitChunks = false;
121+
122+
// Disable source maps
123+
config.devtool = false;
124+
125+
return config;
126+
}
127+
}
128+
129+
export default nextConfig
130+
`;
108131

109132
fs.writeFileSync('next.config.mjs', minimalConfig);
110133

111-
const extremeSuccess = executeCommand('npx next build');
134+
// Try with minimal config and increased memory
135+
const extremeSuccess = executeCommand('npx cross-env NODE_OPTIONS="--max-old-space-size=10240" next build');
112136

113137
// Restore original config
114138
fs.writeFileSync('next.config.mjs', originalConfig);
@@ -117,20 +141,43 @@ async function build() {
117141
if (extremeSuccess) {
118142
console.log('Build with minimal configuration completed successfully!');
119143
} else {
120-
console.error('All build attempts failed.');
121-
process.exit(1);
144+
// Final attempt: Try with static export directly
145+
console.log('All previous attempts failed, trying direct static export...');
146+
147+
// Create an extremely minimal config
148+
const staticConfig = `
149+
/** @type {import('next').NextConfig} */
150+
const nextConfig = {
151+
output: "export",
152+
images: { unoptimized: true },
153+
distDir: '.next',
154+
typescript: { ignoreBuildErrors: true },
155+
eslint: { ignoreDuringBuilds: true },
156+
basePath: process.env.GITHUB_PAGES ? "/lucasbecker-dev" : "",
157+
// No experimental features, no webpack customization
158+
}
159+
160+
export default nextConfig
161+
`;
162+
fs.writeFileSync('next.config.mjs', staticConfig);
163+
164+
const finalSuccess = executeCommand('npx cross-env NODE_OPTIONS="--max-old-space-size=12288" next build');
165+
166+
// Restore original config
167+
fs.writeFileSync('next.config.mjs', originalConfig);
168+
169+
if (finalSuccess) {
170+
console.log('Final build attempt with static export completed successfully!');
171+
} else {
172+
console.error('All build attempts failed.');
173+
process.exit(1);
174+
}
122175
}
123176
}
124177
}
125178
} catch (error) {
126179
console.error('Build process failed:', error.message);
127180
process.exit(1);
128-
} finally {
129-
// Clean up temporary files
130-
console.log('Cleaning up temporary files...');
131-
if (fs.existsSync('.babelrc')) {
132-
fs.unlinkSync('.babelrc');
133-
}
134181
}
135182
}
136183

next.config.mjs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,40 @@ const nextConfig = {
1818
forceSwcTransforms: true,
1919
},
2020
webpack: (config) => {
21-
// Minimal webpack configuration to reduce memory usage
21+
// Optimize for memory usage
2222
config.optimization.minimize = true;
2323

24-
// Disable persistent caching
24+
// Disable persistent caching to reduce memory usage
2525
config.cache = false;
2626

27-
// Use a simpler chunking strategy
27+
// Limit parallel operations
28+
if (config.optimization.minimizer) {
29+
for (const minimizer of config.optimization.minimizer) {
30+
if (minimizer.constructor.name === 'TerserPlugin') {
31+
minimizer.options.parallel = 2;
32+
}
33+
}
34+
}
35+
36+
// Use a very simple chunking strategy
2837
config.optimization.splitChunks = {
2938
chunks: 'all',
30-
maxSize: 500000,
39+
maxInitialRequests: 3,
40+
maxAsyncRequests: 5,
41+
minSize: 20000,
42+
maxSize: 300000,
3143
cacheGroups: {
32-
default: false,
33-
vendors: false
44+
vendor: {
45+
test: /[\\/]node_modules[\\/]/,
46+
name: 'vendors',
47+
chunks: 'all',
48+
priority: 10
49+
},
50+
default: {
51+
minChunks: 2,
52+
priority: -10,
53+
reuseExistingChunk: true
54+
}
3455
}
3556
};
3657

0 commit comments

Comments
 (0)