@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.4 → 0.1.6
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/CHANGELOG.md +1 -1
- package/dist/index.d.ts +131 -131
- package/dist/index.esm.js +148 -148
- package/dist/index.js +148 -148
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ui/accessibility-demo.tsx +271 -0
- package/src/components/ui/advanced-component-architecture-demo.tsx +916 -0
- package/src/components/ui/advanced-transition-system-demo.tsx +670 -0
- package/src/components/ui/advanced-transition-system.tsx +395 -0
- package/src/components/ui/animation/animated-container.tsx +166 -0
- package/src/components/ui/animation/index.ts +19 -0
- package/src/components/ui/animation/staggered-container.tsx +68 -0
- package/src/components/ui/animation-demo.tsx +250 -0
- package/src/components/ui/badge.tsx +33 -0
- package/src/components/ui/battery-conscious-animation-demo.tsx +568 -0
- package/src/components/ui/border-radius-shadow-demo.tsx +187 -0
- package/src/components/ui/button.tsx +36 -0
- package/src/components/ui/card.tsx +207 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/color-preview.tsx +411 -0
- package/src/components/ui/data-display/chart.tsx +653 -0
- package/src/components/ui/data-display/data-grid-simple.tsx +76 -0
- package/src/components/ui/data-display/data-grid.tsx +680 -0
- package/src/components/ui/data-display/list.tsx +456 -0
- package/src/components/ui/data-display/table.tsx +482 -0
- package/src/components/ui/data-display/timeline.tsx +441 -0
- package/src/components/ui/data-display/tree.tsx +602 -0
- package/src/components/ui/data-display/types.ts +536 -0
- package/src/components/ui/enterprise-mobile-experience-demo.tsx +749 -0
- package/src/components/ui/enterprise-mobile-experience.tsx +464 -0
- package/src/components/ui/feedback/alert.tsx +157 -0
- package/src/components/ui/feedback/progress.tsx +292 -0
- package/src/components/ui/feedback/skeleton.tsx +185 -0
- package/src/components/ui/feedback/toast.tsx +280 -0
- package/src/components/ui/feedback/types.ts +125 -0
- package/src/components/ui/font-preview.tsx +288 -0
- package/src/components/ui/form-demo.tsx +553 -0
- package/src/components/ui/hardware-acceleration-demo.tsx +547 -0
- package/src/components/ui/input.tsx +35 -0
- package/src/components/ui/label.tsx +16 -0
- package/src/components/ui/layout-demo.tsx +367 -0
- package/src/components/ui/layouts/adaptive-layout.tsx +139 -0
- package/src/components/ui/layouts/desktop-layout.tsx +224 -0
- package/src/components/ui/layouts/index.ts +10 -0
- package/src/components/ui/layouts/mobile-layout.tsx +162 -0
- package/src/components/ui/layouts/tablet-layout.tsx +197 -0
- package/src/components/ui/mobile-form-validation.tsx +451 -0
- package/src/components/ui/mobile-input-demo.tsx +201 -0
- package/src/components/ui/mobile-input.tsx +281 -0
- package/src/components/ui/mobile-skeleton-loading-demo.tsx +638 -0
- package/src/components/ui/navigation/breadcrumb.tsx +158 -0
- package/src/components/ui/navigation/index.ts +36 -0
- package/src/components/ui/navigation/menu.tsx +374 -0
- package/src/components/ui/navigation/navigation-demo.tsx +324 -0
- package/src/components/ui/navigation/pagination.tsx +272 -0
- package/src/components/ui/navigation/sidebar.tsx +383 -0
- package/src/components/ui/navigation/stepper.tsx +303 -0
- package/src/components/ui/navigation/tabs.tsx +205 -0
- package/src/components/ui/navigation/types.ts +299 -0
- package/src/components/ui/overlay/backdrop.tsx +81 -0
- package/src/components/ui/overlay/focus-manager.tsx +143 -0
- package/src/components/ui/overlay/index.ts +36 -0
- package/src/components/ui/overlay/modal.tsx +270 -0
- package/src/components/ui/overlay/overlay-manager.tsx +110 -0
- package/src/components/ui/overlay/popover.tsx +462 -0
- package/src/components/ui/overlay/portal.tsx +79 -0
- package/src/components/ui/overlay/tooltip.tsx +303 -0
- package/src/components/ui/overlay/types.ts +196 -0
- package/src/components/ui/performance-demo.tsx +596 -0
- package/src/components/ui/semantic-input-system-demo.tsx +502 -0
- package/src/components/ui/semantic-input-system-demo.tsx.disabled +873 -0
- package/src/components/ui/tablet-layout.tsx +192 -0
- package/src/components/ui/theme-customizer.tsx +386 -0
- package/src/components/ui/theme-preview.tsx +310 -0
- package/src/components/ui/theme-switcher.tsx +264 -0
- package/src/components/ui/theme-toggle.tsx +38 -0
- package/src/components/ui/token-demo.tsx +195 -0
- package/src/components/ui/touch-demo.tsx +462 -0
- package/src/components/ui/touch-friendly-interface-demo.tsx +519 -0
- package/src/components/ui/touch-friendly-interface.tsx +296 -0
- package/src/hooks/index.ts +190 -0
- package/src/hooks/use-accessibility-support.ts +518 -0
- package/src/hooks/use-adaptive-layout.ts +289 -0
- package/src/hooks/use-advanced-patterns.ts +294 -0
- package/src/hooks/use-advanced-transition-system.ts +393 -0
- package/src/hooks/use-animation-profile.ts +288 -0
- package/src/hooks/use-battery-animations.ts +384 -0
- package/src/hooks/use-battery-conscious-loading.ts +475 -0
- package/src/hooks/use-battery-optimization.ts +330 -0
- package/src/hooks/use-battery-status.ts +299 -0
- package/src/hooks/use-component-performance.ts +344 -0
- package/src/hooks/use-device-loading-states.ts +459 -0
- package/src/hooks/use-device.tsx +110 -0
- package/src/hooks/use-enterprise-mobile-experience.ts +488 -0
- package/src/hooks/use-form-feedback.ts +403 -0
- package/src/hooks/use-form-performance.ts +513 -0
- package/src/hooks/use-frame-rate.ts +251 -0
- package/src/hooks/use-gestures.ts +338 -0
- package/src/hooks/use-hardware-acceleration.ts +341 -0
- package/src/hooks/use-input-accessibility.ts +455 -0
- package/src/hooks/use-input-performance.ts +506 -0
- package/src/hooks/use-layout-performance.ts +319 -0
- package/src/hooks/use-loading-accessibility.ts +535 -0
- package/src/hooks/use-loading-performance.ts +473 -0
- package/src/hooks/use-memory-usage.ts +287 -0
- package/src/hooks/use-mobile-form-layout.ts +464 -0
- package/src/hooks/use-mobile-form-validation.ts +518 -0
- package/src/hooks/use-mobile-keyboard-optimization.ts +472 -0
- package/src/hooks/use-mobile-layout.ts +302 -0
- package/src/hooks/use-mobile-optimization.ts +406 -0
- package/src/hooks/use-mobile-skeleton.ts +402 -0
- package/src/hooks/use-mobile-touch.ts +414 -0
- package/src/hooks/use-performance-throttling.ts +348 -0
- package/src/hooks/use-performance.ts +316 -0
- package/src/hooks/use-reusable-architecture.ts +414 -0
- package/src/hooks/use-semantic-input-types.ts +357 -0
- package/src/hooks/use-semantic-input.ts +565 -0
- package/src/hooks/use-tablet-layout.ts +384 -0
- package/src/hooks/use-touch-friendly-input.ts +524 -0
- package/src/hooks/use-touch-friendly-interface.ts +331 -0
- package/src/hooks/use-touch-optimization.ts +375 -0
- package/src/index.ts +279 -279
- package/src/lib/utils.ts +6 -0
- package/src/themes/README.md +272 -0
- package/src/themes/ThemeContext.tsx +31 -0
- package/src/themes/ThemeProvider.tsx +232 -0
- package/src/themes/accessibility/index.ts +27 -0
- package/src/themes/accessibility.ts +259 -0
- package/src/themes/aria-patterns.ts +420 -0
- package/src/themes/base-themes.ts +55 -0
- package/src/themes/colorManager.ts +380 -0
- package/src/themes/examples/dark-theme.ts +154 -0
- package/src/themes/examples/minimal-theme.ts +108 -0
- package/src/themes/focus-management.ts +701 -0
- package/src/themes/fontLoader.ts +201 -0
- package/src/themes/high-contrast.ts +621 -0
- package/src/themes/index.ts +19 -0
- package/src/themes/inheritance.ts +227 -0
- package/src/themes/keyboard-navigation.ts +550 -0
- package/src/themes/motion-reduction.ts +662 -0
- package/src/themes/navigation.ts +238 -0
- package/src/themes/screen-reader.ts +645 -0
- package/src/themes/systemThemeDetector.ts +182 -0
- package/src/themes/themeCSSUpdater.ts +262 -0
- package/src/themes/themePersistence.ts +238 -0
- package/src/themes/themes/default.ts +586 -0
- package/src/themes/themes/harvey.ts +554 -0
- package/src/themes/themes/stan-design.ts +683 -0
- package/src/themes/types.ts +460 -0
- package/src/themes/useSystemTheme.ts +48 -0
- package/src/themes/useTheme.ts +87 -0
- package/src/themes/validation.ts +462 -0
- package/src/tokens/index.ts +34 -0
- package/src/tokens/tokenExporter.ts +397 -0
- package/src/tokens/tokenGenerator.ts +276 -0
- package/src/tokens/tokenManager.ts +248 -0
- package/src/tokens/tokenValidator.ts +543 -0
- package/src/tokens/types.ts +78 -0
- package/src/utils/bundle-analyzer.ts +260 -0
- package/src/utils/bundle-splitting.ts +483 -0
- package/src/utils/lazy-loading.ts +441 -0
- package/src/utils/performance-monitor.ts +513 -0
- package/src/utils/tree-shaking.ts +274 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
// Bundle splitting utilities for optimizing build process and loading performance
|
|
2
|
+
export interface BundleSplitConfig {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
strategy: 'dynamic' | 'static' | 'hybrid';
|
|
5
|
+
chunkSize: number;
|
|
6
|
+
maxChunks: number;
|
|
7
|
+
minChunkSize: number;
|
|
8
|
+
vendorChunk: boolean;
|
|
9
|
+
commonChunk: boolean;
|
|
10
|
+
asyncChunk: boolean;
|
|
11
|
+
preloadChunks: boolean;
|
|
12
|
+
cacheGroups: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ChunkAnalysis {
|
|
16
|
+
name: string;
|
|
17
|
+
size: number;
|
|
18
|
+
gzippedSize: number;
|
|
19
|
+
modules: string[];
|
|
20
|
+
dependencies: string[];
|
|
21
|
+
async: boolean;
|
|
22
|
+
vendor: boolean;
|
|
23
|
+
common: boolean;
|
|
24
|
+
loadPriority: 'high' | 'medium' | 'low';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface BundleSplitReport {
|
|
28
|
+
chunks: ChunkAnalysis[];
|
|
29
|
+
totalSize: number;
|
|
30
|
+
totalGzippedSize: number;
|
|
31
|
+
chunkCount: number;
|
|
32
|
+
averageChunkSize: number;
|
|
33
|
+
optimizationScore: number;
|
|
34
|
+
recommendations: string[];
|
|
35
|
+
timestamp: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class BundleSplitter {
|
|
39
|
+
private config: BundleSplitConfig;
|
|
40
|
+
private chunks: Map<string, ChunkAnalysis>;
|
|
41
|
+
|
|
42
|
+
constructor(config: BundleSplitConfig = {
|
|
43
|
+
enabled: true,
|
|
44
|
+
strategy: 'hybrid',
|
|
45
|
+
chunkSize: 244 * 1024, // 244KB
|
|
46
|
+
maxChunks: 10,
|
|
47
|
+
minChunkSize: 30 * 1024, // 30KB
|
|
48
|
+
vendorChunk: true,
|
|
49
|
+
commonChunk: true,
|
|
50
|
+
asyncChunk: true,
|
|
51
|
+
preloadChunks: true,
|
|
52
|
+
cacheGroups: {}
|
|
53
|
+
}) {
|
|
54
|
+
this.config = config;
|
|
55
|
+
this.chunks = new Map();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Analyze bundle chunks from build output
|
|
59
|
+
analyzeChunks(buildOutput: string): ChunkAnalysis[] {
|
|
60
|
+
if (!this.config.enabled) return [];
|
|
61
|
+
|
|
62
|
+
const lines = buildOutput.split('\n');
|
|
63
|
+
const chunks: ChunkAnalysis[] = [];
|
|
64
|
+
|
|
65
|
+
lines.forEach(line => {
|
|
66
|
+
// Handle all dist/ patterns
|
|
67
|
+
if (line.includes('dist/') && line.includes('kB')) {
|
|
68
|
+
// Use a more flexible regex that captures the essential parts
|
|
69
|
+
const match = line.match(/\s*dist\/(?:assets\/)?([^\s]+)\s+(\d+\.\d+)\s+kB\s+\│\s*gzip:\s*(\d+\.\d+)\s+kB/);
|
|
70
|
+
|
|
71
|
+
if (match) {
|
|
72
|
+
const [, filename, size, gzip] = match;
|
|
73
|
+
const sizeKB = parseFloat(size);
|
|
74
|
+
const gzipKB = parseFloat(gzip);
|
|
75
|
+
|
|
76
|
+
// Extract name and extension from filename
|
|
77
|
+
const nameMatch = filename.match(/^([^.]+)(?:\.[^.]+\.([^.]+))?$/);
|
|
78
|
+
const name = nameMatch ? nameMatch[1] : filename;
|
|
79
|
+
const ext = nameMatch && nameMatch[2] ? nameMatch[2] : '';
|
|
80
|
+
|
|
81
|
+
const chunk: ChunkAnalysis = {
|
|
82
|
+
name: ext ? `${name}.${ext}` : name,
|
|
83
|
+
size: sizeKB * 1024, // Convert to bytes
|
|
84
|
+
gzippedSize: gzipKB * 1024,
|
|
85
|
+
modules: this.estimateModulesForChunk(name),
|
|
86
|
+
dependencies: this.estimateDependencies(name),
|
|
87
|
+
async: this.isAsyncChunk(name),
|
|
88
|
+
vendor: this.isVendorChunk(name),
|
|
89
|
+
common: this.isCommonChunk(name),
|
|
90
|
+
loadPriority: this.calculateLoadPriority(name, sizeKB)
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
chunks.push(chunk);
|
|
94
|
+
this.chunks.set(chunk.name, chunk);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return chunks;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Estimate modules for a specific chunk
|
|
103
|
+
private estimateModulesForChunk(chunkName: string): string[] {
|
|
104
|
+
if (chunkName.includes('index')) {
|
|
105
|
+
return ['main', 'themes', 'components', 'utils'];
|
|
106
|
+
} else if (chunkName.includes('vendor')) {
|
|
107
|
+
return ['react', 'react-dom', 'lodash', 'date-fns'];
|
|
108
|
+
} else if (chunkName.includes('theme')) {
|
|
109
|
+
return ['theme-provider', 'theme-switcher', 'theme-customizer'];
|
|
110
|
+
} else if (chunkName.includes('component')) {
|
|
111
|
+
return ['button', 'card', 'input', 'badge'];
|
|
112
|
+
} else if (chunkName.includes('util')) {
|
|
113
|
+
return ['performance', 'bundle', 'tree-shaking', 'lazy-loading'];
|
|
114
|
+
}
|
|
115
|
+
return ['unknown'];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Estimate dependencies for a chunk
|
|
119
|
+
private estimateDependencies(chunkName: string): string[] {
|
|
120
|
+
if (chunkName.includes('index')) {
|
|
121
|
+
return ['vendor', 'theme', 'component'];
|
|
122
|
+
} else if (chunkName.includes('vendor')) {
|
|
123
|
+
return [];
|
|
124
|
+
} else if (chunkName.includes('theme')) {
|
|
125
|
+
return ['vendor'];
|
|
126
|
+
} else if (chunkName.includes('component')) {
|
|
127
|
+
return ['vendor', 'theme'];
|
|
128
|
+
}
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check if chunk is async (lazy-loaded)
|
|
133
|
+
private isAsyncChunk(chunkName: string): boolean {
|
|
134
|
+
return chunkName.includes('async') ||
|
|
135
|
+
chunkName.includes('lazy') ||
|
|
136
|
+
chunkName.includes('dynamic');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check if chunk contains vendor libraries
|
|
140
|
+
private isVendorChunk(chunkName: string): boolean {
|
|
141
|
+
return chunkName.includes('vendor') ||
|
|
142
|
+
chunkName.includes('lib') ||
|
|
143
|
+
chunkName.includes('node_modules');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check if chunk contains common/shared code
|
|
147
|
+
private isCommonChunk(chunkName: string): boolean {
|
|
148
|
+
return chunkName.includes('common') ||
|
|
149
|
+
chunkName.includes('shared') ||
|
|
150
|
+
chunkName.includes('runtime');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Calculate load priority for a chunk
|
|
154
|
+
private calculateLoadPriority(chunkName: string, sizeKB: number): 'high' | 'medium' | 'low' {
|
|
155
|
+
if (chunkName.includes('index') || chunkName.includes('main')) {
|
|
156
|
+
return 'high';
|
|
157
|
+
} else if (chunkName.includes('vendor') || chunkName.includes('common')) {
|
|
158
|
+
return 'medium';
|
|
159
|
+
} else if (sizeKB > 100) {
|
|
160
|
+
return 'low';
|
|
161
|
+
}
|
|
162
|
+
return 'medium';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Generate bundle splitting recommendations
|
|
166
|
+
generateRecommendations(chunks: ChunkAnalysis[]): string[] {
|
|
167
|
+
const recommendations: string[] = [];
|
|
168
|
+
|
|
169
|
+
// Check chunk count
|
|
170
|
+
if (chunks.length > this.config.maxChunks) {
|
|
171
|
+
recommendations.push(`Too many chunks (${chunks.length}). Consider consolidating smaller chunks to reduce HTTP requests.`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Check chunk sizes
|
|
175
|
+
const oversizedChunks = chunks.filter(chunk => chunk.size > this.config.chunkSize);
|
|
176
|
+
if (oversizedChunks.length > 0) {
|
|
177
|
+
recommendations.push(`${oversizedChunks.length} chunks exceed the recommended size of ${this.config.chunkSize / 1024}KB. Consider splitting them further.`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const undersizedChunks = chunks.filter(chunk => chunk.size < this.config.minChunkSize);
|
|
181
|
+
if (undersizedChunks.length > 0) {
|
|
182
|
+
recommendations.push(`${undersizedChunks.length} chunks are too small (below ${this.config.minChunkSize / 1024}KB). Consider merging them.`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check vendor chunk strategy
|
|
186
|
+
const vendorChunks = chunks.filter(chunk => chunk.vendor);
|
|
187
|
+
if (vendorChunks.length === 0 && this.config.vendorChunk) {
|
|
188
|
+
recommendations.push('No vendor chunk detected. Consider creating a separate vendor chunk for third-party libraries.');
|
|
189
|
+
} else if (vendorChunks.length > 1) {
|
|
190
|
+
recommendations.push('Multiple vendor chunks detected. Consider consolidating into a single vendor chunk.');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Check async chunk strategy
|
|
194
|
+
const asyncChunks = chunks.filter(chunk => chunk.async);
|
|
195
|
+
if (asyncChunks.length === 0 && this.config.asyncChunk) {
|
|
196
|
+
recommendations.push('No async chunks detected. Consider implementing code splitting for better performance.');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Check load priorities
|
|
200
|
+
const highPriorityChunks = chunks.filter(chunk => chunk.loadPriority === 'high');
|
|
201
|
+
if (highPriorityChunks.length > 3) {
|
|
202
|
+
recommendations.push('Too many high-priority chunks. Consider reducing critical chunks to improve initial load time.');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (recommendations.length === 0) {
|
|
206
|
+
recommendations.push('Bundle splitting is well-optimized. No immediate actions required.');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return recommendations;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Calculate optimization score
|
|
213
|
+
calculateOptimizationScore(chunks: ChunkAnalysis[]): number {
|
|
214
|
+
let score = 100;
|
|
215
|
+
|
|
216
|
+
// Penalize too many chunks
|
|
217
|
+
if (chunks.length > this.config.maxChunks) {
|
|
218
|
+
score -= (chunks.length - this.config.maxChunks) * 5;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Penalize oversized chunks
|
|
222
|
+
const oversizedChunks = chunks.filter(chunk => chunk.size > this.config.chunkSize);
|
|
223
|
+
score -= oversizedChunks.length * 10;
|
|
224
|
+
|
|
225
|
+
// Penalize undersized chunks
|
|
226
|
+
const undersizedChunks = chunks.filter(chunk => chunk.size < this.config.minChunkSize);
|
|
227
|
+
score -= undersizedChunks.length * 3;
|
|
228
|
+
|
|
229
|
+
// Penalize missing vendor chunk
|
|
230
|
+
const vendorChunks = chunks.filter(chunk => chunk.vendor);
|
|
231
|
+
if (vendorChunks.length === 0 && this.config.vendorChunk) {
|
|
232
|
+
score -= 15;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Penalize missing async chunks
|
|
236
|
+
const asyncChunks = chunks.filter(chunk => chunk.async);
|
|
237
|
+
if (asyncChunks.length === 0 && this.config.asyncChunk) {
|
|
238
|
+
score -= 10;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return Math.max(0, score);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Generate Vite configuration for bundle splitting
|
|
245
|
+
generateViteConfig(): string {
|
|
246
|
+
const config = {
|
|
247
|
+
build: {
|
|
248
|
+
rollupOptions: {
|
|
249
|
+
output: {
|
|
250
|
+
manualChunks: this.generateManualChunks(),
|
|
251
|
+
chunkFileNames: this.generateChunkFileNames(),
|
|
252
|
+
entryFileNames: this.generateEntryFileNames(),
|
|
253
|
+
assetFileNames: this.generateAssetFileNames()
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
chunkSizeWarningLimit: this.config.chunkSize / 1024,
|
|
257
|
+
minify: 'terser',
|
|
258
|
+
sourcemap: true
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return JSON.stringify(config, null, 2);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Generate manual chunk configuration
|
|
266
|
+
private generateManualChunks(): Record<string, string[]> {
|
|
267
|
+
const chunks: Record<string, string[]> = {};
|
|
268
|
+
|
|
269
|
+
if (this.config.vendorChunk) {
|
|
270
|
+
chunks.vendor = [
|
|
271
|
+
'react',
|
|
272
|
+
'react-dom',
|
|
273
|
+
'react-router-dom'
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (this.config.commonChunk) {
|
|
278
|
+
chunks.common = [
|
|
279
|
+
'src/utils',
|
|
280
|
+
'src/themes',
|
|
281
|
+
'src/components/ui'
|
|
282
|
+
];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (this.config.asyncChunk) {
|
|
286
|
+
chunks.async = [
|
|
287
|
+
'src/components/advanced',
|
|
288
|
+
'src/features'
|
|
289
|
+
];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return chunks;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Generate chunk file naming pattern
|
|
296
|
+
private generateChunkFileNames(): string {
|
|
297
|
+
if (this.config.strategy === 'dynamic') {
|
|
298
|
+
return 'assets/[name]-[hash].js';
|
|
299
|
+
} else if (this.config.strategy === 'static') {
|
|
300
|
+
return 'assets/[name].js';
|
|
301
|
+
} else {
|
|
302
|
+
return 'assets/[name]-[hash].js';
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Generate entry file naming pattern
|
|
307
|
+
private generateEntryFileNames(): string {
|
|
308
|
+
return 'assets/[name]-[hash].js';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Generate asset file naming pattern
|
|
312
|
+
private generateAssetFileNames(): string {
|
|
313
|
+
return 'assets/[name]-[hash].[ext]';
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Generate webpack configuration for bundle splitting
|
|
317
|
+
generateWebpackConfig(): string {
|
|
318
|
+
const config = {
|
|
319
|
+
optimization: {
|
|
320
|
+
splitChunks: {
|
|
321
|
+
chunks: 'all',
|
|
322
|
+
minSize: this.config.minChunkSize,
|
|
323
|
+
maxSize: this.config.chunkSize,
|
|
324
|
+
maxChunks: this.config.maxChunks,
|
|
325
|
+
cacheGroups: this.generateWebpackCacheGroups()
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
return JSON.stringify(config, null, 2);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Generate webpack cache groups
|
|
334
|
+
private generateWebpackCacheGroups(): Record<string, any> {
|
|
335
|
+
const cacheGroups: Record<string, any> = {};
|
|
336
|
+
|
|
337
|
+
if (this.config.vendorChunk) {
|
|
338
|
+
cacheGroups.vendor = {
|
|
339
|
+
test: /[\\/]node_modules[\\/]/,
|
|
340
|
+
name: 'vendor',
|
|
341
|
+
chunks: 'all',
|
|
342
|
+
priority: 10
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (this.config.commonChunk) {
|
|
347
|
+
cacheGroups.common = {
|
|
348
|
+
name: 'common',
|
|
349
|
+
minChunks: 2,
|
|
350
|
+
chunks: 'all',
|
|
351
|
+
priority: 5
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Add custom cache groups from config
|
|
356
|
+
Object.assign(cacheGroups, this.config.cacheGroups);
|
|
357
|
+
|
|
358
|
+
return cacheGroups;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Generate dynamic import patterns for code splitting
|
|
362
|
+
generateDynamicImports(): string[] {
|
|
363
|
+
const patterns: string[] = [];
|
|
364
|
+
|
|
365
|
+
if (this.config.asyncChunk) {
|
|
366
|
+
patterns.push(
|
|
367
|
+
"// Theme switching",
|
|
368
|
+
"const ThemeSwitcher = lazy(() => import('./components/ThemeSwitcher'))",
|
|
369
|
+
"",
|
|
370
|
+
"// Advanced components",
|
|
371
|
+
"const AdvancedTable = lazy(() => import('./components/AdvancedTable'))",
|
|
372
|
+
"const DataGrid = lazy(() => import('./components/DataGrid'))",
|
|
373
|
+
"",
|
|
374
|
+
"// Features",
|
|
375
|
+
"const Dashboard = lazy(() => import('./features/Dashboard'))",
|
|
376
|
+
"const Settings = lazy(() => import('./features/Settings'))"
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return patterns;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Generate preload strategies
|
|
384
|
+
generatePreloadStrategies(): string[] {
|
|
385
|
+
const strategies: string[] = [];
|
|
386
|
+
|
|
387
|
+
if (this.config.preloadChunks) {
|
|
388
|
+
strategies.push(
|
|
389
|
+
"// Preload critical chunks",
|
|
390
|
+
"const preloadCriticalChunks = () => {",
|
|
391
|
+
" const criticalChunks = ['vendor', 'common'];",
|
|
392
|
+
" criticalChunks.forEach(chunk => {",
|
|
393
|
+
" const link = document.createElement('link');",
|
|
394
|
+
" link.rel = 'preload';",
|
|
395
|
+
" link.as = 'script';",
|
|
396
|
+
" link.href = `/assets/${chunk}-[hash].js`;",
|
|
397
|
+
" document.head.appendChild(link);",
|
|
398
|
+
" });",
|
|
399
|
+
"};",
|
|
400
|
+
"",
|
|
401
|
+
"// Preload on route change",
|
|
402
|
+
"const preloadRouteChunk = (route: string) => {",
|
|
403
|
+
" const link = document.createElement('link');",
|
|
404
|
+
" link.rel = 'prefetch';",
|
|
405
|
+
" link.as = 'script';",
|
|
406
|
+
" link.href = `/assets/${route}-[hash].js`;",
|
|
407
|
+
" document.head.appendChild(link);",
|
|
408
|
+
"};"
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return strategies;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Get bundle splitting statistics
|
|
416
|
+
getStatistics(chunks: ChunkAnalysis[]): {
|
|
417
|
+
totalSize: number;
|
|
418
|
+
totalGzippedSize: number;
|
|
419
|
+
chunkCount: number;
|
|
420
|
+
averageChunkSize: number;
|
|
421
|
+
vendorChunkCount: number;
|
|
422
|
+
asyncChunkCount: number;
|
|
423
|
+
commonChunkCount: number;
|
|
424
|
+
optimizationScore: number;
|
|
425
|
+
} {
|
|
426
|
+
const totalSize = chunks.reduce((sum, chunk) => sum + chunk.size, 0);
|
|
427
|
+
const totalGzippedSize = chunks.reduce((sum, chunk) => sum + chunk.gzippedSize, 0);
|
|
428
|
+
const averageChunkSize = chunks.length > 0 ? totalSize / chunks.length : 0;
|
|
429
|
+
const vendorChunkCount = chunks.filter(chunk => chunk.vendor).length;
|
|
430
|
+
const asyncChunkCount = chunks.filter(chunk => chunk.async).length;
|
|
431
|
+
const commonChunkCount = chunks.filter(chunk => chunk.common).length;
|
|
432
|
+
const optimizationScore = this.calculateOptimizationScore(chunks);
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
totalSize,
|
|
436
|
+
totalGzippedSize,
|
|
437
|
+
chunkCount: chunks.length,
|
|
438
|
+
averageChunkSize,
|
|
439
|
+
vendorChunkCount,
|
|
440
|
+
asyncChunkCount,
|
|
441
|
+
commonChunkCount,
|
|
442
|
+
optimizationScore
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Export bundle splitting analysis
|
|
447
|
+
exportAnalysis(chunks: ChunkAnalysis[]): string {
|
|
448
|
+
const recommendations = this.generateRecommendations(chunks);
|
|
449
|
+
const statistics = this.getStatistics(chunks);
|
|
450
|
+
const viteConfig = this.generateViteConfig();
|
|
451
|
+
const webpackConfig = this.generateWebpackConfig();
|
|
452
|
+
const dynamicImports = this.generateDynamicImports();
|
|
453
|
+
const preloadStrategies = this.generatePreloadStrategies();
|
|
454
|
+
|
|
455
|
+
return JSON.stringify({
|
|
456
|
+
chunks,
|
|
457
|
+
statistics,
|
|
458
|
+
recommendations,
|
|
459
|
+
configurations: {
|
|
460
|
+
vite: viteConfig,
|
|
461
|
+
webpack: webpackConfig
|
|
462
|
+
},
|
|
463
|
+
codeSplitting: {
|
|
464
|
+
dynamicImports,
|
|
465
|
+
preloadStrategies
|
|
466
|
+
},
|
|
467
|
+
timestamp: new Date().toISOString()
|
|
468
|
+
}, null, 2);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Update configuration
|
|
472
|
+
updateConfig(newConfig: Partial<BundleSplitConfig>): void {
|
|
473
|
+
this.config = { ...this.config, ...newConfig };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Get current configuration
|
|
477
|
+
getConfig(): BundleSplitConfig {
|
|
478
|
+
return { ...this.config };
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Create and export default instance
|
|
483
|
+
export const bundleSplitter = new BundleSplitter();
|