DEV Community

Cover image for **Master Advanced Bundle Analysis: 5 Professional Techniques for JavaScript Optimization Performance**
Nithin Bharadwaj
Nithin Bharadwaj

Posted on

**Master Advanced Bundle Analysis: 5 Professional Techniques for JavaScript Optimization Performance**

As a best-selling author, I invite you to explore my books on Amazon. Don't forget to follow me on Medium and show your support. Thank you! Your support means the world!

Building efficient bundle analyzers requires a systematic approach that combines multiple analysis techniques to provide actionable insights for JavaScript application optimization. I have spent considerable time developing and refining these methods, and they have proven invaluable for identifying performance bottlenecks and optimization opportunities.

Bundle Composition Analysis

The foundation of effective bundle analysis lies in understanding how modules interconnect within your application. When I first started working with bundle analyzers, I realized that simply knowing the size of individual modules wasn't enough. The real value comes from mapping the relationships between modules and understanding how code splitting affects overall performance.

class ModuleCompositionAnalyzer {
  constructor(webpackStats) {
    this.stats = webpackStats;
    this.moduleGraph = new Map();
    this.chunkGraph = new Map();
    this.entryPoints = new Map();
  }

  analyzeComposition() {
    this.buildModuleGraph();
    this.analyzeChunkRelationships();
    this.identifyRedundantPaths();

    return {
      moduleCount: this.moduleGraph.size,
      chunkCount: this.chunkGraph.size,
      redundantModules: this.getRedundantModules(),
      entryPointAnalysis: this.analyzeEntryPoints()
    };
  }

  buildModuleGraph() {
    this.stats.modules.forEach(module => {
      const moduleInfo = {
        id: module.id,
        name: module.name,
        size: module.size,
        chunks: module.chunks,
        dependencies: [],
        dependents: [],
        depth: 0
      };

      // Extract dependencies from reasons
      if (module.reasons) {
        module.reasons.forEach(reason => {
          if (reason.moduleId && reason.moduleId !== module.id) {
            moduleInfo.dependencies.push(reason.moduleId);
          }
        });
      }

      this.moduleGraph.set(module.id, moduleInfo);
    });

    // Build reverse dependencies
    this.moduleGraph.forEach((module, moduleId) => {
      module.dependencies.forEach(depId => {
        const depModule = this.moduleGraph.get(depId);
        if (depModule) {
          depModule.dependents.push(moduleId);
        }
      });
    });

    this.calculateModuleDepths();
  }

  calculateModuleDepths() {
    const visited = new Set();
    const calculating = new Set();

    const calculateDepth = (moduleId) => {
      if (calculating.has(moduleId)) return 0; // Circular dependency
      if (visited.has(moduleId)) {
        return this.moduleGraph.get(moduleId).depth;
      }

      calculating.add(moduleId);
      const module = this.moduleGraph.get(moduleId);

      if (module.dependencies.length === 0) {
        module.depth = 0;
      } else {
        const maxDepth = Math.max(
          ...module.dependencies.map(depId => calculateDepth(depId))
        );
        module.depth = maxDepth + 1;
      }

      calculating.delete(moduleId);
      visited.add(moduleId);
      return module.depth;
    };

    this.moduleGraph.forEach((module, moduleId) => {
      if (!visited.has(moduleId)) {
        calculateDepth(moduleId);
      }
    });
  }

  analyzeChunkRelationships() {
    this.stats.chunks.forEach(chunk => {
      const chunkInfo = {
        id: chunk.id,
        names: chunk.names,
        size: chunk.size,
        modules: chunk.modules || [],
        parents: chunk.parents || [],
        children: chunk.children || [],
        isEntry: chunk.entry || false
      };

      this.chunkGraph.set(chunk.id, chunkInfo);
    });
  }

