@stacksjs/stx 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a11y.d.ts +109 -5
- package/dist/analytics.d.ts +40 -0
- package/dist/animation.d.ts +90 -0
- package/dist/app.d.ts +51 -0
- package/dist/ast.d.ts +286 -0
- package/dist/async-components.d.ts +101 -0
- package/dist/auth.d.ts +1 -3
- package/dist/browser-composables.d.ts +314 -0
- package/dist/build-optimizer.d.ts +126 -0
- package/dist/build-views.d.ts +37 -0
- package/dist/bundle-analyzer/collector.d.ts +66 -0
- package/dist/bundle-analyzer/index.d.ts +60 -0
- package/dist/bundle-analyzer/report.d.ts +39 -0
- package/dist/bundle-analyzer/treemap.d.ts +19 -0
- package/dist/bundle-analyzer.js +499 -0
- package/dist/caching.d.ts +7 -0
- package/dist/cli.js +10880 -1199
- package/dist/client/directive.d.ts +10 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/router.d.ts +36 -0
- package/dist/client/stx-router.browser.d.ts +0 -0
- package/dist/client-script.d.ts +22 -0
- package/dist/component-hmr.d.ts +120 -0
- package/dist/components.d.ts +23 -1
- package/dist/composables/index.d.ts +277 -0
- package/dist/composables/use-battery.d.ts +46 -0
- package/dist/composables/use-broadcast-channel.d.ts +58 -0
- package/dist/composables/use-clipboard.d.ts +34 -0
- package/dist/composables/use-cookie.d.ts +70 -0
- package/dist/composables/use-device-orientation.d.ts +109 -0
- package/dist/composables/use-event-source.d.ts +77 -0
- package/dist/composables/use-eye-dropper.d.ts +107 -0
- package/dist/composables/use-fetch.d.ts +84 -0
- package/dist/composables/use-fullscreen.d.ts +47 -0
- package/dist/composables/use-geolocation.d.ts +62 -0
- package/dist/composables/use-idle.d.ts +84 -0
- package/dist/composables/use-intersection-observer.d.ts +81 -0
- package/dist/composables/use-keyboard.d.ts +100 -0
- package/dist/composables/use-media-query.d.ts +56 -0
- package/dist/composables/use-mouse.d.ts +64 -0
- package/dist/composables/use-mutation-observer.d.ts +101 -0
- package/dist/composables/use-network.d.ts +40 -0
- package/dist/composables/use-notification.d.ts +89 -0
- package/dist/composables/use-permissions.d.ts +109 -0
- package/dist/composables/use-resize-observer.d.ts +60 -0
- package/dist/composables/use-share.d.ts +70 -0
- package/dist/composables/use-speech.d.ts +117 -0
- package/dist/composables/use-storage.d.ts +64 -0
- package/dist/composables/use-text-selection.d.ts +97 -0
- package/dist/composables/use-wake-lock.d.ts +85 -0
- package/dist/composables/use-websocket.d.ts +69 -0
- package/dist/composables/use-window.d.ts +84 -0
- package/dist/composables.d.ts +268 -0
- package/dist/composition-api.d.ts +190 -0
- package/dist/computed.d.ts +137 -0
- package/dist/conditionals.d.ts +14 -2
- package/dist/config.d.ts +35 -2
- package/dist/craft-bridge.d.ts +319 -0
- package/dist/craft-compiler.d.ts +229 -0
- package/dist/craft-components.d.ts +411 -0
- package/dist/craft-entry.d.ts +5 -0
- package/dist/craft-ssr.d.ts +134 -0
- package/dist/craft.js +1553 -0
- package/dist/csp.d.ts +229 -0
- package/dist/database.d.ts +407 -0
- package/dist/database.js +5 -0
- package/dist/defer.d.ts +4 -0
- package/dist/deploy/config-generators.d.ts +75 -0
- package/dist/deploy/index.d.ts +84 -0
- package/dist/deploy/netlify.d.ts +109 -0
- package/dist/dev-server/crosswind.d.ts +54 -0
- package/dist/dev-server/index.d.ts +7 -0
- package/dist/dev-server/keyboard-shortcuts.d.ts +34 -0
- package/dist/dev-server/native-window.d.ts +40 -0
- package/dist/dev-server/port-utils.d.ts +27 -0
- package/dist/dev-server/terminal-colors.d.ts +60 -0
- package/dist/dev-server/theme-selector.d.ts +32 -0
- package/dist/dev-server/types.d.ts +92 -0
- package/dist/dev-server.d.ts +21 -0
- package/dist/devtools.d.ts +142 -0
- package/dist/directive-api.d.ts +111 -0
- package/dist/dynamic-components.d.ts +14 -0
- package/dist/edge-runtime.d.ts +200 -0
- package/dist/env.d.ts +9 -0
- package/dist/error-boundaries.d.ts +71 -0
- package/dist/error-handling.d.ts +1 -101
- package/dist/errors/codes.d.ts +99 -0
- package/dist/errors/formatter.d.ts +64 -0
- package/dist/errors/index.d.ts +56 -0
- package/dist/errors/logger.d.ts +74 -0
- package/dist/errors/sanitizer.d.ts +43 -0
- package/dist/errors/types.d.ts +79 -0
- package/dist/events.d.ts +106 -0
- package/dist/expressions.d.ts +86 -11
- package/dist/forms-validation.d.ts +173 -0
- package/dist/forms.d.ts +157 -8
- package/dist/head.d.ts +225 -0
- package/dist/heatmap.d.ts +125 -0
- package/dist/hot-reload.d.ts +87 -0
- package/dist/hydration-runtime.d.ts +47 -0
- package/dist/hydration.d.ts +161 -0
- package/dist/i18n.d.ts +239 -3
- package/dist/image-optimization/build-plugin.d.ts +53 -0
- package/dist/image-optimization/component.d.ts +46 -0
- package/dist/image-optimization/directive.d.ts +30 -0
- package/dist/image-optimization/index.d.ts +86 -0
- package/dist/image-optimization/processor.d.ts +112 -0
- package/dist/includes.d.ts +94 -9
- package/dist/index.d.ts +63 -3
- package/dist/index.js +11603 -1318
- package/dist/init.d.ts +32 -2
- package/dist/interactive.d.ts +14 -0
- package/dist/internal-markdown.d.ts +22 -0
- package/dist/jsx-runtime.d.ts +110 -0
- package/dist/keep-alive.d.ts +87 -0
- package/dist/lazy-loader.d.ts +122 -0
- package/dist/loading-indicator.d.ts +40 -0
- package/dist/loops.d.ts +22 -1
- package/dist/media/client/blur-up.d.ts +65 -0
- package/dist/media/client/index.d.ts +77 -0
- package/dist/media/client/lazy-load.d.ts +73 -0
- package/dist/media/client/upload-handler.d.ts +79 -0
- package/dist/media/image/component.d.ts +46 -0
- package/dist/media/image/directive.d.ts +9 -0
- package/dist/media/image/editing.d.ts +212 -0
- package/dist/media/image/index.d.ts +118 -0
- package/dist/media/image/placeholder.d.ts +78 -0
- package/dist/media/image/processor/cache.d.ts +32 -0
- package/dist/media/image/processor/index.d.ts +12 -0
- package/dist/media/image/processor/optimizer.d.ts +13 -0
- package/dist/media/image/processor/responsive.d.ts +17 -0
- package/dist/media/image/srcset.d.ts +158 -0
- package/dist/media/index.d.ts +295 -0
- package/dist/media/manager/embed.d.ts +25 -0
- package/dist/media/protected/component.d.ts +34 -0
- package/dist/media/protected/index.d.ts +34 -0
- package/dist/media/protected/signature.d.ts +72 -0
- package/dist/media/shared/cache.d.ts +54 -0
- package/dist/media/shared/hash.d.ts +24 -0
- package/dist/media/shared/index.d.ts +2 -0
- package/dist/media/types.d.ts +1051 -0
- package/dist/media/upload/component.d.ts +23 -0
- package/dist/media/upload/index.d.ts +1 -0
- package/dist/media/video/directive.d.ts +9 -0
- package/dist/media/video/index.d.ts +47 -0
- package/dist/media/video/processor/cache.d.ts +33 -0
- package/dist/media/video/processor/index.d.ts +21 -0
- package/dist/media/video/processor/streaming.d.ts +19 -0
- package/dist/media/video/processor/thumbnail.d.ts +28 -0
- package/dist/media/video/processor/transcoder.d.ts +9 -0
- package/dist/middleware.d.ts +42 -3
- package/dist/native-build.d.ts +74 -0
- package/dist/parser/directive-parser.d.ts +79 -0
- package/dist/parser/expression-parser.d.ts +59 -0
- package/dist/parser/index.d.ts +35 -0
- package/dist/parser/tokenizer.d.ts +81 -0
- package/dist/partial-hydration.d.ts +88 -0
- package/dist/performance-utils.d.ts +146 -3
- package/dist/plugin-system.d.ts +128 -0
- package/dist/precompiler.d.ts +108 -0
- package/dist/production-build.d.ts +199 -0
- package/dist/props.d.ts +199 -0
- package/dist/pwa/audit.d.ts +42 -0
- package/dist/pwa/directives.d.ts +29 -0
- package/dist/pwa/icons.d.ts +39 -0
- package/dist/pwa/index.d.ts +59 -0
- package/dist/pwa/inject.d.ts +22 -0
- package/dist/pwa/manifest.d.ts +104 -0
- package/dist/pwa/offline.d.ts +8 -0
- package/dist/pwa/precache.d.ts +29 -0
- package/dist/pwa/service-worker.d.ts +21 -0
- package/dist/pwa/workbox-strategies.d.ts +100 -0
- package/dist/pwa/workbox.d.ts +52 -0
- package/dist/pwa.d.ts +51 -0
- package/dist/pwa.js +8124 -0
- package/dist/reactive-bindings.d.ts +24 -0
- package/dist/reactive.d.ts +100 -0
- package/dist/reactivity.d.ts +253 -0
- package/dist/route-middleware.d.ts +232 -0
- package/dist/router.d.ts +31 -0
- package/dist/routes.d.ts +0 -7
- package/dist/runtime.d.ts +140 -0
- package/dist/safe-evaluator.d.ts +117 -3
- package/dist/scaffolding.d.ts +113 -0
- package/dist/seo.d.ts +120 -7
- package/dist/server-components.d.ts +134 -0
- package/dist/signals.d.ts +501 -0
- package/dist/slots.d.ts +63 -0
- package/dist/source-maps.d.ts +117 -0
- package/dist/ssg.d.ts +157 -0
- package/dist/ssg.js +6831 -0
- package/dist/ssr.d.ts +107 -0
- package/dist/state-management.d.ts +324 -0
- package/dist/stores-client.d.ts +70 -0
- package/dist/story/addons.d.ts +123 -0
- package/dist/story/analytics.d.ts +92 -0
- package/dist/story/auto-stories.d.ts +38 -0
- package/dist/story/bookmarks.d.ts +53 -0
- package/dist/story/bun-test.d.ts +44 -0
- package/dist/story/cli.d.ts +34 -0
- package/dist/story/collect/analyzer.d.ts +33 -0
- package/dist/story/collect/index.d.ts +27 -0
- package/dist/story/collect/parser.d.ts +17 -0
- package/dist/story/collect/scanner.d.ts +13 -0
- package/dist/story/collect/tree.d.ts +17 -0
- package/dist/story/commands/build.d.ts +14 -0
- package/dist/story/commands/dev.d.ts +16 -0
- package/dist/story/commands/index.d.ts +6 -0
- package/dist/story/commands/preview.d.ts +15 -0
- package/dist/story/compiled-output.d.ts +26 -0
- package/dist/story/composition.d.ts +47 -0
- package/dist/story/config-watcher.d.ts +26 -0
- package/dist/story/config.d.ts +26 -0
- package/dist/story/context.d.ts +21 -0
- package/dist/story/controls/index.d.ts +54 -0
- package/dist/story/crosswind.d.ts +29 -0
- package/dist/story/desktop-preview.d.ts +34 -0
- package/dist/story/docs-generator.d.ts +30 -0
- package/dist/story/errors.d.ts +47 -0
- package/dist/story/figma-export.d.ts +169 -0
- package/dist/story/generator.d.ts +21 -0
- package/dist/story/hmr.d.ts +64 -0
- package/dist/story/hot-swap.d.ts +35 -0
- package/dist/story/index.d.ts +51 -0
- package/dist/story/interactions.d.ts +52 -0
- package/dist/story/keyboard-shortcuts.d.ts +34 -0
- package/dist/story/output.d.ts +85 -0
- package/dist/story/performance.d.ts +76 -0
- package/dist/story/presets.d.ts +62 -0
- package/dist/story/props-validation.d.ts +45 -0
- package/dist/story/renderer.d.ts +53 -0
- package/dist/story/search-index.d.ts +47 -0
- package/dist/story/search.d.ts +45 -0
- package/dist/story/server.d.ts +21 -0
- package/dist/story/setup.d.ts +47 -0
- package/dist/story/snapshots.d.ts +65 -0
- package/dist/story/testing.d.ts +58 -0
- package/dist/story/theme.d.ts +68 -0
- package/dist/story/types.d.ts +249 -0
- package/dist/story/ui/code-panel.d.ts +42 -0
- package/dist/story/ui/controls-panel.d.ts +25 -0
- package/dist/story/ui/index.d.ts +4 -0
- package/dist/story/ui/navigation.d.ts +55 -0
- package/dist/story/ui/preview.d.ts +46 -0
- package/dist/story/visual-testing.d.ts +45 -0
- package/dist/streaming.d.ts +82 -2
- package/dist/suspense.d.ts +83 -0
- package/dist/teleport.d.ts +9 -0
- package/dist/testing.d.ts +289 -0
- package/dist/transitions.d.ts +87 -0
- package/dist/type-checker.d.ts +109 -0
- package/dist/types/component-types.d.ts +129 -0
- package/dist/types/config-types.d.ts +336 -0
- package/dist/types/context-types.d.ts +99 -0
- package/dist/types/csp-types.d.ts +79 -0
- package/dist/types/directive-types.d.ts +259 -0
- package/dist/types/index.d.ts +98 -0
- package/dist/types/pwa-types.d.ts +218 -0
- package/dist/types.d.ts +1 -315
- package/dist/typescript-templates.d.ts +178 -0
- package/dist/utils.d.ts +52 -6
- package/dist/validator.d.ts +77 -0
- package/dist/variable-extractor.d.ts +39 -0
- package/dist/view-composers.d.ts +154 -9
- package/dist/virtual-scrolling.d.ts +103 -0
- package/dist/visual-editor.d.ts +209 -0
- package/dist/visual-testing.d.ts +109 -0
- package/dist/visual-testing.js +126 -0
- package/dist/vue-template.d.ts +16 -0
- package/dist/web-components/css-scoping.d.ts +54 -0
- package/dist/web-components/index.d.ts +20 -0
- package/dist/web-components/reactive-generator.d.ts +72 -0
- package/dist/web-components.d.ts +222 -2
- package/dist/x-element.d.ts +35 -0
- package/package.json +41 -11
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { collectBundleStats, formatBytes, parseSize } from './collector';
|
|
2
|
+
import { generateReport, analyzeBundle } from './report';
|
|
3
|
+
import { generateTreemap, openInBrowser } from './treemap';
|
|
4
|
+
/**
|
|
5
|
+
* Analyze a bundle directory and generate a report
|
|
6
|
+
*/
|
|
7
|
+
export declare function analyze(options?: AnalyzeOptions): Promise<{
|
|
8
|
+
stats: ReturnType<typeof collectBundleStats> extends Promise<infer T> ? T : never
|
|
9
|
+
report: string
|
|
10
|
+
outputPath?: string
|
|
11
|
+
exceedsThreshold: boolean
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Quick summary of bundle size
|
|
15
|
+
*/
|
|
16
|
+
export declare function getBundleSummary(directory: string): Promise<{
|
|
17
|
+
totalSize: number
|
|
18
|
+
totalSizeFormatted: string
|
|
19
|
+
gzipSize: number
|
|
20
|
+
gzipSizeFormatted: string
|
|
21
|
+
moduleCount: number
|
|
22
|
+
chunkCount: number
|
|
23
|
+
}>;
|
|
24
|
+
export declare interface AnalyzeOptions {
|
|
25
|
+
directory?: string
|
|
26
|
+
output?: string
|
|
27
|
+
format?: 'html' | 'json' | 'text' | 'markdown'
|
|
28
|
+
open?: boolean
|
|
29
|
+
gzip?: boolean
|
|
30
|
+
threshold?: string | number
|
|
31
|
+
recommendations?: boolean
|
|
32
|
+
topModules?: number
|
|
33
|
+
parseImports?: boolean
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
collectBundleStats,
|
|
37
|
+
formatBytes,
|
|
38
|
+
parseSize,
|
|
39
|
+
percentage,
|
|
40
|
+
type ModuleInfo,
|
|
41
|
+
type ModuleType,
|
|
42
|
+
type ChunkInfo,
|
|
43
|
+
type DuplicateModule,
|
|
44
|
+
type BundleStats,
|
|
45
|
+
type CollectorOptions,
|
|
46
|
+
} from './collector';
|
|
47
|
+
export {
|
|
48
|
+
generateReport,
|
|
49
|
+
analyzeBundle,
|
|
50
|
+
getModuleRecommendation,
|
|
51
|
+
type ReportOptions,
|
|
52
|
+
type AnalysisResult,
|
|
53
|
+
type AnalysisIssue,
|
|
54
|
+
type Recommendation,
|
|
55
|
+
} from './report';
|
|
56
|
+
export {
|
|
57
|
+
generateTreemap,
|
|
58
|
+
openInBrowser,
|
|
59
|
+
type TreemapOptions,
|
|
60
|
+
} from './treemap';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BundleStats } from './collector';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a report from bundle statistics
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateReport(stats: BundleStats, options: ReportOptions): string;
|
|
6
|
+
/**
|
|
7
|
+
* Analyze bundle for issues and recommendations
|
|
8
|
+
*/
|
|
9
|
+
export declare function analyzeBundle(stats: BundleStats, options: ReportOptions): AnalysisResult;
|
|
10
|
+
/**
|
|
11
|
+
* Get recommendations for a specific module
|
|
12
|
+
*/
|
|
13
|
+
export declare function getModuleRecommendation(modulePath: string): Recommendation | null;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Types
|
|
16
|
+
// ============================================================================
|
|
17
|
+
export declare interface ReportOptions {
|
|
18
|
+
format: 'text' | 'json' | 'markdown'
|
|
19
|
+
threshold?: number
|
|
20
|
+
recommendations?: boolean
|
|
21
|
+
topModules?: number
|
|
22
|
+
showGzip?: boolean
|
|
23
|
+
}
|
|
24
|
+
export declare interface AnalysisResult {
|
|
25
|
+
score: number
|
|
26
|
+
issues: AnalysisIssue[]
|
|
27
|
+
recommendations: Recommendation[]
|
|
28
|
+
}
|
|
29
|
+
export declare interface AnalysisIssue {
|
|
30
|
+
severity: 'error' | 'warning' | 'info'
|
|
31
|
+
message: string
|
|
32
|
+
details?: string
|
|
33
|
+
}
|
|
34
|
+
export declare interface Recommendation {
|
|
35
|
+
title: string
|
|
36
|
+
description: string
|
|
37
|
+
impact: 'high' | 'medium' | 'low'
|
|
38
|
+
effort: 'low' | 'medium' | 'high'
|
|
39
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BundleStats } from './collector';
|
|
2
|
+
/**
|
|
3
|
+
* Generate interactive HTML treemap
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateTreemap(stats: BundleStats, options?: TreemapOptions): string;
|
|
6
|
+
/**
|
|
7
|
+
* Open URL in default browser
|
|
8
|
+
*/
|
|
9
|
+
export declare function openInBrowser(filePath: string): void;
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Types
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export declare interface TreemapOptions {
|
|
14
|
+
output?: string
|
|
15
|
+
open?: boolean
|
|
16
|
+
title?: string
|
|
17
|
+
gzip?: boolean
|
|
18
|
+
colorScheme?: 'default' | 'pastel' | 'monochrome'
|
|
19
|
+
}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import v from"fs";import H from"path";import{gzipSync as z}from"zlib";import{createHash as g}from"crypto";var D={".js":"js",".mjs":"js",".cjs":"js",".ts":"js",".jsx":"js",".tsx":"js",".css":"css",".scss":"css",".sass":"css",".less":"css",".html":"html",".htm":"html",".png":"image",".jpg":"image",".jpeg":"image",".gif":"image",".svg":"image",".webp":"image",".avif":"image",".ico":"image",".woff":"font",".woff2":"font",".ttf":"font",".eot":"font",".otf":"font"},b=[/node_modules/,/vendor/,/bower_components/,/\.min\./],B=[/index\.(js|ts|html)$/,/main\.(js|ts)$/,/app\.(js|ts)$/,/entry\.(js|ts)$/];async function L(Z,$={}){let{includeSourceMaps:X=!1,parseImports:j=!0,detectDuplicates:U=!0,topModulesCount:Q=20}=$;if(!v.existsSync(Z))throw Error(`Build directory not found: ${Z}`);if(!v.statSync(Z).isDirectory())throw Error(`Not a directory: ${Z}`);let K=await k(Z,X),J=[],F=[];for(let A of K)try{let O=await f(A,Z,j);J.push(O)}catch(O){F.push(`Failed to process ${A}: ${O}`)}let Y=c(J,Z),V=J.reduce((A,O)=>A+O.size,0),_=J.reduce((A,O)=>A+O.gzipSize,0),w=m(J),G=U?p(J):[],C=[...J].sort((A,O)=>O.size-A.size).slice(0,Q);return{timestamp:Date.now(),buildDir:H.resolve(Z),chunks:Y,totalSize:V,totalGzipSize:_,moduleCount:J.length,duplicates:G,byType:w,largestModules:C,warnings:F}}async function k(Z,$){let X=[];async function j(U){let Q=await v.promises.readdir(U,{withFileTypes:!0});for(let q of Q){let K=H.join(U,q.name);if(q.isDirectory()){if(!q.name.startsWith(".")&&q.name!=="node_modules")await j(K)}else if(q.isFile()){if(!$&&q.name.endsWith(".map"))continue;X.push(K)}}}return await j(Z),X}async function f(Z,$,X){let j=await v.promises.readFile(Z),U=H.relative($,Z),Q=H.extname(Z).toLowerCase(),q=j.length,K=y(j),J=h(j,Q),F=g("md5").update(j).digest("hex").slice(0,8),Y=D[Q]||"other",V=[];if(X&&Y==="js")V.push(...d(j.toString("utf-8")));return{id:U,path:U,size:q,gzipSize:K,parsedSize:J,extension:Q,type:Y,imports:V,importedBy:[],hash:F}}function y(Z){try{let $=z(Z,{level:9}).length;return Math.min($,Z.length)}catch{return Z.length}}function h(Z,$){if($.includes(".min.")||Z.length<1000)return Z.length;let j=D[$];if(j==="js")return Math.round(Z.length*0.6);if(j==="css")return Math.round(Z.length*0.7);return Z.length}function d(Z){let $=[],X=/import\s+(?:[\w*{}\s,]+\s+from\s+)?['"]([^'"]+)['"]/g,j;while((j=X.exec(Z))!==null)$.push(j[1]);let U=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;while((j=U.exec(Z))!==null)$.push(j[1]);let Q=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;while((j=Q.exec(Z))!==null)$.push(j[1]);return[...new Set($)]}function c(Z,$){let X=new Map;for(let U of Z){let Q=U.path.split(H.sep),q;if(Q.length===1)q=H.basename(U.path,U.extension);else q=Q[0];let K=X.get(q)||[];K.push(U),X.set(q,K)}let j=[];for(let[U,Q]of X){let q=Q.reduce((Y,V)=>Y+V.size,0),K=Q.reduce((Y,V)=>Y+V.gzipSize,0),J=Q.some((Y)=>B.some((V)=>V.test(Y.path))),F=Q.some((Y)=>b.some((V)=>V.test(Y.path)));j.push({name:U,files:Q.map((Y)=>Y.path),modules:Q,size:q,gzipSize:K,isEntry:J,isVendor:F})}return j.sort((U,Q)=>Q.size-U.size)}function m(Z){let $={js:{count:0,size:0,gzipSize:0},css:{count:0,size:0,gzipSize:0},html:{count:0,size:0,gzipSize:0},image:{count:0,size:0,gzipSize:0},font:{count:0,size:0,gzipSize:0},other:{count:0,size:0,gzipSize:0}};for(let X of Z)$[X.type].count++,$[X.type].size+=X.size,$[X.type].gzipSize+=X.gzipSize;return $}function p(Z){let $=new Map;for(let j of Z){let U=$.get(j.hash)||[];U.push(j),$.set(j.hash,U)}let X=[];for(let[,j]of $)if(j.length>1){let U=j[0];X.push({path:U.path,count:j.length,wastedBytes:U.size*(j.length-1),locations:j.map((Q)=>Q.path)})}return X.sort((j,U)=>U.wastedBytes-j.wastedBytes)}function W(Z){if(Z<1024)return`${Z} B`;if(Z<1048576)return`${(Z/1024).toFixed(2)} KB`;return`${(Z/1048576).toFixed(2)} MB`}function I(Z){let $=Z.match(/^([\d.]+)\s*(B|KB|MB|GB)?$/i);if(!$)return 0;let X=Number.parseFloat($[1]);switch(($[2]||"B").toUpperCase()){case"KB":return X*1024;case"MB":return X*1024*1024;case"GB":return X*1024*1024*1024;default:return X}}function E(Z,$){if($===0)return"0%";return`${(Z/$*100).toFixed(1)}%`}function x(Z,$){switch($.format){case"json":return u(Z,$);case"markdown":return l(Z,$);case"text":default:return r(Z,$)}}function u(Z,$){let X=N(Z,$);return JSON.stringify({timestamp:Z.timestamp,buildDir:Z.buildDir,summary:{totalSize:Z.totalSize,totalSizeFormatted:W(Z.totalSize),totalGzipSize:Z.totalGzipSize,totalGzipSizeFormatted:W(Z.totalGzipSize),moduleCount:Z.moduleCount,chunkCount:Z.chunks.length,duplicateCount:Z.duplicates.length},byType:Object.fromEntries(Object.entries(Z.byType).map(([j,U])=>[j,{...U,sizeFormatted:W(U.size),gzipSizeFormatted:W(U.gzipSize)}])),chunks:Z.chunks.map((j)=>({name:j.name,size:j.size,sizeFormatted:W(j.size),gzipSize:j.gzipSize,gzipSizeFormatted:W(j.gzipSize),moduleCount:j.modules.length,isEntry:j.isEntry,isVendor:j.isVendor})),largestModules:Z.largestModules.slice(0,$.topModules||10).map((j)=>({path:j.path,size:j.size,sizeFormatted:W(j.size),gzipSize:j.gzipSize,gzipSizeFormatted:W(j.gzipSize),type:j.type})),duplicates:Z.duplicates,analysis:X,warnings:Z.warnings},null,2)}function r(Z,$){let X=[],j=$.showGzip!==!1;if(X.push(""),X.push("Bundle Analysis Report"),X.push("\u2550".repeat(50)),X.push(""),X.push("Summary"),X.push("\u2500".repeat(50)),j)X.push(`Total Size: ${W(Z.totalSize)} (${W(Z.totalGzipSize)} gzip)`);else X.push(`Total Size: ${W(Z.totalSize)}`);if(X.push(`Modules: ${Z.moduleCount}`),X.push(`Chunks: ${Z.chunks.length}`),Z.duplicates.length>0)X.push(`Duplicates: ${Z.duplicates.length}`);if(X.push(""),$.threshold&&Z.totalSize>$.threshold)X.push(`\u26A0\uFE0F Bundle exceeds threshold of ${W($.threshold)}!`),X.push("");X.push("Size by Type"),X.push("\u2500".repeat(50));let U=["js","css","html","image","font","other"];for(let q of U){let K=Z.byType[q];if(K.count>0){let J=E(K.size,Z.totalSize),F=j?` (${W(K.gzipSize)} gzip)`:"";X.push(` ${q.padEnd(8)} ${W(K.size).padStart(12)}${F} ${J.padStart(6)} (${K.count} files)`)}}X.push(""),X.push("Chunks"),X.push("\u2500".repeat(50));for(let q of Z.chunks.slice(0,10)){let K=[];if(q.isEntry)K.push("entry");if(q.isVendor)K.push("vendor");let J=K.length>0?` [${K.join(", ")}]`:"",F=j?` (${W(q.gzipSize)} gzip)`:"";X.push(` ${q.name.padEnd(20)} ${W(q.size).padStart(12)}${F}${J}`)}if(Z.chunks.length>10)X.push(` ... and ${Z.chunks.length-10} more chunks`);X.push("");let Q=$.topModules||10;X.push(`Largest Modules (Top ${Q})`),X.push("\u2500".repeat(50));for(let q=0;q<Math.min(Q,Z.largestModules.length);q++){let K=Z.largestModules[q],J=j?` (${W(K.gzipSize)} gzip)`:"";X.push(` ${(q+1).toString().padStart(2)}. ${K.path}`),X.push(` ${W(K.size)}${J}`)}if(X.push(""),Z.duplicates.length>0){X.push("Duplicate Modules"),X.push("\u2500".repeat(50));for(let q of Z.duplicates.slice(0,5))X.push(` ${q.path}`),X.push(` ${q.count} copies, wasting ${W(q.wastedBytes)}`);if(Z.duplicates.length>5)X.push(` ... and ${Z.duplicates.length-5} more duplicates`);X.push("")}if($.recommendations!==!1){let q=N(Z,$);if(q.recommendations.length>0){X.push("Recommendations"),X.push("\u2500".repeat(50));for(let K of q.recommendations.slice(0,5)){let J=K.impact==="high"?"\u26A1":K.impact==="medium"?"\uD83D\uDCCA":"\uD83D\uDCA1";X.push(` ${J} ${K.title}`),X.push(` ${K.description}`)}X.push("")}}if(Z.warnings.length>0){X.push("Warnings"),X.push("\u2500".repeat(50));for(let q of Z.warnings)X.push(` \u26A0\uFE0F ${q}`);X.push("")}return X.join(`
|
|
3
|
+
`)}function l(Z,$){let X=[],j=$.showGzip!==!1;if(X.push("# Bundle Analysis Report"),X.push(""),X.push(`Generated: ${new Date(Z.timestamp).toISOString()}`),X.push(""),X.push("## Summary"),X.push(""),X.push("| Metric | Value |"),X.push("|--------|-------|"),X.push(`| Total Size | ${W(Z.totalSize)} |`),j)X.push(`| Gzip Size | ${W(Z.totalGzipSize)} |`);X.push(`| Modules | ${Z.moduleCount} |`),X.push(`| Chunks | ${Z.chunks.length} |`),X.push(`| Duplicates | ${Z.duplicates.length} |`),X.push(""),X.push("## Size by Type"),X.push(""),X.push("| Type | Size | Gzip | % | Files |"),X.push("|------|------|------|---|-------|");let U=["js","css","html","image","font","other"];for(let q of U){let K=Z.byType[q];if(K.count>0)X.push(`| ${q} | ${W(K.size)} | ${W(K.gzipSize)} | ${E(K.size,Z.totalSize)} | ${K.count} |`)}X.push(""),X.push("## Chunks"),X.push(""),X.push("| Name | Size | Gzip | Modules | Type |"),X.push("|------|------|------|---------|------|");for(let q of Z.chunks.slice(0,15)){let K=q.isEntry?"Entry":q.isVendor?"Vendor":"-";X.push(`| ${q.name} | ${W(q.size)} | ${W(q.gzipSize)} | ${q.modules.length} | ${K} |`)}X.push("");let Q=$.topModules||10;X.push(`## Largest Modules (Top ${Q})`),X.push(""),X.push("| # | Path | Size | Gzip |"),X.push("|---|------|------|------|");for(let q=0;q<Math.min(Q,Z.largestModules.length);q++){let K=Z.largestModules[q];X.push(`| ${q+1} | \`${K.path}\` | ${W(K.size)} | ${W(K.gzipSize)} |`)}if(X.push(""),Z.duplicates.length>0){X.push("## Duplicates"),X.push(""),X.push("| Path | Copies | Wasted |"),X.push("|------|--------|--------|");for(let q of Z.duplicates.slice(0,10))X.push(`| \`${q.path}\` | ${q.count} | ${W(q.wastedBytes)} |`);X.push("")}if($.recommendations!==!1){let q=N(Z,$);if(q.recommendations.length>0){X.push("## Recommendations"),X.push("");for(let K of q.recommendations)X.push(`### ${K.title}`),X.push(""),X.push(K.description),X.push(""),X.push(`- **Impact:** ${K.impact}`),X.push(`- **Effort:** ${K.effort}`),X.push("")}}return X.join(`
|
|
4
|
+
`)}function N(Z,$){let X=[],j=[];if($.threshold&&Z.totalSize>$.threshold)X.push({severity:"error",message:`Bundle size (${W(Z.totalSize)}) exceeds threshold (${W($.threshold)})`});if(Z.totalSize>1048576)X.push({severity:"warning",message:`Bundle is over 1MB (${W(Z.totalSize)})`,details:"Large bundles can significantly impact load time"});if(Z.duplicates.length>0){let K=Z.duplicates.reduce((J,F)=>J+F.wastedBytes,0);X.push({severity:"warning",message:`${Z.duplicates.length} duplicate modules found, wasting ${W(K)}`}),j.push({title:"Remove Duplicate Modules",description:"Consider using import aliases or ensuring consistent package versions to eliminate duplicates.",impact:"medium",effort:"low"})}if(Z.byType.js.size/Z.totalSize>0.8&&Z.totalSize>512000)j.push({title:"Code Splitting",description:"Over 80% of your bundle is JavaScript. Consider splitting code by route or feature.",impact:"high",effort:"medium"});let Q=Z.largestModules.filter((K)=>K.size>102400);if(Q.length>0){X.push({severity:"info",message:`${Q.length} modules are over 100KB`});for(let K of Q){if(K.path.includes("lodash")&&!K.path.includes("lodash-es"))j.push({title:"Use lodash-es instead of lodash",description:"lodash-es supports tree-shaking and can significantly reduce bundle size.",impact:"high",effort:"low"});if(K.path.includes("moment"))j.push({title:"Replace moment.js",description:"Consider using date-fns or dayjs for smaller date handling libraries.",impact:"high",effort:"medium"})}}if(Z.byType.image.size>512000)j.push({title:"Optimize Images",description:`Images account for ${W(Z.byType.image.size)}. Consider using WebP/AVIF formats and responsive images.`,impact:"high",effort:"low"});let q=100;if(Z.totalSize>1048576)q-=20;else if(Z.totalSize>512000)q-=10;if(q-=Math.min(20,Z.duplicates.length*2),q-=Math.min(15,Q.length*3),$.threshold&&Z.totalSize>$.threshold)q-=25;return{score:Math.max(0,q),issues:X,recommendations:j}}var i={lodash:{alternative:"lodash-es or individual imports",savings:"~70%"},moment:{alternative:"date-fns or dayjs",savings:"~90%"},"chart.js":{alternative:"chart.js with tree-shaking",savings:"~50%"},"highlight.js":{alternative:"Selective language imports",savings:"~80%"},fontawesome:{alternative:"Individual icon imports",savings:"~90%"},"material-ui":{alternative:"Named imports from @mui/*",savings:"~60%"}};function n(Z){for(let[$,X]of Object.entries(i))if(Z.includes($))return{title:`Optimize ${$}`,description:`Consider using ${X.alternative}. Potential savings: ${X.savings}`,impact:"high",effort:"low"};return null}var o={default:{js:"#f7df1e",css:"#264de4",html:"#e34c26",image:"#4caf50",font:"#9c27b0",other:"#607d8b",vendor:"#ff5722"},pastel:{js:"#fff3b0",css:"#b0d4ff",html:"#ffb0b0",image:"#b0ffb0",font:"#e0b0ff",other:"#d0d0d0",vendor:"#ffcfb0"},monochrome:{js:"#333333",css:"#555555",html:"#777777",image:"#999999",font:"#bbbbbb",other:"#dddddd",vendor:"#444444"}};function R(Z,$={}){let{title:X="Bundle Analysis",gzip:j=!0,colorScheme:U="default"}=$,Q=o[U],q=a(Z),K=JSON.stringify(q);return`<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
+
<title>${M(X)}</title>
|
|
10
|
+
<style>
|
|
11
|
+
* {
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
margin: 0;
|
|
14
|
+
padding: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
body {
|
|
18
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
19
|
+
background: #1a1a2e;
|
|
20
|
+
color: #eee;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.header {
|
|
25
|
+
background: #16213e;
|
|
26
|
+
padding: 1rem 2rem;
|
|
27
|
+
display: flex;
|
|
28
|
+
justify-content: space-between;
|
|
29
|
+
align-items: center;
|
|
30
|
+
border-bottom: 1px solid #0f3460;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.header h1 {
|
|
34
|
+
font-size: 1.5rem;
|
|
35
|
+
font-weight: 500;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.stats {
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 2rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.stat {
|
|
44
|
+
text-align: center;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.stat-value {
|
|
48
|
+
font-size: 1.25rem;
|
|
49
|
+
font-weight: bold;
|
|
50
|
+
color: #e94560;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.stat-label {
|
|
54
|
+
font-size: 0.75rem;
|
|
55
|
+
color: #888;
|
|
56
|
+
text-transform: uppercase;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.controls {
|
|
60
|
+
background: #16213e;
|
|
61
|
+
padding: 0.75rem 2rem;
|
|
62
|
+
display: flex;
|
|
63
|
+
gap: 1rem;
|
|
64
|
+
align-items: center;
|
|
65
|
+
border-bottom: 1px solid #0f3460;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.controls label {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: 0.5rem;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.controls input[type="checkbox"] {
|
|
76
|
+
width: 1rem;
|
|
77
|
+
height: 1rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.search-box {
|
|
81
|
+
flex: 1;
|
|
82
|
+
max-width: 300px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.search-box input {
|
|
86
|
+
width: 100%;
|
|
87
|
+
padding: 0.5rem 1rem;
|
|
88
|
+
border: 1px solid #0f3460;
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
background: #1a1a2e;
|
|
91
|
+
color: #eee;
|
|
92
|
+
font-size: 0.875rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.search-box input:focus {
|
|
96
|
+
outline: none;
|
|
97
|
+
border-color: #e94560;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.breadcrumb {
|
|
101
|
+
background: #16213e;
|
|
102
|
+
padding: 0.5rem 2rem;
|
|
103
|
+
display: flex;
|
|
104
|
+
gap: 0.5rem;
|
|
105
|
+
align-items: center;
|
|
106
|
+
font-size: 0.875rem;
|
|
107
|
+
border-bottom: 1px solid #0f3460;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.breadcrumb-item {
|
|
111
|
+
color: #888;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.breadcrumb-item:hover {
|
|
116
|
+
color: #e94560;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.breadcrumb-item.active {
|
|
120
|
+
color: #eee;
|
|
121
|
+
cursor: default;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.breadcrumb-sep {
|
|
125
|
+
color: #444;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#treemap {
|
|
129
|
+
width: 100%;
|
|
130
|
+
height: calc(100vh - 180px);
|
|
131
|
+
min-height: 400px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.tooltip {
|
|
135
|
+
position: fixed;
|
|
136
|
+
background: #16213e;
|
|
137
|
+
border: 1px solid #0f3460;
|
|
138
|
+
border-radius: 4px;
|
|
139
|
+
padding: 0.75rem 1rem;
|
|
140
|
+
pointer-events: none;
|
|
141
|
+
z-index: 1000;
|
|
142
|
+
max-width: 400px;
|
|
143
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.tooltip-title {
|
|
147
|
+
font-weight: bold;
|
|
148
|
+
margin-bottom: 0.5rem;
|
|
149
|
+
word-break: break-all;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.tooltip-row {
|
|
153
|
+
display: flex;
|
|
154
|
+
justify-content: space-between;
|
|
155
|
+
gap: 2rem;
|
|
156
|
+
font-size: 0.875rem;
|
|
157
|
+
color: #888;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.tooltip-row span:last-child {
|
|
161
|
+
color: #eee;
|
|
162
|
+
font-weight: 500;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.legend {
|
|
166
|
+
position: fixed;
|
|
167
|
+
bottom: 1rem;
|
|
168
|
+
right: 1rem;
|
|
169
|
+
background: #16213e;
|
|
170
|
+
border: 1px solid #0f3460;
|
|
171
|
+
border-radius: 4px;
|
|
172
|
+
padding: 0.75rem 1rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.legend-title {
|
|
176
|
+
font-size: 0.75rem;
|
|
177
|
+
color: #888;
|
|
178
|
+
margin-bottom: 0.5rem;
|
|
179
|
+
text-transform: uppercase;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.legend-item {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
gap: 0.5rem;
|
|
186
|
+
font-size: 0.75rem;
|
|
187
|
+
margin-bottom: 0.25rem;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.legend-color {
|
|
191
|
+
width: 12px;
|
|
192
|
+
height: 12px;
|
|
193
|
+
border-radius: 2px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.node {
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
transition: opacity 0.2s;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.node:hover {
|
|
202
|
+
opacity: 0.8;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.node-label {
|
|
206
|
+
font-size: 11px;
|
|
207
|
+
fill: #000;
|
|
208
|
+
pointer-events: none;
|
|
209
|
+
text-anchor: middle;
|
|
210
|
+
}
|
|
211
|
+
</style>
|
|
212
|
+
</head>
|
|
213
|
+
<body>
|
|
214
|
+
<div class="header">
|
|
215
|
+
<h1>${M(X)}</h1>
|
|
216
|
+
<div class="stats">
|
|
217
|
+
<div class="stat">
|
|
218
|
+
<div class="stat-value" id="total-size">${W(Z.totalSize)}</div>
|
|
219
|
+
<div class="stat-label">Total Size</div>
|
|
220
|
+
</div>
|
|
221
|
+
<div class="stat">
|
|
222
|
+
<div class="stat-value" id="gzip-size">${W(Z.totalGzipSize)}</div>
|
|
223
|
+
<div class="stat-label">Gzip Size</div>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="stat">
|
|
226
|
+
<div class="stat-value">${Z.moduleCount}</div>
|
|
227
|
+
<div class="stat-label">Modules</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div class="stat">
|
|
230
|
+
<div class="stat-value">${Z.chunks.length}</div>
|
|
231
|
+
<div class="stat-label">Chunks</div>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
|
|
236
|
+
<div class="controls">
|
|
237
|
+
<div class="search-box">
|
|
238
|
+
<input type="text" id="search" placeholder="Search modules...">
|
|
239
|
+
</div>
|
|
240
|
+
<label>
|
|
241
|
+
<input type="checkbox" id="show-gzip" ${j?"checked":""}>
|
|
242
|
+
Show Gzip Size
|
|
243
|
+
</label>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<div class="breadcrumb" id="breadcrumb">
|
|
247
|
+
<span class="breadcrumb-item active">root</span>
|
|
248
|
+
</div>
|
|
249
|
+
|
|
250
|
+
<div id="treemap"></div>
|
|
251
|
+
|
|
252
|
+
<div class="tooltip" id="tooltip" style="display: none;"></div>
|
|
253
|
+
|
|
254
|
+
<div class="legend">
|
|
255
|
+
<div class="legend-title">File Types</div>
|
|
256
|
+
<div class="legend-item">
|
|
257
|
+
<div class="legend-color" style="background: ${Q.js}"></div>
|
|
258
|
+
<span>JavaScript</span>
|
|
259
|
+
</div>
|
|
260
|
+
<div class="legend-item">
|
|
261
|
+
<div class="legend-color" style="background: ${Q.css}"></div>
|
|
262
|
+
<span>CSS</span>
|
|
263
|
+
</div>
|
|
264
|
+
<div class="legend-item">
|
|
265
|
+
<div class="legend-color" style="background: ${Q.html}"></div>
|
|
266
|
+
<span>HTML</span>
|
|
267
|
+
</div>
|
|
268
|
+
<div class="legend-item">
|
|
269
|
+
<div class="legend-color" style="background: ${Q.image}"></div>
|
|
270
|
+
<span>Images</span>
|
|
271
|
+
</div>
|
|
272
|
+
<div class="legend-item">
|
|
273
|
+
<div class="legend-color" style="background: ${Q.font}"></div>
|
|
274
|
+
<span>Fonts</span>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="legend-item">
|
|
277
|
+
<div class="legend-color" style="background: ${Q.other}"></div>
|
|
278
|
+
<span>Other</span>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
283
|
+
<script>
|
|
284
|
+
const data = ${K};
|
|
285
|
+
const colors = ${JSON.stringify(Q)};
|
|
286
|
+
|
|
287
|
+
let showGzip = ${j};
|
|
288
|
+
let currentRoot = data;
|
|
289
|
+
let searchTerm = '';
|
|
290
|
+
|
|
291
|
+
const container = document.getElementById('treemap');
|
|
292
|
+
const tooltip = document.getElementById('tooltip');
|
|
293
|
+
const breadcrumb = document.getElementById('breadcrumb');
|
|
294
|
+
const searchInput = document.getElementById('search');
|
|
295
|
+
const showGzipCheckbox = document.getElementById('show-gzip');
|
|
296
|
+
|
|
297
|
+
function formatSize(bytes) {
|
|
298
|
+
if (bytes < 1024) return bytes + ' B';
|
|
299
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
|
|
300
|
+
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function getColor(d) {
|
|
304
|
+
if (d.data.type) {
|
|
305
|
+
return colors[d.data.type] || colors.other;
|
|
306
|
+
}
|
|
307
|
+
if (d.data.name.includes('node_modules') || d.data.name.includes('vendor')) {
|
|
308
|
+
return colors.vendor;
|
|
309
|
+
}
|
|
310
|
+
return colors.other;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function getSizeValue(d) {
|
|
314
|
+
return showGzip ? d.data.gzipSize : d.data.size;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function render() {
|
|
318
|
+
container.innerHTML = '';
|
|
319
|
+
|
|
320
|
+
const width = container.clientWidth;
|
|
321
|
+
const height = container.clientHeight;
|
|
322
|
+
|
|
323
|
+
const hierarchy = d3.hierarchy(currentRoot)
|
|
324
|
+
.sum(d => {
|
|
325
|
+
if (searchTerm && d.name && !d.name.toLowerCase().includes(searchTerm.toLowerCase())) {
|
|
326
|
+
return 0;
|
|
327
|
+
}
|
|
328
|
+
return d.children ? 0 : getSizeValue({ data: d });
|
|
329
|
+
})
|
|
330
|
+
.sort((a, b) => getSizeValue(b) - getSizeValue(a));
|
|
331
|
+
|
|
332
|
+
const treemap = d3.treemap()
|
|
333
|
+
.size([width, height])
|
|
334
|
+
.paddingOuter(3)
|
|
335
|
+
.paddingTop(19)
|
|
336
|
+
.paddingInner(1)
|
|
337
|
+
.round(true);
|
|
338
|
+
|
|
339
|
+
const root = treemap(hierarchy);
|
|
340
|
+
|
|
341
|
+
const svg = d3.select(container)
|
|
342
|
+
.append('svg')
|
|
343
|
+
.attr('width', width)
|
|
344
|
+
.attr('height', height);
|
|
345
|
+
|
|
346
|
+
const node = svg.selectAll('g')
|
|
347
|
+
.data(root.descendants().filter(d => d.depth > 0))
|
|
348
|
+
.join('g')
|
|
349
|
+
.attr('transform', d => \`translate(\${d.x0},\${d.y0})\`);
|
|
350
|
+
|
|
351
|
+
node.append('rect')
|
|
352
|
+
.attr('class', 'node')
|
|
353
|
+
.attr('width', d => Math.max(0, d.x1 - d.x0))
|
|
354
|
+
.attr('height', d => Math.max(0, d.y1 - d.y0))
|
|
355
|
+
.attr('fill', d => getColor(d))
|
|
356
|
+
.attr('stroke', '#1a1a2e')
|
|
357
|
+
.attr('stroke-width', 1)
|
|
358
|
+
.on('click', (event, d) => {
|
|
359
|
+
if (d.children) {
|
|
360
|
+
zoomIn(d.data);
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
.on('mouseover', (event, d) => showTooltip(event, d))
|
|
364
|
+
.on('mousemove', (event) => moveTooltip(event))
|
|
365
|
+
.on('mouseout', hideTooltip);
|
|
366
|
+
|
|
367
|
+
node.append('text')
|
|
368
|
+
.attr('class', 'node-label')
|
|
369
|
+
.attr('x', d => (d.x1 - d.x0) / 2)
|
|
370
|
+
.attr('y', d => (d.y1 - d.y0) / 2 + 4)
|
|
371
|
+
.text(d => {
|
|
372
|
+
const width = d.x1 - d.x0;
|
|
373
|
+
const height = d.y1 - d.y0;
|
|
374
|
+
if (width < 40 || height < 20) return '';
|
|
375
|
+
const name = d.data.name;
|
|
376
|
+
const maxLen = Math.floor(width / 7);
|
|
377
|
+
return name.length > maxLen ? name.slice(0, maxLen - 2) + '..' : name;
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Group headers
|
|
381
|
+
node.filter(d => d.children)
|
|
382
|
+
.append('text')
|
|
383
|
+
.attr('x', 4)
|
|
384
|
+
.attr('y', 14)
|
|
385
|
+
.attr('fill', '#000')
|
|
386
|
+
.attr('font-size', '12px')
|
|
387
|
+
.attr('font-weight', 'bold')
|
|
388
|
+
.text(d => {
|
|
389
|
+
const width = d.x1 - d.x0;
|
|
390
|
+
const name = d.data.name;
|
|
391
|
+
const maxLen = Math.floor(width / 7);
|
|
392
|
+
return name.length > maxLen ? name.slice(0, maxLen - 2) + '..' : name;
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function showTooltip(event, d) {
|
|
397
|
+
const size = d.data.size || d.value;
|
|
398
|
+
const gzipSize = d.data.gzipSize || Math.round(size * 0.3);
|
|
399
|
+
const path = d.data.path || d.data.name;
|
|
400
|
+
|
|
401
|
+
tooltip.innerHTML = \`
|
|
402
|
+
<div class="tooltip-title">\${path}</div>
|
|
403
|
+
<div class="tooltip-row">
|
|
404
|
+
<span>Size</span>
|
|
405
|
+
<span>\${formatSize(size)}</span>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="tooltip-row">
|
|
408
|
+
<span>Gzip</span>
|
|
409
|
+
<span>\${formatSize(gzipSize)}</span>
|
|
410
|
+
</div>
|
|
411
|
+
\${d.data.type ? \`<div class="tooltip-row"><span>Type</span><span>\${d.data.type}</span></div>\` : ''}
|
|
412
|
+
\${d.children ? \`<div class="tooltip-row"><span>Children</span><span>\${d.children.length}</span></div>\` : ''}
|
|
413
|
+
\`;
|
|
414
|
+
tooltip.style.display = 'block';
|
|
415
|
+
moveTooltip(event);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function moveTooltip(event) {
|
|
419
|
+
const x = event.clientX + 10;
|
|
420
|
+
const y = event.clientY + 10;
|
|
421
|
+
tooltip.style.left = x + 'px';
|
|
422
|
+
tooltip.style.top = y + 'px';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function hideTooltip() {
|
|
426
|
+
tooltip.style.display = 'none';
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function zoomIn(node) {
|
|
430
|
+
currentRoot = node;
|
|
431
|
+
updateBreadcrumb();
|
|
432
|
+
render();
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function zoomOut(index) {
|
|
436
|
+
let node = data;
|
|
437
|
+
const parts = getBreadcrumbParts();
|
|
438
|
+
for (let i = 1; i <= index; i++) {
|
|
439
|
+
const child = node.children?.find(c => c.name === parts[i]);
|
|
440
|
+
if (child) node = child;
|
|
441
|
+
}
|
|
442
|
+
currentRoot = node;
|
|
443
|
+
updateBreadcrumb();
|
|
444
|
+
render();
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function getBreadcrumbParts() {
|
|
448
|
+
const parts = ['root'];
|
|
449
|
+
let node = currentRoot;
|
|
450
|
+
const path = [];
|
|
451
|
+
|
|
452
|
+
function findPath(current, target, currentPath) {
|
|
453
|
+
if (current === target) {
|
|
454
|
+
path.push(...currentPath);
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
if (current.children) {
|
|
458
|
+
for (const child of current.children) {
|
|
459
|
+
if (findPath(child, target, [...currentPath, child.name])) {
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (currentRoot !== data) {
|
|
468
|
+
findPath(data, currentRoot, []);
|
|
469
|
+
parts.push(...path);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return parts;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function updateBreadcrumb() {
|
|
476
|
+
const parts = getBreadcrumbParts();
|
|
477
|
+
breadcrumb.innerHTML = parts.map((part, i) => {
|
|
478
|
+
const isLast = i === parts.length - 1;
|
|
479
|
+
const sep = i > 0 ? '<span class="breadcrumb-sep">/</span>' : '';
|
|
480
|
+
return \`\${sep}<span class="breadcrumb-item \${isLast ? 'active' : ''}" onclick="zoomOut(\${i})">\${part}</span>\`;
|
|
481
|
+
}).join('');
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
searchInput.addEventListener('input', (e) => {
|
|
485
|
+
searchTerm = e.target.value;
|
|
486
|
+
render();
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
showGzipCheckbox.addEventListener('change', (e) => {
|
|
490
|
+
showGzip = e.target.checked;
|
|
491
|
+
render();
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
window.addEventListener('resize', render);
|
|
495
|
+
|
|
496
|
+
render();
|
|
497
|
+
</script>
|
|
498
|
+
</body>
|
|
499
|
+
</html>`}function a(Z){let $={name:"root",size:Z.totalSize,gzipSize:Z.totalGzipSize,children:[]};for(let X of Z.chunks){let j={name:X.name,size:X.size,gzipSize:X.gzipSize,children:[]};for(let U of X.modules)e(j,U);$.children.push(j)}return $}function e(Z,$){let X=$.path.split("/"),j=Z;for(let Q=0;Q<X.length-1;Q++){let q=X[Q],K=j.children?.find((J)=>J.name===q);if(!K){if(K={name:q,size:0,gzipSize:0,children:[]},!j.children)j.children=[];j.children.push(K)}j=K}let U=X[X.length-1];if(!j.children)j.children=[];j.children.push({name:U,path:$.path,size:$.size,gzipSize:$.gzipSize,type:$.type}),s(Z,$.size,$.gzipSize)}function s(Z,$,X){}function M(Z){return Z.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function T(Z){let $=process.platform,X=$==="darwin"?"open":$==="win32"?"start":"xdg-open";Bun.spawn([X,Z],{stdio:["ignore","ignore","ignore"]})}import P from"fs";import S from"path";async function CX(Z={}){let{directory:$="dist",output:X,format:j="html",open:U=!0,gzip:Q=!0,threshold:q,recommendations:K=!0,topModules:J=20,parseImports:F=!0}=Z,V=await L($,{parseImports:F,detectDuplicates:!0,topModulesCount:J}),_=q?typeof q==="string"?I(q):q:void 0,w=_?V.totalSize>_:!1,G,C;if(j==="html"){let A={title:`Bundle Analysis - ${S.basename(S.resolve($))}`,gzip:Q};if(G=R(V,A),C=X||S.join($,"bundle-report.html"),await P.promises.writeFile(C,G),U)T(C)}else if(G=x(V,{format:j,threshold:_,recommendations:K,topModules:J,showGzip:Q}),X)C=X,await P.promises.writeFile(C,G);return{stats:V,report:G,outputPath:C,exceedsThreshold:w}}async function GX(Z){let $=await L(Z,{parseImports:!1,detectDuplicates:!1,topModulesCount:0});return{totalSize:$.totalSize,totalSizeFormatted:W($.totalSize),gzipSize:$.totalGzipSize,gzipSizeFormatted:W($.totalGzipSize),moduleCount:$.moduleCount,chunkCount:$.chunks.length}}export{E as percentage,I as parseSize,T as openInBrowser,n as getModuleRecommendation,GX as getBundleSummary,R as generateTreemap,x as generateReport,W as formatBytes,L as collectBundleStats,N as analyzeBundle,CX as analyze};
|
package/dist/caching.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export declare function checkCache(filePath: string, options: StxOptions): Promi
|
|
|
9
9
|
export declare function cacheTemplate(filePath: string, output: string, dependencies: Set<string>, options: StxOptions): Promise<void>;
|
|
10
10
|
/**
|
|
11
11
|
* Create a hash of the file path for cache filenames
|
|
12
|
+
*
|
|
13
|
+
* Uses SHA-1 (fast, collision-resistant enough for cache keys) truncated to
|
|
14
|
+
* CACHE_HASH_LENGTH characters. The truncated hash still provides strong
|
|
15
|
+
* uniqueness guarantees for cache file identification.
|
|
16
|
+
*
|
|
17
|
+
* @param filePath - Absolute path to the template file
|
|
18
|
+
* @returns A 16-character hex string suitable for use as a filename
|
|
12
19
|
*/
|
|
13
20
|
export declare function hashFilePath(filePath: string): string;
|
|
14
21
|
// Memory cache for compiled templates
|