Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

optimize-standalone.js 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * Script to optimize Next.js standalone output for production
  3. * Removes unnecessary files like jest-worker that are bundled with Next.js
  4. */
  5. const fs = require('fs');
  6. const path = require('path');
  7. console.log('🔧 Optimizing standalone output...');
  8. const standaloneDir = path.join(__dirname, '..', '.next', 'standalone');
  9. // Check if standalone directory exists
  10. if (!fs.existsSync(standaloneDir)) {
  11. console.error('❌ Standalone directory not found. Please run "next build" first.');
  12. process.exit(1);
  13. }
  14. // List of paths to remove (relative to standalone directory)
  15. const pathsToRemove = [
  16. // Remove jest-worker from Next.js compiled dependencies
  17. 'node_modules/.pnpm/next@*/node_modules/next/dist/compiled/jest-worker',
  18. // Remove jest-worker symlinks from terser-webpack-plugin
  19. 'node_modules/.pnpm/terser-webpack-plugin@*/node_modules/jest-worker',
  20. // Remove actual jest-worker packages (directories only, not symlinks)
  21. 'node_modules/.pnpm/jest-worker@*',
  22. ];
  23. // Function to safely remove a path
  24. function removePath(basePath, relativePath) {
  25. const fullPath = path.join(basePath, relativePath);
  26. // Handle wildcard patterns
  27. if (relativePath.includes('*')) {
  28. const parts = relativePath.split('/');
  29. let currentPath = basePath;
  30. for (let i = 0; i < parts.length; i++) {
  31. const part = parts[i];
  32. if (part.includes('*')) {
  33. // Find matching directories
  34. if (fs.existsSync(currentPath)) {
  35. const entries = fs.readdirSync(currentPath);
  36. // replace '*' with '.*'
  37. const regexPattern = part.replace(/\*/g, '.*');
  38. const regex = new RegExp(`^${regexPattern}$`);
  39. for (const entry of entries) {
  40. if (regex.test(entry)) {
  41. const remainingPath = parts.slice(i + 1).join('/');
  42. const matchedPath = path.join(currentPath, entry, remainingPath);
  43. try {
  44. // Use lstatSync to check if path exists (works for both files and symlinks)
  45. const stats = fs.lstatSync(matchedPath);
  46. if (stats.isSymbolicLink()) {
  47. // Remove symlink
  48. fs.unlinkSync(matchedPath);
  49. console.log(`✅ Removed symlink: ${path.relative(basePath, matchedPath)}`);
  50. } else {
  51. // Remove directory/file
  52. fs.rmSync(matchedPath, { recursive: true, force: true });
  53. console.log(`✅ Removed: ${path.relative(basePath, matchedPath)}`);
  54. }
  55. } catch (error) {
  56. // Silently ignore ENOENT (path not found) errors
  57. if (error.code !== 'ENOENT') {
  58. console.error(`❌ Failed to remove ${matchedPath}: ${error.message}`);
  59. }
  60. }
  61. }
  62. }
  63. }
  64. return;
  65. } else {
  66. currentPath = path.join(currentPath, part);
  67. }
  68. }
  69. } else {
  70. // Direct path removal
  71. if (fs.existsSync(fullPath)) {
  72. try {
  73. fs.rmSync(fullPath, { recursive: true, force: true });
  74. console.log(`✅ Removed: ${relativePath}`);
  75. } catch (error) {
  76. console.error(`❌ Failed to remove ${fullPath}: ${error.message}`);
  77. }
  78. }
  79. }
  80. }
  81. // Remove unnecessary paths
  82. console.log('🗑️ Removing unnecessary files...');
  83. for (const pathToRemove of pathsToRemove) {
  84. removePath(standaloneDir, pathToRemove);
  85. }
  86. // Calculate size reduction
  87. console.log('\n📊 Optimization complete!');
  88. // Optional: Display the size of remaining jest-related files (if any)
  89. const checkForJest = (dir) => {
  90. const jestFiles = [];
  91. function walk(currentPath) {
  92. if (!fs.existsSync(currentPath)) return;
  93. try {
  94. const entries = fs.readdirSync(currentPath);
  95. for (const entry of entries) {
  96. const fullPath = path.join(currentPath, entry);
  97. try {
  98. const stat = fs.lstatSync(fullPath); // Use lstatSync to handle symlinks
  99. if (stat.isDirectory() && !stat.isSymbolicLink()) {
  100. // Skip node_modules subdirectories to avoid deep traversal
  101. if (entry === 'node_modules' && currentPath !== standaloneDir) {
  102. continue;
  103. }
  104. walk(fullPath);
  105. } else if (stat.isFile() && entry.includes('jest')) {
  106. jestFiles.push(path.relative(standaloneDir, fullPath));
  107. }
  108. } catch (err) {
  109. // Skip files that can't be accessed
  110. continue;
  111. }
  112. }
  113. } catch (err) {
  114. // Skip directories that can't be read
  115. return;
  116. }
  117. }
  118. walk(dir);
  119. return jestFiles;
  120. };
  121. const remainingJestFiles = checkForJest(standaloneDir);
  122. if (remainingJestFiles.length > 0) {
  123. console.log('\n⚠️ Warning: Some jest-related files still remain:');
  124. remainingJestFiles.forEach(file => console.log(` - ${file}`));
  125. } else {
  126. console.log('\n✨ No jest-related files found in standalone output!');
  127. }