vite-bundle-explorer
Advanced tools
| import { Plugin } from "vite"; | ||
| //#region plugin/stats-plugin.d.ts | ||
| interface StatsPluginOptions { | ||
| enabled?: boolean; | ||
| reportDirectoryName?: string; | ||
| reportCompressedSize?: boolean; | ||
| emitHtml?: boolean; | ||
| emitJson?: boolean; | ||
| check?: boolean; | ||
| failOnWarning?: boolean; | ||
| } | ||
| declare function statsPlugin(options?: StatsPluginOptions): Plugin<any>; | ||
| //#endregion | ||
| export { statsPlugin }; |
| import { join } from "node:path"; | ||
| import { gzip } from "node:zlib"; | ||
| import { promisify } from "node:util"; | ||
| import fs from "node:fs/promises"; | ||
| import { fileURLToPath } from "node:url"; | ||
| //#region src/entities/bundle-stats/index.ts | ||
| function isDependency(moduleFileName) { | ||
| return moduleFileName.startsWith("node_modules"); | ||
| } | ||
| function getModuleDependencyName(moduleFileName) { | ||
| if (!isDependency(moduleFileName)) return ""; | ||
| if (moduleFileName.startsWith("node_modules/.pnpm")) { | ||
| const parts$1 = moduleFileName.split("/"); | ||
| if (parts$1[4].startsWith("@")) return `${parts$1[4]}/${parts$1[5]}`; | ||
| else return parts$1[4]; | ||
| } | ||
| const parts = moduleFileName.split("/"); | ||
| const index = parts.lastIndexOf("node_modules"); | ||
| if (parts[index + 1].startsWith("@")) return `${parts[index + 1]}/${parts[index + 2]}`; | ||
| else return parts[index + 1]; | ||
| } | ||
| //#endregion | ||
| //#region src/features/overview/model/overview.ts | ||
| function getBundleOverview(stats) { | ||
| const numberOfChunks = stats.chunks.length; | ||
| let numberOfModules = 0; | ||
| let numberOfVirtualModules = 0; | ||
| for (const chunk of stats.chunks) { | ||
| numberOfModules += chunk.modules.length; | ||
| for (const mod of chunk.modules) if (mod.virtual) numberOfVirtualModules += 1; | ||
| } | ||
| const dependencies = /* @__PURE__ */ new Map(); | ||
| for (const module of stats.moduleFileNames) { | ||
| const dep = getModuleDependencyName(module); | ||
| if (!dep) continue; | ||
| const index = module.lastIndexOf(`node_modules/${dep}`); | ||
| const entry = dependencies.get(dep); | ||
| if (entry) { | ||
| if (!entry.indices.includes(index)) entry.indices.push(index); | ||
| } else dependencies.set(dep, { indices: [index] }); | ||
| } | ||
| const duplicatedDependencies = []; | ||
| for (const [dep, entry] of dependencies) if (entry.indices.length > 1) duplicatedDependencies.push({ | ||
| name: dep, | ||
| count: entry.indices.length | ||
| }); | ||
| return { | ||
| numberOfModules, | ||
| numberOfVirtualModules, | ||
| numberOfChunks, | ||
| numberOfDependencies: dependencies.size, | ||
| duplicatedDependencies, | ||
| hasWarnings: duplicatedDependencies.length > 0 | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region plugin/stats-plugin.ts | ||
| const compress = promisify(gzip); | ||
| const REPORT_DIR_NAME = "bundle-report"; | ||
| function upsertNodeIndex(nodes, item) { | ||
| const index = nodes.indexOf(item); | ||
| return index === -1 ? nodes.push(item) - 1 : index; | ||
| } | ||
| function statsPlugin(options) { | ||
| const emitHtml = options?.emitHtml ?? true; | ||
| const emitJson = options?.emitJson ?? false; | ||
| const check = options?.check ?? true; | ||
| const failOnWarning = options?.failOnWarning ?? false; | ||
| let root = process.cwd(); | ||
| let enabled = options?.enabled ?? true; | ||
| function truncatePath(filePath) { | ||
| let index = 0; | ||
| const normalizedPath = filePath.replaceAll("\0", ""); | ||
| if (root && normalizedPath.startsWith(root)) index = root.length; | ||
| return index > 0 ? normalizedPath.substring(index + 1) : normalizedPath; | ||
| } | ||
| const edges = /* @__PURE__ */ new Set(); | ||
| const stats = { | ||
| chunks: [], | ||
| importGraph: { edges: [] }, | ||
| moduleFileNames: [] | ||
| }; | ||
| return { | ||
| name: "stats-plugin", | ||
| configResolved(config) { | ||
| enabled = enabled && config.env.PROD; | ||
| }, | ||
| resolveId: { | ||
| order: "pre", | ||
| async handler(source, importer, options$1) { | ||
| if (!enabled) return; | ||
| if (!importer) return; | ||
| const result = await this.resolve(source, importer, { | ||
| ...options$1, | ||
| skipSelf: true | ||
| }); | ||
| if (!result) return; | ||
| const parent = upsertNodeIndex(stats.moduleFileNames, truncatePath(importer)); | ||
| const child = upsertNodeIndex(stats.moduleFileNames, truncatePath(result.id)); | ||
| edges.add(`${parent},${child}`); | ||
| } | ||
| }, | ||
| generateBundle: { async handler(_options, bundle) { | ||
| if (!enabled) return; | ||
| for (const [_name, chunk] of Object.entries(bundle)) { | ||
| if (chunk.type !== "chunk") continue; | ||
| const currentChunk = { | ||
| fileName: chunk.fileName, | ||
| modules: [], | ||
| minifiedLength: -1, | ||
| compressedLength: -1 | ||
| }; | ||
| stats.chunks.push(currentChunk); | ||
| for (const [moduleName, mod] of Object.entries(chunk.modules)) { | ||
| const fileName = truncatePath(moduleName); | ||
| currentChunk.modules.push({ | ||
| fileNameIndex: upsertNodeIndex(stats.moduleFileNames, fileName), | ||
| renderedLength: mod.renderedLength, | ||
| virtual: moduleName.startsWith("\0") ? true : void 0 | ||
| }); | ||
| } | ||
| } | ||
| stats.importGraph.edges = Array.from(edges).map((edge) => { | ||
| const pair = edge.split(","); | ||
| return [Number.parseInt(pair[0], 10), Number.parseInt(pair[1], 10)]; | ||
| }); | ||
| } }, | ||
| async writeBundle(_options, bundle) { | ||
| for (const [_name, chunk] of Object.entries(bundle)) { | ||
| if (chunk.type !== "chunk") continue; | ||
| const c = stats.chunks.find((c$1) => c$1.fileName === chunk.fileName); | ||
| if (!c) continue; | ||
| c.minifiedLength = chunk.code.length; | ||
| c.compressedLength = (await compress(chunk.code)).length; | ||
| } | ||
| }, | ||
| async closeBundle(error) { | ||
| if (!enabled || error) return; | ||
| enabled = false; | ||
| const target = join(root, options?.reportDirectoryName ?? REPORT_DIR_NAME); | ||
| try { | ||
| if ((await fs.stat(target)).isDirectory()) await fs.rm(target, { recursive: true }); | ||
| } catch (e) {} | ||
| await fs.mkdir(target); | ||
| if (emitHtml) { | ||
| const source = join(fileURLToPath(import.meta.url), "..", "dist-ui"); | ||
| const names = await fs.readdir(source); | ||
| await Promise.all(names.map((name) => { | ||
| return fs.cp(join(source, name), join(target, name), { recursive: true }); | ||
| })); | ||
| let html = await fs.readFile(join(target, "index.html"), "utf-8"); | ||
| html = html.replace("%BUNDLE_STATS%", JSON.stringify(stats).replaceAll("'", "\\'")); | ||
| fs.writeFile(join(target, "index.html"), html); | ||
| } | ||
| if (emitJson) fs.writeFile(join(target, "stats.json"), JSON.stringify(stats, null, 2)); | ||
| console.log(`Bundle stats saved to ${target}`); | ||
| if (emitHtml) console.log(`Run "npx vite-bundle-explorer ${target}" to view the stats`); | ||
| if (check) { | ||
| const report = getBundleOverview(stats); | ||
| if (report.duplicatedDependencies.length > 0) { | ||
| this.warn("Output bundle has duplicated dependencies"); | ||
| for (const dep of report.duplicatedDependencies) this.warn(`- ${dep.name} has ${dep.count} different versions`); | ||
| } | ||
| if (failOnWarning && report.hasWarnings) throw new Error("[plugin stats-plugin] Cancelling build due to failOnWarning option. Check [plugin stats-plugin] warnings for more details."); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| //#endregion | ||
| export { statsPlugin }; |
| *,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color, #e5e7eb)}:before,:after{--un-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.i-mdi-chart-tree{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14 6h8v16h-8zM2 4h20V2H2zm0 4h10V6H2zm7 14h3V10H9zm-7 0h5V10H2z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi-graph{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19.5 17c-.13 0-.26 0-.39.04l-1.61-3.25a2.5 2.5 0 0 0-1.75-4.29c-.13 0-.25 0-.39.04l-1.63-3.25c.48-.45.77-1.08.77-1.79a2.5 2.5 0 0 0-5 0c0 .71.29 1.34.76 1.79L8.64 9.54c-.14-.04-.26-.04-.39-.04a2.5 2.5 0 0 0-1.75 4.29l-1.61 3.25C4.76 17 4.63 17 4.5 17a2.5 2.5 0 0 0 0 5A2.5 2.5 0 0 0 7 19.5c0-.7-.29-1.34-.76-1.79l1.62-3.25c.14.04.26.04.39.04s.25 0 .39-.04l1.63 3.25c-.47.45-.77 1.09-.77 1.79a2.5 2.5 0 0 0 5 0A2.5 2.5 0 0 0 12 17c-.13 0-.26 0-.39.04L10 13.79c.46-.45.75-1.08.75-1.79s-.29-1.34-.75-1.79l1.61-3.25c.13.04.26.04.39.04s.26 0 .39-.04L14 10.21c-.45.45-.75 1.09-.75 1.79a2.5 2.5 0 0 0 2.5 2.5c.13 0 .25 0 .39-.04l1.63 3.25c-.47.45-.77 1.09-.77 1.79a2.5 2.5 0 0 0 5 0a2.5 2.5 0 0 0-2.5-2.5'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:alert-circle-outline{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:chevron-down{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:close{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:info{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:minus{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 13H5v-2h14z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:plus{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:warning-outline{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 2L1 21h22M12 6l7.53 13H4.47M11 10v4h2v-4m-2 6v2h2v-2'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:0}.left-\[50\%\]{left:50%}.right-2{right:.5rem}.top-\[50\%\]{top:50%}.top-3{top:.75rem}.z-30{z-index:30}.m-5{margin:1.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-auto{margin-top:auto;margin-bottom:auto}.ml-auto{margin-left:auto}.mt-2{margin-top:.5rem}.mt-auto{margin-top:auto}.block{display:block}.h-\[20px\]{height:20px}.h-3\.5{height:.875rem}.h-screen{height:100vh}.max-h-\[85vh\]{max-height:85vh}.max-w-\[350px\]{max-width:350px}.max-w-\[450px\]{max-width:450px}.max-w-\[70px\]{max-width:70px}.min-w-0{min-width:0}.w-\[24px\]{width:24px}.w-\[32px\]{width:32px}.w-\[90vw\]{width:90vw}.w-1\/2{width:50%}.w-1\/3{width:33.3333333333%}.w-3\.5{width:.875rem}.w-full{width:100%}.w-screen{width:100vw}.flex{display:flex}.flex-shrink-0{flex-shrink:0}.flex-shrink-1{flex-shrink:1}.flex-grow-1{flex-grow:1}.flex-col{flex-direction:column}.data-\[state\=checked\]\:translate-x-full[data-state=checked]{--un-translate-x:100%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-\[-50\%\]{--un-translate-x:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-0\.5{--un-translate-x:.125rem;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-y-\[-50\%\]{--un-translate-y:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.group[data-state=open] .group-data-\[state\=open\]\:rotate-180{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.cursor-pointer{cursor:pointer}.appearance-none{-webkit-appearance:none;appearance:none}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.b,.border,.border-1,.border-px{border-width:1px}.border-b,.data-\[state\=closed\]\:border-b[data-state=closed]{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-blue-400{--un-border-opacity:1;border-color:rgb(96 165 250 / var(--un-border-opacity))}.border-blue-600,.data-\[state\=checked\]\:border-blue-600[data-state=checked]{--un-border-opacity:1;border-color:rgb(37 99 235 / var(--un-border-opacity))}.border-gray-300{--un-border-opacity:1;border-color:rgb(209 213 219 / var(--un-border-opacity))}.border-stone-300{--un-border-opacity:1;border-color:rgb(214 211 209 / var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.border-none{border-style:none}.border-solid{border-style:solid}.bg-blue-600,.data-\[state\=checked\]\:bg-blue-600[data-state=checked]{--un-bg-opacity:1;background-color:rgb(37 99 235 / var(--un-bg-opacity))}.bg-gray-200{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}.bg-transparent{background-color:transparent}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.data-\[state\=unchecked\]\:bg-stone-300[data-state=unchecked]{--un-bg-opacity:1;background-color:rgb(214 211 209 / var(--un-bg-opacity))}.hover\:bg-blue-300:hover{--un-bg-opacity:1;background-color:rgb(147 197 253 / var(--un-bg-opacity))}.hover\:bg-blue-700:hover{--un-bg-opacity:1;background-color:rgb(29 78 216 / var(--un-bg-opacity))}.hover\:bg-gray-200:hover{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}.hover\:bg-gray-300:hover{--un-bg-opacity:1;background-color:rgb(209 213 219 / var(--un-bg-opacity))}.active\:bg-blue-800:active{--un-bg-opacity:1;background-color:rgb(30 64 175 / var(--un-bg-opacity))}.p-1{padding:.25rem}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-center{text-align:center}.c-slate-800{--un-text-opacity:1;color:rgb(30 41 59 / var(--un-text-opacity))}.c-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.c-yellow-500{--un-text-opacity:1;color:rgb(234 179 8 / var(--un-text-opacity))}.hover\:c-white:hover{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.capitalize{text-transform:capitalize}.opacity-75{opacity:.75}.shadow-sm{--un-shadow:var(--un-shadow-inset) 0 1px 2px 0 var(--un-shadow-color, rgb(0 0 0 / .05));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.will-change-transform{will-change:transform} |
Sorry, the diff of this file is too big to display
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <title>vite-bundle-explorer</title> | ||
| <script> | ||
| var BUNDLE_STATS = '%BUNDLE_STATS%' | ||
| </script> | ||
| <script type="module" crossorigin src="/assets/index-DHfe3O-k.js"></script> | ||
| <link rel="stylesheet" crossorigin href="/assets/index-D-ZNVfN7.css"> | ||
| </head> | ||
| <body> | ||
| <div id="app"></div> | ||
| </body> | ||
| </html> |
+17
-16
| { | ||
| "name": "vite-bundle-explorer", | ||
| "description": "Bundle analyzer and visualizer tool for Vite", | ||
| "version": "0.3.2", | ||
| "version": "0.3.3", | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "vue-tsc -b && pnpm build:plugin && vite build", | ||
| "build:plugin": "tsdown", | ||
| "format": "prettier src plugin bin vite.config.ts --write", | ||
| "release": "pnpm build && pnpm changelogen --release --push && pnpm publish" | ||
| }, | ||
| "homepage": "https://github.com/Solant/vite-bundle-explorer#readme", | ||
@@ -35,11 +42,11 @@ "repository": { | ||
| "./plugin": { | ||
| "types": "./plugin/stats-plugin.d.ts", | ||
| "default": "./plugin/stats-plugin.js" | ||
| "types": "./dist-plugin/stats-plugin.d.ts", | ||
| "default": "./dist-plugin/stats-plugin.js" | ||
| } | ||
| }, | ||
| "files": [ | ||
| "./dist/index.html", | ||
| "./dist/assets", | ||
| "plugin/stats-plugin.js", | ||
| "plugin/stats-plugin.d.ts", | ||
| "dist-ui/index.html", | ||
| "dist-ui/assets", | ||
| "dist-plugin/stats-plugin.js", | ||
| "dist-plugin/stats-plugin.d.ts", | ||
| "bin/index.js" | ||
@@ -63,15 +70,9 @@ ], | ||
| "reka-ui": "^2.3.2", | ||
| "tsdown": "^0.15.4", | ||
| "typescript": "~5.8.3", | ||
| "unocss": "^66.3.3", | ||
| "vite": "^7.0.4", | ||
| "vite": "^7.1.7", | ||
| "vue": "^3.5.17", | ||
| "vue-tsc": "^2.2.12" | ||
| }, | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "vue-tsc -b && pnpm build:plugin && vite build", | ||
| "build:plugin": "tsc --module Node16 --moduleResolution node16 plugin/stats-plugin.ts", | ||
| "format": "prettier src plugin bin vite.config.ts --write", | ||
| "release": "pnpm build && pnpm changelogen --release --push && pnpm publish" | ||
| } | ||
| } | ||
| } |
+3
-0
@@ -10,2 +10,3 @@ # vite-bundle-explorer | ||
| - ✅ Detect duplicated dependencies | ||
| - ✅ Run checks during build | ||
@@ -73,1 +74,3 @@  | ||
| | `emitJson` | `boolean` | `false` | Generate `stats.json` file | | ||
| | `check` | `boolean` | `true` | Run report checks during build | | ||
| | `failOnWarning` | `boolean` | `false` | Cancel build if bundle has any report warnings | |
Sorry, the diff of this file is too big to display
| *,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color, #e5e7eb)}:before,:after{--un-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.i-mdi-chart-tree{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14 6h8v16h-8zM2 4h20V2H2zm0 4h10V6H2zm7 14h3V10H9zm-7 0h5V10H2z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi-graph{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19.5 17c-.13 0-.26 0-.39.04l-1.61-3.25a2.5 2.5 0 0 0-1.75-4.29c-.13 0-.25 0-.39.04l-1.63-3.25c.48-.45.77-1.08.77-1.79a2.5 2.5 0 0 0-5 0c0 .71.29 1.34.76 1.79L8.64 9.54c-.14-.04-.26-.04-.39-.04a2.5 2.5 0 0 0-1.75 4.29l-1.61 3.25C4.76 17 4.63 17 4.5 17a2.5 2.5 0 0 0 0 5A2.5 2.5 0 0 0 7 19.5c0-.7-.29-1.34-.76-1.79l1.62-3.25c.14.04.26.04.39.04s.25 0 .39-.04l1.63 3.25c-.47.45-.77 1.09-.77 1.79a2.5 2.5 0 0 0 5 0A2.5 2.5 0 0 0 12 17c-.13 0-.26 0-.39.04L10 13.79c.46-.45.75-1.08.75-1.79s-.29-1.34-.75-1.79l1.61-3.25c.13.04.26.04.39.04s.26 0 .39-.04L14 10.21c-.45.45-.75 1.09-.75 1.79a2.5 2.5 0 0 0 2.5 2.5c.13 0 .25 0 .39-.04l1.63 3.25c-.47.45-.77 1.09-.77 1.79a2.5 2.5 0 0 0 5 0a2.5 2.5 0 0 0-2.5-2.5'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:alert-circle-outline{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:chevron-down{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7.41 8.58L12 13.17l4.59-4.59L18 10l-6 6l-6-6z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:close{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:info{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:minus{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 13H5v-2h14z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:plus{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-mdi\:warning-outline{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 2L1 21h22M12 6l7.53 13H4.47M11 10v4h2v-4m-2 6v2h2v-2'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:0}.left-\[50\%\]{left:50%}.right-2{right:.5rem}.top-\[50\%\]{top:50%}.top-3{top:.75rem}.z-30{z-index:30}.m-5{margin:1.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-auto{margin-top:auto;margin-bottom:auto}.ml-auto{margin-left:auto}.mt-2{margin-top:.5rem}.mt-auto{margin-top:auto}.block{display:block}.h-\[20px\]{height:20px}.h-3\.5{height:.875rem}.h-screen{height:100vh}.max-h-\[85vh\]{max-height:85vh}.max-w-\[350px\]{max-width:350px}.max-w-\[450px\]{max-width:450px}.max-w-\[70px\]{max-width:70px}.min-w-0{min-width:0}.w-\[24px\]{width:24px}.w-\[32px\]{width:32px}.w-\[90vw\]{width:90vw}.w-1\/2{width:50%}.w-1\/3{width:33.3333333333%}.w-3\.5{width:.875rem}.w-full{width:100%}.w-screen{width:100vw}.flex{display:flex}.flex-shrink-0{flex-shrink:0}.flex-shrink-1{flex-shrink:1}.flex-grow-1{flex-grow:1}.flex-col{flex-direction:column}.data-\[state\=checked\]\:translate-x-full[data-state=checked]{--un-translate-x:100%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-\[-50\%\]{--un-translate-x:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-0\.5{--un-translate-x:.125rem;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-y-\[-50\%\]{--un-translate-y:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.group[data-state=open] .group-data-\[state\=open\]\:rotate-180{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.cursor-pointer{cursor:pointer}.appearance-none{-webkit-appearance:none;appearance:none}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.b,.border,.border-1,.border-px{border-width:1px}.border-b,.data-\[state\=closed\]\:border-b[data-state=closed]{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-blue-400{--un-border-opacity:1;border-color:rgb(96 165 250 / var(--un-border-opacity))}.border-blue-600,.data-\[state\=checked\]\:border-blue-600[data-state=checked]{--un-border-opacity:1;border-color:rgb(37 99 235 / var(--un-border-opacity))}.border-gray-300{--un-border-opacity:1;border-color:rgb(209 213 219 / var(--un-border-opacity))}.border-stone-300{--un-border-opacity:1;border-color:rgb(214 211 209 / var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.border-none{border-style:none}.border-solid{border-style:solid}.bg-blue-600,.data-\[state\=checked\]\:bg-blue-600[data-state=checked]{--un-bg-opacity:1;background-color:rgb(37 99 235 / var(--un-bg-opacity))}.bg-gray-200{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}.bg-transparent{background-color:transparent}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.data-\[state\=unchecked\]\:bg-stone-300[data-state=unchecked]{--un-bg-opacity:1;background-color:rgb(214 211 209 / var(--un-bg-opacity))}.hover\:bg-blue-300:hover{--un-bg-opacity:1;background-color:rgb(147 197 253 / var(--un-bg-opacity))}.hover\:bg-blue-700:hover{--un-bg-opacity:1;background-color:rgb(29 78 216 / var(--un-bg-opacity))}.hover\:bg-gray-200:hover{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}.hover\:bg-gray-300:hover{--un-bg-opacity:1;background-color:rgb(209 213 219 / var(--un-bg-opacity))}.active\:bg-blue-800:active{--un-bg-opacity:1;background-color:rgb(30 64 175 / var(--un-bg-opacity))}.p-1{padding:.25rem}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-center{text-align:center}.c-slate-800{--un-text-opacity:1;color:rgb(30 41 59 / var(--un-text-opacity))}.c-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.c-yellow-500{--un-text-opacity:1;color:rgb(234 179 8 / var(--un-text-opacity))}.hover\:c-white:hover{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.capitalize{text-transform:capitalize}.opacity-75{opacity:.75}.shadow-sm{--un-shadow:var(--un-shadow-inset) 0 1px 2px 0 var(--un-shadow-color, rgb(0 0 0 / .05));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.will-change-transform{will-change:transform} |
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <title>vite-bundle-explorer</title> | ||
| <script> | ||
| var BUNDLE_STATS = '%BUNDLE_STATS%' | ||
| </script> | ||
| <script type="module" crossorigin src="/assets/index-C2mzRsne.js"></script> | ||
| <link rel="stylesheet" crossorigin href="/assets/index-D-ZNVfN7.css"> | ||
| </head> | ||
| <body> | ||
| <div id="app"></div> | ||
| </body> | ||
| </html> |
| import { type Plugin } from 'vite'; | ||
| interface StatsPluginOptions { | ||
| enabled?: boolean; | ||
| reportDirectoryName?: string; | ||
| reportCompressedSize?: boolean; | ||
| emitHtml?: boolean; | ||
| emitJson?: boolean; | ||
| } | ||
| declare function statsPlugin(options?: StatsPluginOptions): Plugin; | ||
| export { statsPlugin }; |
| import { join } from 'node:path'; | ||
| import { gzip } from 'node:zlib'; | ||
| import { promisify } from 'node:util'; | ||
| import fs from 'node:fs/promises'; | ||
| const compress = promisify(gzip); | ||
| const REPORT_DIR_NAME = 'bundle-report'; | ||
| function upsertNodeIndex(nodes, item) { | ||
| const index = nodes.indexOf(item); | ||
| return index === -1 ? nodes.push(item) - 1 : index; | ||
| } | ||
| export function statsPlugin(options) { | ||
| const emitHtml = options?.emitHtml ?? true; | ||
| const emitJson = options?.emitJson ?? false; | ||
| let root = process.cwd(); | ||
| let outDir = ''; | ||
| let enabled = options?.enabled ?? true; | ||
| let reportCompressed = true; | ||
| function truncatePath(filePath) { | ||
| let index = 0; | ||
| const normalizedPath = filePath.replaceAll('\u0000', ''); | ||
| if (outDir && normalizedPath.startsWith(outDir)) { | ||
| index = outDir.length; | ||
| } | ||
| else if (root && normalizedPath.startsWith(root)) { | ||
| index = root.length; | ||
| } | ||
| return index > 0 ? normalizedPath.substring(index + 1) : normalizedPath; | ||
| } | ||
| const edges = new Set(); | ||
| const stats = { chunks: [], importGraph: { edges: [] }, moduleFileNames: [] }; | ||
| const plugin = { | ||
| name: 'stats-plugin', | ||
| // vite specific hook | ||
| configResolved(config) { | ||
| // disable during dev mode | ||
| enabled = enabled && config.env.PROD; | ||
| }, | ||
| resolveId: { | ||
| order: 'pre', | ||
| async handler(source, importer, options) { | ||
| if (!enabled) { | ||
| return; | ||
| } | ||
| // skip bundle root element | ||
| if (!importer) { | ||
| return; | ||
| } | ||
| const result = await this.resolve(source, importer, { ...options, skipSelf: true }); | ||
| if (!result) { | ||
| return; | ||
| } | ||
| const parent = upsertNodeIndex(stats.moduleFileNames, truncatePath(importer)); | ||
| const child = upsertNodeIndex(stats.moduleFileNames, truncatePath(result.id)); | ||
| edges.add(`${parent},${child}`); | ||
| }, | ||
| }, | ||
| generateBundle: { | ||
| async handler(_options, bundle) { | ||
| if (!enabled) { | ||
| return; | ||
| } | ||
| for (const [_name, chunk] of Object.entries(bundle)) { | ||
| if (chunk.type !== 'chunk') { | ||
| continue; | ||
| } | ||
| const currentChunk = { | ||
| fileName: chunk.fileName, | ||
| modules: [], | ||
| minifiedLength: -1, | ||
| compressedLength: -1, | ||
| }; | ||
| stats.chunks.push(currentChunk); | ||
| for (const [moduleName, mod] of Object.entries(chunk.modules)) { | ||
| const fileName = truncatePath(moduleName); | ||
| currentChunk.modules.push({ | ||
| fileNameIndex: upsertNodeIndex(stats.moduleFileNames, fileName), | ||
| renderedLength: mod.renderedLength, | ||
| virtual: moduleName.startsWith('\u0000') ? true : undefined, | ||
| }); | ||
| } | ||
| } | ||
| stats.importGraph.edges = Array.from(edges).map((edge) => { | ||
| const pair = edge.split(','); | ||
| return [Number.parseInt(pair[0], 10), Number.parseInt(pair[1], 10)]; | ||
| }); | ||
| }, | ||
| }, | ||
| async writeBundle(_options, bundle) { | ||
| for (const [_name, chunk] of Object.entries(bundle)) { | ||
| if (chunk.type !== 'chunk') { | ||
| continue; | ||
| } | ||
| const c = stats.chunks.find((c) => c.fileName === chunk.fileName); | ||
| if (!c) { | ||
| continue; | ||
| } | ||
| c.minifiedLength = chunk.code.length; | ||
| if (reportCompressed) { | ||
| c.compressedLength = (await compress(chunk.code)).length; | ||
| } | ||
| } | ||
| }, | ||
| async closeBundle(error) { | ||
| if (!enabled || error) { | ||
| return; | ||
| } | ||
| // prevent this hook from being called again for a different format | ||
| enabled = false; | ||
| // create a target directory | ||
| const target = join(root, options?.reportDirectoryName ?? REPORT_DIR_NAME); | ||
| try { | ||
| const stat = await fs.stat(target); | ||
| if (stat.isDirectory()) { | ||
| await fs.rm(target, { recursive: true }); | ||
| } | ||
| } | ||
| catch (e) { } | ||
| await fs.mkdir(target); | ||
| if (emitHtml) { | ||
| const source = new URL('../dist', import.meta.url); | ||
| const names = await fs.readdir(source); | ||
| await Promise.all(names.map((name) => { | ||
| return fs.cp(join(source.pathname, name), join(target, name), { recursive: true }); | ||
| })); | ||
| let html = await fs.readFile(join(target, 'index.html'), 'utf-8'); | ||
| html = html.replace('%BUNDLE_STATS%', JSON.stringify(stats).replaceAll("'", "\\'")); | ||
| fs.writeFile(join(target, 'index.html'), html); | ||
| } | ||
| if (emitJson) { | ||
| fs.writeFile(join(target, 'stats.json'), JSON.stringify(stats, null, 2)); | ||
| } | ||
| console.log(`Bundle stats saved to ${target}`); | ||
| if (emitHtml) { | ||
| console.log(`Run "npx vite-bundle-explorer ${target}" to view the stats`); | ||
| } | ||
| }, | ||
| }; | ||
| return plugin; | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
698251
0.2%2883
1.23%75
4.17%18
5.88%3
50%