react-insight
Version:
A powerful React performance monitoring component that helps you identify and fix performance issues in your React applications
1 lines • 21.7 kB
Source Map (JSON)
{"version":3,"sources":["../src/components/PerformanceMonitor.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport \"./PerformanceMonitor.css\";\n\n/***************************\n * GLOBAL INSTRUMENTATION *\n ***************************/\n\n// Avoid double‑patching when Hot Reload remounts the component\nif (!(window as any).__PM_PATCHED__) {\n (window as any).__PM_PATCHED__ = true;\n\n /* ---------- Timers ---------- */\n let timeoutCount = 0;\n let intervalCount = 0;\n\n const _setTimeout = window.setTimeout;\n const _clearTimeout = window.clearTimeout;\n const _setInterval = window.setInterval;\n const _clearInterval = window.clearInterval;\n\n window.setTimeout = (...args) => {\n timeoutCount++;\n return _setTimeout(...args);\n };\n window.clearTimeout = (id) => {\n if (timeoutCount > 0) timeoutCount--;\n _clearTimeout(id);\n };\n\n window.setInterval = (...args) => {\n intervalCount++;\n return _setInterval(...args);\n };\n window.clearInterval = (id) => {\n if (intervalCount > 0) intervalCount--;\n _clearInterval(id);\n };\n\n (window as any).__PM_GET_ACTIVE_TIMERS__ = () => timeoutCount + intervalCount;\n\n /* ---------- Event listeners ---------- */\n let listenerCount = 0;\n const _add = EventTarget.prototype.addEventListener;\n const _remove = EventTarget.prototype.removeEventListener;\n\n EventTarget.prototype.addEventListener = function (...args) {\n listenerCount++;\n // @ts-ignore\n return _add.apply(this, args);\n };\n EventTarget.prototype.removeEventListener = function (...args) {\n if (listenerCount > 0) listenerCount--;\n // @ts-ignore\n return _remove.apply(this, args);\n };\n\n (window as any).__PM_GET_EVENT_LISTENERS__ = () => listenerCount;\n\n /* ---------- Pending fetch ---------- */\n let pendingFetches = 0;\n const _fetch : any= window.fetch.bind(window);\n\n window.fetch = (...args) => {\n pendingFetches++;\n return _fetch(...args)?.finally(() => {\n if (pendingFetches > 0) pendingFetches--;\n });\n };\n\n (window as any).__PM_GET_PENDING_REQUESTS__ = () => pendingFetches;\n}\n\n/***************************\n * TYPES\n ***************************/\n\ninterface PerformanceData {\n score: number;\n domSize: {\n totalElements: number;\n depth: number;\n bodyElements: number;\n headElements: number;\n };\n imagesAlt: {\n total: number;\n withoutAlt: number;\n elements: Element[];\n };\n layoutShift: {\n value: number;\n elements: Element[];\n };\n memoryUsage: {\n usedMB: number;\n totalMB: number;\n limitMB: number;\n } | null;\n activeTimers: number;\n eventListeners: { totalListeners: number };\n interactionDelay: number;\n pendingRequests: { total: number; requests: PerformanceEntry[] };\n}\n/************ CLS accumulator ************/\nlet clsValue = 0;\nlet clsEntries: any[] = [];\n\nif (!(\"__PM_CLS_OBSERVER__\" in window) && \"PerformanceObserver\" in window) {\n const clsObserver = new PerformanceObserver(list => {\n list.getEntries().forEach(e => {\n const entry = e as any;\n if (!entry.hadRecentInput && entry.value > 0) {\n clsValue += entry.value; // <- accumulate magnitude\n clsEntries.push(entry);\n }\n });\n });\n\n clsObserver.observe({ type: \"layout-shift\", buffered: true });\n (window as any).__PM_CLS_OBSERVER__ = clsObserver;\n}\n\n/***************************\n * METRIC HELPERS\n ***************************/\n\nconst checkImagesAlt = () => {\n const imgs = Array.from(document.querySelectorAll<HTMLImageElement>(\"img\"));\n const without = imgs.filter((img) => !(img.getAttribute(\"alt\") ?? \"\").trim());\n return { total: imgs.length, withoutAlt: without.length, elements: without };\n};\n\nconst getMaxDepth = (el: Element | null, depth = 0): number => {\n if (!el || el.children.length === 0) return depth;\n return Math.max(...Array.from(el.children).map((c) => getMaxDepth(c, depth + 1)));\n};\n\nconst checkDOMSize = () => {\n const bodyElements = document.body.getElementsByTagName(\"*\").length;\n const headElements = document.head.getElementsByTagName(\"*\").length;\n return {\n totalElements: bodyElements + headElements,\n depth: getMaxDepth(document.body),\n bodyElements,\n headElements,\n };\n};\n\n\n/************ helper ************/\nconst checkLayoutShift = () => {\n // Grab the nodes for developer hints\n const nodes = new Set<Element>();\n clsEntries.forEach(e => e.sources?.forEach((s:any) => s.node && nodes.add(s.node!)));\n // Return both the cumulative value and the offending nodes\n return { value: +clsValue.toFixed(3), elements: Array.from(nodes) };\n};\n\nconst checkMemoryUsage = () => {\n if ((performance as any).memory) {\n const { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit } =\n (performance as any).memory;\n\n return {\n usedMB: +(usedJSHeapSize / 1048576).toFixed(2),\n totalMB: +(totalJSHeapSize / 1048576).toFixed(2),\n limitMB: +(jsHeapSizeLimit / 1048576).toFixed(2)\n };\n }\n return null; // API not available\n};\nconst measureInteractionDelay = () =>\n new Promise<number>((resolve) => {\n const start = performance.now();\n requestAnimationFrame(() => resolve(performance.now() - start));\n });\n\nconst checkPerformance = async (): Promise<PerformanceData> => {\n const domSize = checkDOMSize();\n const imagesAlt = checkImagesAlt();\n const layoutShift = checkLayoutShift();\n const memoryUsage = checkMemoryUsage();\n const activeTimers = (window as any).__PM_GET_ACTIVE_TIMERS__?.() ?? 0;\n const totalListeners = (window as any).__PM_GET_EVENT_LISTENERS__?.() ?? 0;\n const pending = (window as any).__PM_GET_PENDING_REQUESTS__?.() ?? 0;\n const interactionDelay = await measureInteractionDelay();\n\n /* ---------- score ---------- */\n let score = 100;\n\n if (domSize.totalElements > 3000) score -= 50;\n else if (domSize.totalElements > 2000) score -= 35;\n else if (domSize.totalElements > 1000) score -= 25;\n\n if (domSize.depth > 32) score -= Math.min(10, domSize.depth - 10);\n if (imagesAlt.withoutAlt) score -= Math.min(15, imagesAlt.withoutAlt * 2);\n \n if (layoutShift.value > 0.1) { // 0.1 is Google’s “good” threshold\n score -= Math.min(10, layoutShift.value * 100); // 0.25 CLS ⇒ –10 pts\n }\n if (memoryUsage && memoryUsage.limitMB && memoryUsage.usedMB / memoryUsage.limitMB > 0.3) {\n score -= Math.min(15, ((memoryUsage.usedMB / memoryUsage.limitMB) - 0.3) * 50);\n }\n\n if (activeTimers > 10) score -= Math.min(10, activeTimers - 10);\n if (totalListeners > 500) score -= Math.min(15, (totalListeners - 500) / 50);\n if (interactionDelay > 100) score -= Math.min(20, (interactionDelay - 100) / 10);\n if (pending > 5) score -= Math.min(10, pending - 5);\n\n if (score < 0) score = 0;\n\n return {\n score,\n domSize,\n imagesAlt,\n layoutShift,\n memoryUsage,\n activeTimers,\n eventListeners: { totalListeners },\n interactionDelay,\n pendingRequests: { total: pending, requests: [] },\n };\n};\n\n/***************************\n * UI Helpers\n ***************************/\n\nconst scoreColor = (s: number) =>\n s >= 90 ? \"#4CAF50\" : s >= 70 ? \"#FFC107\" : s >= 50 ? \"#FF9800\" : \"#F44336\";\n\n/***************************\n * THE COMPONENT\n ***************************/\n\nexport const PerformanceMonitor: React.FC<{ children: React.ReactNode }> = ({\n children,\n}) => {\n const [open, setOpen] = useState(false);\n const [data, setData] = useState<PerformanceData | null>(null);\n const [loading, setLoading] = useState(false);\n const pop = useRef<HTMLDivElement | null>(null);\n\n const analyze = async () => {\n setLoading(true);\n try {\n setData(await checkPerformance());\n setOpen(true);\n } finally {\n setLoading(false);\n }\n };\n\n /* click‑outside */\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (pop.current && !pop.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, []);\n\n return (\n <>\n {children}\n <div className=\"PerformanceMonitor_container\">\n <button\n className=\"PerformanceMonitor_analyzeButton\"\n onClick={analyze}\n disabled={loading}\n aria-label=\"Analyze Performance\"\n >\n <span className=\"PerformanceMonitor_buttonIcon\">\n {loading ? \"⏳\" : \"🔍\"}\n </span>\n <span className=\"PerformanceMonitor_buttonText\">\n {loading ? \"Analyzing…\" : \"Analyze Performance\"}\n </span>\n </button>\n\n {open && data && (\n <div className=\"PerformanceMonitor_popover\" ref={pop}>\n {/* header */}\n <div className=\"PerformanceMonitor_popoverHeader\">\n <h2 className=\"PerformanceMonitor_popoverTitle\">\n Performance Analysis\n </h2>\n <button\n className=\"PerformanceMonitor_closeButton\"\n onClick={() => setOpen(false)}\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n\n {/* score donut */}\n <div className=\"PerformanceMonitor_scoreContainer\">\n <div\n className=\"PerformanceMonitor_scoreCircle\"\n style={{\n background: `conic-gradient(${scoreColor(\n data.score\n )} ${data.score}%, #f0f0f0 ${data.score}% 100%)`,\n }}\n >\n <div className=\"PerformanceMonitor_scoreInner\">\n <span className=\"PerformanceMonitor_scoreValue\">\n {Math.round(data.score)}\n </span>\n <span className=\"PerformanceMonitor_scoreLabel\">Score</span>\n </div>\n </div>\n </div>\n\n {/* results */}\n <div className=\"PerformanceMonitor_resultsContainer\">\n {data.score >= 99 ? (\n <div className=\"PerformanceMonitor_goodResult\">\n <h3>Great job! Your app is performing well.</h3>\n <p>Keep monitoring as your codebase grows.</p>\n </div>\n ) : (\n <>\n <h3 className=\"PerformanceMonitor_resultsTitle\">\n Areas for Improvement:\n </h3>\n\n {/* list of issues (rendered only when triggered) */}\n {data.domSize.totalElements > 1000 && (\n <Issue\n title=\"Large DOM Size\"\n detail={`DOM has ${data.domSize.totalElements} elements (limit ≈ 1000).`}\n suggestion=\"Simplify or virtualise parts of the UI.\"\n />\n )}\n\n {data.domSize.depth > 32 && (\n <Issue\n title=\"Deep DOM Structure\"\n detail={`DOM depth is ${data.domSize.depth} (recommended ≤ 32) for Single Page Applications.`}\n suggestion=\"Flatten nested component trees.\"\n />\n )}\n\n {data.imagesAlt.withoutAlt > 0 && (\n <Issue\n title=\"Missing Image Alts\"\n detail={`${data.imagesAlt.withoutAlt} image(s) lack alt attributes.`}\n suggestion=\"Add descriptive alt text.\"\n />\n )}\n\n {data.layoutShift.value > 0 && (\n <Issue\n title=\"Layout Shifts Detected\"\n detail={`CLS score ${data.layoutShift.value.toFixed(3)} across ${\n data.layoutShift.elements.length\n } element(s).`}\n suggestion=\"Reserve space for images/ads and avoid inserting content above existing UI.\"\n />\n )}\n\n {data.memoryUsage && data.memoryUsage.usedMB > 100 && (\n <Issue\n title=\"High Memory Usage\"\n detail={`Using ${data.memoryUsage.usedMB} MB (target ≤ 100 MB).`}\n suggestion=\"Release large objects and watch for leaks.\"\n />\n )}\n\n {data.activeTimers > 10 && (\n <Issue\n title=\"Too Many Active Timers\"\n detail={`${data.activeTimers} active timeouts/intervals (limit ≈ 10).`}\n suggestion=\"Clear timers on unmount, replace polling with events.\"\n />\n )}\n\n {data.eventListeners.totalListeners > 500 && (\n <Issue\n title=\"Excessive Event Listeners\"\n detail={`${data.eventListeners.totalListeners} listeners attached (limit ≈ 500).`}\n suggestion=\"Remove listeners on cleanup, delegate where possible.\"\n />\n )}\n\n {data.interactionDelay > 100 && (\n <Issue\n title=\"Slow Interaction Response\"\n detail={`Interaction delay ${Math.round(\n data.interactionDelay\n )} ms (target ≤ 100 ms).`}\n suggestion=\"Move heavy work off main thread or use Web Workers.\"\n />\n )}\n\n {data.pendingRequests.total > 5 && (\n <Issue\n title=\"Many Pending Requests\"\n detail={`${data.pendingRequests.total} concurrent fetches (limit ≈ 5).`}\n suggestion=\"Batch requests or debounce API calls.\"\n />\n )}\n </>\n )}\n </div>\n </div>\n )}\n </div>\n </>\n );\n};\n\n/* helper sub‑component */\ninterface IssueProps {\n title: string;\n detail: string;\n suggestion: string;\n}\nconst Issue: React.FC<IssueProps> = ({ title, detail, suggestion }) => (\n <div className=\"PerformanceMonitor_issueItem\">\n <div className=\"PerformanceMonitor_issueHeader\">\n <span className=\"PerformanceMonitor_issueIcon\">⚠️</span>\n <h4>{title}</h4>\n </div>\n <p>{detail}</p>\n <p className=\"PerformanceMonitor_suggestion\">{suggestion}</p>\n </div>\n);\n\nexport default PerformanceMonitor;\n"],"mappings":"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","names":[]}