  identifyRedundantPaths() {
    const moduleChunkMap = new Map();

    // Map modules to chunks
    this.chunkGraph.forEach((chunk, chunkId) => {
      chunk.modules.forEach(moduleId => {
        if (!moduleChunkMap.has(moduleId)) {
          moduleChunkMap.set(moduleId, []);
        }
        moduleChunkMap.get(moduleId).push(chunkId);
      });
    });

    // Find modules that appear in multiple chunks
    this.redundantModules = [];
    moduleChunkMap.forEach((chunks, moduleId) => {
      if (chunks.length > 1) {
        const module = this.moduleGraph.get(moduleId);
        this.redundantModules.push({
          moduleId,
          moduleName: module ? module.name : 'Unknown',
          chunks,
          duplicatedSize: (chunks.length - 1) * (module ? module.size : 0)
        });
      }
    });
  }

  getRedundantModules() {
    return this.redundantModules.sort((a, b) => b.duplicatedSize - a.duplicatedSize);
  }

  analyzeEntryPoints() {
    const entryAnalysis = [];

    this.chunkGraph.forEach((chunk, chunkId) => {
      if (chunk.isEntry) {
        const analysis = this.analyzeEntryPoint(chunkId);
        entryAnalysis.push({
          chunkId,
          names: chunk.names,
          ...analysis
        });
      }
    });

    return entryAnalysis;
  }

