UNPKG

@ordojs/dev-tools

Version:

Advanced developer tools for OrdoJS with component inspector, AST explorer, and performance profiling

285 lines (283 loc) 8.69 kB
import { EventEmitter } from 'events'; // src/bundle-analyzer/index.ts var BundleAnalyzer = class extends EventEmitter { analyses; isRunning; port; /** * Create a new BundleAnalyzer instance * * @param port - WebSocket port for bundle analyzer */ constructor(port = 24682) { super(); this.analyses = /* @__PURE__ */ new Map(); this.isRunning = false; this.port = port; } /** * Start the bundle analyzer */ async start() { if (this.isRunning) { console.warn("Bundle analyzer is already running"); return; } try { await this.startWebSocketServer(); this.isRunning = true; console.log(`Bundle analyzer started on port ${this.port}`); this.emit("started"); } catch (error) { console.error("Failed to start bundle analyzer:", error); this.emit("error", error); throw error; } } /** * Stop the bundle analyzer */ async stop() { if (!this.isRunning) { console.warn("Bundle analyzer is not running"); return; } try { await this.stopWebSocketServer(); this.isRunning = false; console.log("Bundle analyzer stopped"); this.emit("stopped"); } catch (error) { console.error("Failed to stop bundle analyzer:", error); this.emit("error", error); throw error; } } /** * Analyze a bundle file * * @param bundlePath - Path to the bundle file * @param bundleName - Name for the bundle analysis * @returns Bundle analysis result */ async analyzeBundle(bundlePath, bundleName) { try { const analysis = { size: 0, gzippedSize: 0, modules: [], chunks: [], dependencies: [], warnings: [], errors: [] }; await this.simulateBundleAnalysis(bundlePath, analysis); this.analyses.set(bundleName, analysis); this.emit("bundleAnalyzed", { bundleName, analysis }); return analysis; } catch (error) { console.error("Failed to analyze bundle:", error); this.emit("error", error); throw error; } } /** * Get bundle analysis by name * * @param bundleName - Bundle name * @returns Bundle analysis or undefined */ getAnalysis(bundleName) { return this.analyses.get(bundleName); } /** * Get all bundle analyses * * @returns Array of all bundle analyses */ getAllAnalyses() { return Array.from(this.analyses.values()); } /** * Compare two bundle analyses * * @param bundleName1 - First bundle name * @param bundleName2 - Second bundle name * @returns Comparison result */ compareBundles(bundleName1, bundleName2) { const analysis1 = this.analyses.get(bundleName1); const analysis2 = this.analyses.get(bundleName2); if (!analysis1 || !analysis2) { throw new Error("One or both bundle analyses not found"); } const sizeDifference = analysis2.size - analysis1.size; const sizeDifferencePercent = sizeDifference / analysis1.size * 100; const moduleCountDifference = analysis2.modules.length - analysis1.modules.length; const dependencyCountDifference = analysis2.dependencies.length - analysis1.dependencies.length; const modules1 = new Set(analysis1.modules.map((m) => m.name)); const modules2 = new Set(analysis2.modules.map((m) => m.name)); const newModules = analysis2.modules.filter((m) => !modules1.has(m.name)).map((m) => m.name); const removedModules = analysis1.modules.filter((m) => !modules2.has(m.name)).map((m) => m.name); const deps1 = new Set(analysis1.dependencies.map((d) => d.name)); const deps2 = new Set(analysis2.dependencies.map((d) => d.name)); const newDependencies = analysis2.dependencies.filter((d) => !deps1.has(d.name)).map((d) => d.name); const removedDependencies = analysis1.dependencies.filter((d) => !deps2.has(d.name)).map((d) => d.name); return { sizeDifference, sizeDifferencePercent, moduleCountDifference, dependencyCountDifference, newModules, removedModules, newDependencies, removedDependencies }; } /** * Get bundle optimization suggestions * * @param bundleName - Bundle name * @returns Optimization suggestions */ getOptimizationSuggestions(bundleName) { const analysis = this.analyses.get(bundleName); if (!analysis) { throw new Error("Bundle analysis not found"); } const moduleCounts = /* @__PURE__ */ new Map(); for (const module of analysis.modules) { moduleCounts.set(module.name, (moduleCounts.get(module.name) || 0) + 1); } const duplicateModules = Array.from(moduleCounts.entries()).filter(([_, count]) => count > 1).map(([name, _]) => name); const largeModules = analysis.modules.filter((module) => module.size > 100 * 1024).map((module) => module.name); const unusedDependencies = []; const codeSplittingOpportunities = analysis.modules.filter((module) => module.size > 50 * 1024 && !module.name.includes("vendor")).map((module) => module.name); const compressionOpportunities = analysis.modules.filter((module) => module.size > 10 * 1024).map((module) => module.name); return { duplicateModules, largeModules, unusedDependencies, codeSplittingOpportunities, compressionOpportunities }; } /** * Get bundle statistics * * @param bundleName - Bundle name * @returns Bundle statistics */ getBundleStats(bundleName) { const analysis = this.analyses.get(bundleName); if (!analysis) { throw new Error("Bundle analysis not found"); } const totalSize = analysis.size; const gzippedSize = analysis.gzippedSize; const moduleCount = analysis.modules.length; const dependencyCount = analysis.dependencies.length; const averageModuleSize = totalSize / moduleCount || 0; const largestModule = analysis.modules.length > 0 ? analysis.modules.reduce( (largest, current) => current.size > largest.size ? current : largest ) : null; const largestModuleSize = largestModule ? largestModule.size : 0; return { totalSize, gzippedSize, moduleCount, dependencyCount, averageModuleSize, largestModule: largestModule ? largestModule.name : "", largestModuleSize }; } /** * Clear all bundle analyses */ clearAnalyses() { this.analyses.clear(); this.emit("analysesCleared"); } /** * Simulate bundle analysis (placeholder implementation) * * @param bundlePath - Path to bundle file * @param analysis - Analysis object to populate */ async simulateBundleAnalysis(bundlePath, analysis) { const fs = await import('fs/promises'); try { const stats = await fs.stat(bundlePath); analysis.size = stats.size; analysis.gzippedSize = Math.round(analysis.size * 0.3); analysis.modules = [ { name: "main.js", size: Math.round(analysis.size * 0.6), dependencies: ["react", "react-dom"], exports: ["App", "main"], path: bundlePath }, { name: "vendor.js", size: Math.round(analysis.size * 0.4), dependencies: ["lodash", "moment"], exports: ["vendor"], path: bundlePath } ]; analysis.chunks = [ { name: "main", size: analysis.modules[0]?.size || 0, modules: ["main.js"], entry: true }, { name: "vendor", size: analysis.modules[1]?.size || 0, modules: ["vendor.js"], entry: false } ]; analysis.dependencies = [ { name: "react", version: "18.2.0", size: 100 * 1024, type: "production" }, { name: "react-dom", version: "18.2.0", size: 150 * 1024, type: "production" }, { name: "lodash", version: "4.17.21", size: 70 * 1024, type: "production" } ]; } catch (error) { analysis.errors.push(`Failed to analyze bundle: ${error instanceof Error ? error.message : String(error)}`); } } /** * Start WebSocket server for bundle analyzer communication */ async startWebSocketServer() { console.log("Starting WebSocket server for bundle analyzer..."); } /** * Stop WebSocket server */ async stopWebSocketServer() { console.log("Stopping WebSocket server for bundle analyzer..."); } }; export { BundleAnalyzer }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map