|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /**
- * Script to optimize Next.js standalone output for production
- * Removes unnecessary files like jest-worker that are bundled with Next.js
- */
-
- const fs = require('fs');
- const path = require('path');
-
- console.log('🔧 Optimizing standalone output...');
-
- const standaloneDir = path.join(__dirname, '..', '.next', 'standalone');
-
- // Check if standalone directory exists
- if (!fs.existsSync(standaloneDir)) {
- console.error('❌ Standalone directory not found. Please run "next build" first.');
- process.exit(1);
- }
-
- // List of paths to remove (relative to standalone directory)
- const pathsToRemove = [
- // Remove jest-worker from Next.js compiled dependencies
- 'node_modules/.pnpm/next@*/node_modules/next/dist/compiled/jest-worker',
- // Remove jest-worker symlinks from terser-webpack-plugin
- 'node_modules/.pnpm/terser-webpack-plugin@*/node_modules/jest-worker',
- // Remove actual jest-worker packages (directories only, not symlinks)
- 'node_modules/.pnpm/jest-worker@*',
- ];
-
- // Function to safely remove a path
- function removePath(basePath, relativePath) {
- const fullPath = path.join(basePath, relativePath);
-
- // Handle wildcard patterns
- if (relativePath.includes('*')) {
- const parts = relativePath.split('/');
- let currentPath = basePath;
-
- for (let i = 0; i < parts.length; i++) {
- const part = parts[i];
- if (part.includes('*')) {
- // Find matching directories
- if (fs.existsSync(currentPath)) {
- const entries = fs.readdirSync(currentPath);
-
- // replace '*' with '.*'
- const regexPattern = part.replace(/\*/g, '.*');
-
- const regex = new RegExp(`^${regexPattern}$`);
-
- for (const entry of entries) {
- if (regex.test(entry)) {
- const remainingPath = parts.slice(i + 1).join('/');
- const matchedPath = path.join(currentPath, entry, remainingPath);
-
- try {
- // Use lstatSync to check if path exists (works for both files and symlinks)
- const stats = fs.lstatSync(matchedPath);
-
- if (stats.isSymbolicLink()) {
- // Remove symlink
- fs.unlinkSync(matchedPath);
- console.log(`✅ Removed symlink: ${path.relative(basePath, matchedPath)}`);
- } else {
- // Remove directory/file
- fs.rmSync(matchedPath, { recursive: true, force: true });
- console.log(`✅ Removed: ${path.relative(basePath, matchedPath)}`);
- }
- } catch (error) {
- // Silently ignore ENOENT (path not found) errors
- if (error.code !== 'ENOENT') {
- console.error(`❌ Failed to remove ${matchedPath}: ${error.message}`);
- }
- }
- }
- }
- }
- return;
- } else {
- currentPath = path.join(currentPath, part);
- }
- }
- } else {
- // Direct path removal
- if (fs.existsSync(fullPath)) {
- try {
- fs.rmSync(fullPath, { recursive: true, force: true });
- console.log(`✅ Removed: ${relativePath}`);
- } catch (error) {
- console.error(`❌ Failed to remove ${fullPath}: ${error.message}`);
- }
- }
- }
- }
-
- // Remove unnecessary paths
- console.log('🗑️ Removing unnecessary files...');
- for (const pathToRemove of pathsToRemove) {
- removePath(standaloneDir, pathToRemove);
- }
-
- // Calculate size reduction
- console.log('\n📊 Optimization complete!');
-
- // Optional: Display the size of remaining jest-related files (if any)
- const checkForJest = (dir) => {
- const jestFiles = [];
-
- function walk(currentPath) {
- if (!fs.existsSync(currentPath)) return;
-
- try {
- const entries = fs.readdirSync(currentPath);
- for (const entry of entries) {
- const fullPath = path.join(currentPath, entry);
-
- try {
- const stat = fs.lstatSync(fullPath); // Use lstatSync to handle symlinks
-
- if (stat.isDirectory() && !stat.isSymbolicLink()) {
- // Skip node_modules subdirectories to avoid deep traversal
- if (entry === 'node_modules' && currentPath !== standaloneDir) {
- continue;
- }
- walk(fullPath);
- } else if (stat.isFile() && entry.includes('jest')) {
- jestFiles.push(path.relative(standaloneDir, fullPath));
- }
- } catch (err) {
- // Skip files that can't be accessed
- continue;
- }
- }
- } catch (err) {
- // Skip directories that can't be read
- return;
- }
- }
-
- walk(dir);
- return jestFiles;
- };
-
- const remainingJestFiles = checkForJest(standaloneDir);
- if (remainingJestFiles.length > 0) {
- console.log('\n⚠️ Warning: Some jest-related files still remain:');
- remainingJestFiles.forEach(file => console.log(` - ${file}`));
- } else {
- console.log('\n✨ No jest-related files found in standalone output!');
- }
|