  analyzeEntryPoint(entryChunkId) {
    const visited = new Set();
    const modulesByDepth = new Map();
    let totalSize = 0;

    const traverse = (chunkId) => {
      if (visited.has(chunkId)) return;
      visited.add(chunkId);

      const chunk = this.chunkGraph.get(chunkId);
      if (!chunk) return;

      chunk.modules.forEach(moduleId => {
        const module = this.moduleGraph.get(moduleId);
        if (module) {
          totalSize += module.size;

          if (!modulesByDepth.has(module.depth)) {
            modulesByDepth.set(module.depth, []);
          }
          modulesByDepth.get(module.depth).push(module);
        }
      });

      chunk.children.forEach(childId => traverse(childId));
    };

    traverse(entryChunkId);

    return {
      totalSize,
      moduleCount: visited.size,
      maxDepth: Math.max(...modulesByDepth.keys()),
      modulesByDepth: Object.fromEntries(modulesByDepth)
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Understanding module composition helps identify opportunities for better code splitting and reduces redundant code across different entry points. I have found that visualizing these relationships often reveals unexpected dependencies that can be optimized.

Memory Usage Profiling

Memory profiling during bundle execution provides critical insights into runtime performance characteristics. Traditional bundle analyzers focus on static file sizes, but memory usage patterns during execution often tell a different story about actual performance impact.

class MemoryProfiler {
  constructor(options = {}) {
    this.options = {
      sampleInterval: options.sampleInterval || 100,
      trackAllocations: options.trackAllocations || true,
      maxSamples: options.maxSamples || 1000,
      ...options
    };

    this.samples = [];
    this.allocations = new Map();
    this.leakCandidates = [];
    this.isProfileing = false;
  }

  startProfiling() {
    if (this.isProfileing) return;

    this.isProfileing = true;
    this.samples = [];
    this.startTime = performance.now();

    // Start memory sampling
    this.samplingInterval = setInterval(() => {
      this.takeSample();
    }, this.options.sampleInterval);

    // Track object allocations if supported
    if (this.options.trackAllocations && window.performance.measureUserAgentSpecificMemory) {
      this.trackObjectAllocations();
    }

    // Monitor garbage collection if available
    if (window.performance.measureUserAgentSpecificMemory) {
      this.monitorGarbageCollection();
    }
  }

  stopProfiling() {
    if (!this.isProfileing) return;

    this.isProfileing = false;
    clearInterval(this.samplingInterval);

    const endTime = performance.now();
    const duration = endTime - this.startTime;

    return this.generateReport(duration);
  }

  takeSample() {
    const sample = {
      timestamp: performance.now() - this.startTime,
      memory: this.getMemoryInfo(),
      domNodes: document.querySelectorAll('*').length,
      eventListeners: this.countEventListeners()
    };

    this.samples.push(sample);

    // Keep only the most recent samples
    if (this.samples.length > this.options.maxSamples) {
      this.samples.shift();
    }

    // Detect potential memory leaks
    this.detectMemoryLeaks(sample);
  }

  getMemoryInfo() {
    if (performance.memory) {
      return {
        used: performance.memory.usedJSHeapSize,
        total: performance.memory.totalJSHeapSize,
        limit: performance.memory.jsHeapSizeLimit
      };
    }

    // Fallback estimation
    return {
      used: this.estimateMemoryUsage(),
      total: 0,
      limit: 0
    };
  }

  estimateMemoryUsage() {
    // Rough estimation based on DOM size and stored data
    const domSize = document.documentElement.outerHTML.length;
    const storageSize = this.calculateStorageSize();

    return domSize + storageSize;
  }

  calculateStorageSize() {
    let size = 0;

    // Calculate localStorage size
    for (let key in localStorage) {
      if (localStorage.hasOwnProperty(key)) {
        size += localStorage[key].length + key.length;
      }
    }

    // Calculate sessionStorage size
    for (let key in sessionStorage) {
      if (sessionStorage.hasOwnProperty(key)) {
        size += sessionStorage[key].length + key.length;
      }
    }

    return size;
  }

  countEventListeners() {
    // This is a simplified count - actual implementation would need
    // to track listeners added during profiling
    return document.querySelectorAll('[onclick], [onload], [onchange]').length;
  }

  detectMemoryLeaks(currentSample) {
    if (this.samples.length < 10) return;

    const recentSamples = this.samples.slice(-10);
    const memoryGrowth = recentSamples.map((sample, index) => {
      if (index === 0) return 0;
      return sample.memory.used - recentSamples[index - 1].memory.used;
    });

    const averageGrowth = memoryGrowth.reduce((sum, growth) => sum + growth, 0) / memoryGrowth.length;

    // Detect consistent memory growth
    if (averageGrowth > 1024 * 100) { // 100KB average growth
      const growthRate = averageGrowth / this.options.sampleInterval;

      this.leakCandidates.push({
        timestamp: currentSample.timestamp,
        growthRate,
        memoryUsed: currentSample.memory.used,
        suspectedCause: this.identifyLeakCause(currentSample)
      });
    }
  }

  identifyLeakCause(sample) {
    const causes = [];

    // Check DOM node growth
    if (this.samples.length > 1) {
      const previousSample = this.samples[this.samples.length - 2];
      const domGrowth = sample.domNodes - previousSample.domNodes;

      if (domGrowth > 10) {
        causes.push(`DOM nodes increased by ${domGrowth}`);
      }
    }

    // Check event listener growth
    const listenerGrowth = sample.eventListeners - (this.samples[0]?.eventListeners || 0);
    if (listenerGrowth > 5) {
      causes.push(`Event listeners increased by ${listenerGrowth}`);
    }

    return causes.length > 0 ? causes.join(', ') : 'Unknown cause';
  }

  trackObjectAllocations() {
    // Modern browsers might support allocation tracking
    if (typeof FinalizationRegistry !== 'undefined') {
      this.allocationRegistry = new FinalizationRegistry((heldValue) => {
        this.recordDeallocation(heldValue);
      });
    }
  }

  recordAllocation(object, metadata) {
    if (this.allocationRegistry) {
      const allocationInfo = {
        timestamp: performance.now() - this.startTime,
        size: this.estimateObjectSize(object),
        type: metadata.type || 'unknown',
        stackTrace: this.captureStackTrace()
      };

      this.allocations.set(object, allocationInfo);
      this.allocationRegistry.register(object, allocationInfo);
    }
  }

  recordDeallocation(allocationInfo) {
    // Track when objects are garbage collected
    allocationInfo.deallocatedAt = performance.now() - this.startTime;
  }

  estimateObjectSize(obj) {
    if (obj === null || obj === undefined) return 0;

    const type = typeof obj;
    switch (type) {
      case 'boolean': return 4;
      case 'number': return 8;
      case 'string': return obj.length * 2;
      case 'object':
        if (Array.isArray(obj)) {
          return obj.reduce((size, item) => size + this.estimateObjectSize(item), 0);
        }

        let size = 0;
        for (const key in obj) {
          if (obj.hasOwnProperty(key)) {
            size += key.length * 2 + this.estimateObjectSize(obj[key]);
          }
        }
        return size;
      default:
        return 0;
    }
  }

  captureStackTrace() {
    const error = new Error();
    return error.stack ? error.stack.split('\n').slice(2, 7) : [];
  }

  monitorGarbageCollection() {
    // This would integrate with performance observers if available
    if (window.PerformanceObserver) {
      try {
        const observer = new PerformanceObserver((list) => {
          const entries = list.getEntries();
          entries.forEach(entry => {
            if (entry.entryType === 'measure' && entry.name.includes('gc')) {
              this.recordGCEvent(entry);
            }
          });
        });

        observer.observe({ entryTypes: ['measure'] });
      } catch (error) {
        console.warn('GC monitoring not available');
      }
    }
  }

  recordGCEvent(entry) {
    const gcEvent = {
      timestamp: entry.startTime,
      duration: entry.duration,
      type: entry.name
    };

    if (!this.gcEvents) {
      this.gcEvents = [];
    }

    this.gcEvents.push(gcEvent);
  }

  generateReport(duration) {
    const report = {
      duration,
      sampleCount: this.samples.length,
      memoryAnalysis: this.analyzeMemoryUsage(),
      leakDetection: this.analyzeLeaks(),
      allocationAnalysis: this.analyzeAllocations(),
      recommendations: this.generateRecommendations()
    };

    return report;
  }

  analyzeMemoryUsage() {
    if (this.samples.length === 0) return null;

    const memoryValues = this.samples.map(s => s.memory.used);
    const minMemory = Math.min(...memoryValues);
    const maxMemory = Math.max(...memoryValues);
    const avgMemory = memoryValues.reduce((sum, val) => sum + val, 0) / memoryValues.length;

    // Calculate memory growth trend
    const firstQuarter = memoryValues.slice(0, Math.floor(memoryValues.length / 4));
    const lastQuarter = memoryValues.slice(-Math.floor(memoryValues.length / 4));

    const firstQuarterAvg = firstQuarter.reduce((sum, val) => sum + val, 0) / firstQuarter.length;
    const lastQuarterAvg = lastQuarter.reduce((sum, val) => sum + val, 0) / lastQuarter.length;

    const growthTrend = lastQuarterAvg - firstQuarterAvg;

    return {
      min: this.formatBytes(minMemory),
      max: this.formatBytes(maxMemory),
      average: this.formatBytes(avgMemory),
      growth: this.formatBytes(growthTrend),
      growthRate: (growthTrend / (this.samples[this.samples.length - 1].timestamp - this.samples[0].timestamp)) * 1000
    };
  }

  analyzeLeaks() {
    return {
      potentialLeaks: this.leakCandidates.length,
      totalGrowth: this.formatBytes(
        this.leakCandidates.reduce((sum, leak) => sum + leak.growthRate * 1000, 0)
      ),
      leakDetails: this.leakCandidates.map(leak => ({
        timestamp: Math.round(leak.timestamp),
        growthRate: this.formatBytes(leak.growthRate * 1000) + '/s',
        memoryUsed: this.formatBytes(leak.memoryUsed),
        cause: leak.suspectedCause
      }))
    };
  }

  analyzeAllocations() {
    if (this.allocations.size === 0) return null;

    const allocationsArray = Array.from(this.allocations.values());
    const totalAllocated = allocationsArray.reduce((sum, alloc) => sum + alloc.size, 0);
    const deallocated = allocationsArray.filter(alloc => alloc.deallocatedAt).length;

    return {
      totalAllocations: allocationsArray.length,
      totalSize: this.formatBytes(totalAllocated),
      deallocated,
      stillAllocated: allocationsArray.length - deallocated,
      allocationRate: allocationsArray.length / (this.samples[this.samples.length - 1].timestamp / 1000)
    };
  }

  generateRecommendations() {
    const recommendations = [];

    if (this.leakCandidates.length > 0) {
      recommendations.push('Potential memory leaks detected. Review event listener cleanup and object references.');
    }

    const memoryAnalysis = this.analyzeMemoryUsage();
    if (memoryAnalysis && memoryAnalysis.growthRate > 1024) {
      recommendations.push('High memory growth rate detected. Consider implementing object pooling or reducing object creation.');
    }

    if (this.samples.some(s => s.domNodes > 1000)) {
      recommendations.push('High DOM node count detected. Consider virtual scrolling or lazy loading for large lists.');
    }

    return recommendations;
  }

  formatBytes(bytes) {
    const units = ['B', 'KB', 'MB', 'GB'];
    let size = bytes;
    let unitIndex = 0;

    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }

    return `${size.toFixed(2)} ${units[unitIndex]}`;
  }
}
Enter fullscreen mode Exit fullscreen mode

Memory profiling has been instrumental in identifying performance issues that static analysis cannot detect. The combination of heap monitoring and allocation tracking provides comprehensive insights into runtime behavior.

Tree Shaking Verification

Effective tree shaking verification goes beyond checking if unused exports are removed. Modern applications often have complex side effects and dynamic imports that can interfere with dead code elimination. I have developed techniques to systematically identify these issues.


javascript
class TreeShakingAnalyzer {
  constructor(sourceCode, options = {}) {
    this.sourceCode = sourceCode;
    this.options = {
      checkSideEffects: options.checkSideEffects !== false,
      analyzeDeepImports: options.analyzeDeepImports !== false,
      trackDynamicImports: options.trackDynamicImports !== false,
      ...options
    };

    this.exportMap = new Map();
    this.importMap = new Map();
    this.sideEffects = [];
    this.unusedExports = [];
    this.problematicPatterns = [];
  }

  analyze() {
    this.parseExports();
    this.parseImports();
    this.identifyUsedExports();
    this.detectSideEffects();
    this.findProblematicPatterns();

    return this.generateShakingReport();
  }

  parseExports() {
    const exportPatterns = [
      /export\s+(?:default\s+)?(?:function|class|const|let|var)\s+(\w+)/g,
      /export\s*\{\s*([^}]+)\s*\}/g,
      /export\s+\*\s+from\s+['"]([^'"]+)['"]/g,
      /export\s*\{\s*([^}]+)\s*\}\s*from\s+['"]([^'"]+)['"]/g
    ];

    exportPatterns.forEach(pattern => {
      let match;
      while ((match = pattern.exec(this.sourceCode)) !== null) {
        this.processExportMatch(match, pattern);
      }
    });
  }

