UNPKG

speed-measure-vite-plugin

Version:
152 lines (148 loc) 4.83 kB
import { decorateVitePluginOption } from 'decorate-vite-plugin'; import { performance } from 'node:perf_hooks'; function log(text) { return console.log(`${text}`); } function colorGreen(s) { return `\x1B[32m${s}\x1B[0m`; } function colorPrimary(s) { return `\x1B[38;2;124;102;255m${s}\x1B[0m`; } function speedMeasureWrap(plugins, { hooks = ["transform"], sort = (a, b) => b - a, maxGapTimeOnce = 1e3, maxTransformTimeOnce } = {}) { let statsMap = /* @__PURE__ */ new Map(); let lastTransformRunAt = null; let interval = null; const gapTimeOnce = maxGapTimeOnce || maxTransformTimeOnce; function checkProcessDone() { if (lastTransformRunAt && lastTransformRunAt < performance.now() - gapTimeOnce) { printResults(statsMap, sort); statsMap = /* @__PURE__ */ new Map(); } } function printResults(statsMap2, sort2) { if (statsMap2.size === 0) { return; } log(colorPrimary("[SMVP]")); const pluginTotals = /* @__PURE__ */ new Map(); let allPluginsTotal = 0; statsMap2.forEach((hookStats, pluginName) => { let pluginTotal = 0; hookStats.forEach((stats) => { pluginTotal += stats.total; }); pluginTotals.set(pluginName, pluginTotal); allPluginsTotal += pluginTotal; }); const pluginEntries = Array.from(pluginTotals.entries()); if (typeof sort2 === "function") { pluginEntries.sort((a, b) => sort2(a[1], b[1])); } pluginEntries.forEach(([pluginName, pluginTotal], index) => { if (index > 0) { log(""); } log(`${pluginName}: ${colorGreen(`${pluginTotal / 1e3}s`)}`); const hookStats = statsMap2.get(pluginName); if (!hookStats || hookStats.size === 0) return; let maxHookNameLength = 0; hookStats.forEach((_, hookName) => { maxHookNameLength = Math.max(maxHookNameLength, hookName.length); }); const table = []; hookStats.forEach((stats, hookName) => { const { total, parallel } = stats; table.push({ hookName, total, parallel, totalS: `${total / 1e3}s`, parallelS: `${parallel / 1e3}s` }); }); if (typeof sort2 === "function") { table.sort((a, b) => sort2(a.total, b.total)); } table.forEach(({ hookName, totalS, parallelS }) => { const paddedHookName = hookName.padEnd(maxHookNameLength, " "); log(` ${paddedHookName} Total: ${colorGreen(totalS)} Parallel: ${colorGreen(parallelS)}`); }); }); log(colorPrimary(`All plugins total time: ${allPluginsTotal / 1e3}s`)); } const createHookDecorator = (hookName) => { return (originalHook, plugin) => { if (typeof originalHook !== "function") { return originalHook; } const name = plugin.name || `unnamed_${Math.random().toString(36).substring(2, 15)}`; return function decoratedHook(...args) { if (!interval) { interval = setInterval(checkProcessDone, 1e3); } let pluginStats = statsMap.get(name); if (!pluginStats) { pluginStats = /* @__PURE__ */ new Map(); statsMap.set(name, pluginStats); } let hookStats = pluginStats.get(hookName); if (!hookStats) { hookStats = { total: 0, parallel: 0, runAt: 0, runCount: 0 }; pluginStats.set(hookName, hookStats); } hookStats.runCount++; const startAt = performance.now(); if (hookName === "transform") { lastTransformRunAt = startAt; } if (hookStats.runAt === 0) { hookStats.runAt = startAt; } const res = originalHook.apply(this, args); function writeTime() { if (!hookStats) return; const endAt = performance.now(); hookStats.total += endAt - startAt; hookStats.runCount--; if (hookStats.runCount === 0) { hookStats.parallel += endAt - hookStats.runAt; hookStats.runAt = 0; } } if (res instanceof Promise) { res.then(writeTime); } else { writeTime(); } return res; }; }; }; let wrappedPlugins = plugins; hooks.forEach((hookName) => { wrappedPlugins = decorateVitePluginOption(wrappedPlugins, hookName, createHookDecorator(hookName)); }); const closeBundlePlugin = { name: "smvp:closeBundleWatcher", closeBundle: () => { printResults(statsMap, sort); if (interval) { clearInterval(interval); interval = null; } } }; return Array.isArray(wrappedPlugins) ? [...wrappedPlugins, closeBundlePlugin] : [wrappedPlugins, closeBundlePlugin]; } export { speedMeasureWrap as default };