  processExportMatch(match, pattern) {
    const fullMatch = match[0];
    const location = this.getLineNumber(match.index);

    if (fullMatch.includes('export *')) {
      // Re-export all
      this.exportMap.set(`*:${match[1]}`, {
        type: 'reexport-all',
        source: match[1],
        location,
        used: false
      });
    } else if (fullMatch.includes('from')) {
      // Named re-export
      const exports = this.parseExportList(match[1]);
      const source = match[2];

      exports.forEach(exp => {
        this.exportMap.set(exp.name, {
          type: 'reexport',
          source,
          alias: exp.alias,
          location,
          used: false
        });
      });
    } else if (match[1].includes(',')) {
      // Multiple named exports
      const exports = this.parseExportList(match[1]);
      exports.forEach(exp => {
        this.exportMap.set(exp.name, {
          type: 'named',
          alias: exp.alias,
          location,
          used: false,
          definition: this.findDefinition(exp.name)
        });
      });
    } else {
      // Single export
      this.exportMap.set(match[1], {
        type: fullMatch.includes('default') ? 'default' : 'named',
        location,
        used: false,
        definition: this.findDefinition(match[1])
      });
    }
  }

  parseExportList(exportString) {
    return exportString.split(',').map(item => {
      const trimmed = item.trim();
      const asIndex = trimmed.indexOf(' as ');

      if (asIndex !== -1) {
        return {
          name: trimmed.substring(0, asIndex).trim(),
          alias: trimmed.substring(asIndex + 4).trim()
        };
      }

      return { name: trimmed, alias: null };
    });
  }

  parseImports() {
    const importPatterns = [
      /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,
      /import\s*\{\s*([^}]+)\s*\}\s*from\s+['"]([^'"]+)['"]/g,
      /import\s*\*\s*as\s*(\w+)\s*from\s+['"]([^'"]+)['"]/g,
      /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g
    ];

    importPatterns.forEach(pattern => {
      let match;
      while ((match = pattern.exec(this.sourceCode)) !== null) {
        this.processImportMatch(match, pattern);
      }
    });
  }

  processImportMatch(match, pattern) {
    const fullMatch = match[0];
    const location = this.getLineNumber(match.index);

    if (fullMatch.includes('import(')) {
      // Dynamic import
      this.importMap.set(`dynamic:${match[1]}`, {
        type: 'dynamic',
        source: match[1],
        location,
        used: true // Dynamic imports are always considered used
      });
    } else if (fullMatch.includes('* as')) {
      // Namespace import
      this.importMap.set(match[1], {
        type: 'namespace',
        source: match[2],
        location,
        used: this.isIdentifierUsed(match[1])
      });
    } else if (match[1] && match[1].includes(',')) {
      // Named imports
      const imports = this.parseImportList(match[1]);
      const source = match[2];

      imports.forEach(imp => {
        this.importMap.set(imp.local, {
          type: 'named',
          source,
          imported: imp.imported,
          location,
          used: this.isIdentifierUsed(imp.local)
        });
      });
    } else {
      // Default import
      this.importMap.set(match[1], {
        type: 'default',
        source: match[2],
        location,
        used: this.isIdentifierUsed(match[1])
      });
    }
  }

  parseImportList(importString) {
    return importString.split(',').map(item => {
      const trimmed = item.trim();
      const asIndex = trimmed.indexOf(' as ');

      if (asIndex !== -1) {
        return {
          imported: trimmed.substring(0, asIndex).trim(),
          local: trimmed.substring(asIndex + 4).trim()
        };
      }

      return { imported: trimmed, local: trimmed };
    });
  }

  identifyUsedExports() {
    // Mark exports as used based on imports in other modules
    this.importMap.forEach((importInfo, importName) => {
      if (importInfo.used && importInfo.type !== 'dynamic') {
        const exportKey = importInfo.imported || importName;
        if (this.exportMap.has(exportKey)) {
          this.exportMap.get(exportKey).used = true;
        }
      }
    });

    // Check for usage in the same module
    this.exportMap.forEach((exportInfo, exportName) => {
      if (!exportInfo.used) {
        exportInfo.used = this.isIdentifierUsed(exportName);
      }
    });
  }

  isIdentifierUsed(identifier) {
    // Simple usage detection - could be more sophisticated
    const usagePattern = new RegExp(`\\b${identifier}\\b`, 'g');
    const matches = this.sourceCode.match(usagePattern);

    // If found more than once (definition + usage), consider it used
    return matches && matches.length > 1;
  }

  detectSideEffects() {
    if (!this.options.checkSideEffects) return;

    const sideEffectPatterns = [
      {
        pattern: /console\.(log|warn|error|info)/g,
        type: 'console',
        severity: 'low'
      },
      {
        pattern: /window\.\w+\s*=/g,
        type: 'global-assignment',
        severity: 'high'
      },
      {
        pattern: /document\.(getElementById|querySelector|addEventListener)/g,
        type: 'dom-interaction',
        severity: 'medium'
      },
      {
        pattern: /localStorage\.|sessionStorage\./g,
        type: 'storage-access',
        severity: 'medium'
      },
      {
        pattern: /fetch\(|XMLHttpRequest/g,
        type: 'network-request',
        severity: 'high'
      },
      {
        pattern: /setInterval\(|setTimeout\(/g,
        type: 'timer',
        severity: 'medium'
      }
    ];

    sideEffectPatterns.forEach(({ pattern, type, severity }) => {
      let match;
      while ((match = pattern.exec(this.sourceCode)) !== null) {
        this.sideEffects.push({
          type,
          severity,
          location: this.getLineNumber(match.index),
          code: this.getCodeContext(match.index),
          impact: this.assessSideEffectImpact(type, match[0])
        });
      }
    });
  }

  assessSideEffectImpact(type, code) {
    switch (type) {
      case 'global-assignment':
        return 'Prevents tree shaking of entire module';
      case 'network-request':
        return 'May cause unwanted network activity';
      case 'dom-interaction':
        return 'May cause DOM manipulation side effects';
      case 'timer':
        return 'May create persistent timers';
      default:
        return 'May have runtime side effects';
    }
  }

  findProblematicPatterns() {
    const patterns = [
      {
        name: 'default-export-object',
        pattern: /export\s+default\s*\{[\s\S]*?\}/g,
        issue: 'Default object exports prevent individual property tree shaking'
      },
      {
        name: 'destructuring-reexport',
        pattern: /export\s*\{\s*\.\.\.(\w+)\s*\}/g,
        issue: 'Spread operator in exports prevents static analysis'
      },
      {
        name: 'conditional-export',
        pattern: /if\s*\([\s\S]*?\)\s*\{[\s\S]*?export/g,
        issue: 'Conditional exports prevent tree shaking'
      },
      {
        name: 'computed-property-export',
        pattern: /export\s*\{\s*\[[\s\S]*?\]\s*:/g,
        issue: 'Computed property names prevent static analysis'
      }
    ];

    patterns.forEach(({ name, pattern, issue }) => {
---
📘 **Checkout my [latest ebook](https://youtu.be/WpR6F4ky4uM) for free on my channel!**  
Be sure to **like**, **share**, **comment**, and **subscribe** to the channel!

---
## 101 Books

**101 Books** is an AI-driven publishing company co-founded by author **Aarav Joshi**. By leveraging advanced AI technology, we keep our publishing costs incredibly low—some books are priced as low as **$4**—making quality knowledge accessible to everyone.

Check out our book **[Golang Clean Code](https://www.amazon.com/dp/B0DQQF9K3Z)** available on Amazon. 

Stay tuned for updates and exciting news. When shopping for books, search for **Aarav Joshi** to find more of our titles. Use the provided link to enjoy **special discounts**!

## Our Creations

Be sure to check out our creations:

**[Investor Central](https://www.investorcentral.co.uk/)** | **[Investor Central Spanish](https://spanish.investorcentral.co.uk/)** | **[Investor Central German](https://german.investorcentral.co.uk/)** | **[Smart Living](https://smartliving.investorcentral.co.uk/)** | **[Epochs & Echoes](https://epochsandechoes.com/)** | **[Puzzling Mysteries](https://www.puzzlingmysteries.com/)** | **[Hindutva](http://hindutva.epochsandechoes.com/)** | **[Elite Dev](https://elitedev.in/)** | **[JS Schools](https://jsschools.com/)**

---

### We are on Medium

**[Tech Koala Insights](https://techkoalainsights.com/)** | **[Epochs & Echoes World](https://world.epochsandechoes.com/)** | **[Investor Central Medium](https://medium.investorcentral.co.uk/)** | **[Puzzling Mysteries Medium](https://medium.com/puzzling-mysteries)** | **[Science & Epochs Medium](https://science.epochsandechoes.com/)** | **[Modern Hindutva](https://modernhindutva.substack.com/)**

Enter fullscreen mode Exit fullscreen mode

Top comments (0)