11import bundleStatsPlugin , { type GroupingRule } from './src' ;
2+ import { BlacklistEntry } from './src/lib/runner/types' ;
3+
4+ const sharedHint =
5+ 'Remove or conditionally load. Supported natively in modern browsers or replace with modern Angular architecture. See: https://blog.angular.io/zone-less-angular-explained-5fa951ce6f6e' ;
6+
7+ const blacklist : BlacklistEntry [ ] = [
8+ // 🧹 Remove or conditionally load. Supported natively in modern browsers or replace with modern Angular architecture.
9+ {
10+ pattern : '**/node_modules/core-js/**' ,
11+ hint : sharedHint ,
12+ } ,
13+ {
14+ pattern : '**/node_modules/zone.js/**' ,
15+ hint : sharedHint ,
16+ } ,
17+ {
18+ pattern : '**/node_modules/smoothscroll-polyfill/**' ,
19+ hint : sharedHint ,
20+ } ,
21+ {
22+ pattern : '**/node_modules/web-animations-js/**' ,
23+ hint : sharedHint ,
24+ } ,
25+
26+ // 🔁 Replace with modern alternatives
27+ {
28+ pattern : '**/node_modules/lodash/**' ,
29+ hint : 'Replace with `lodash-es` and use selective imports like `import isEmpty from "lodash-es/isEmpty"`.' ,
30+ } ,
31+ {
32+ pattern : '**/node_modules/underscore/**' ,
33+ hint : 'Replace with `lodash-es` or native utilities like `Object.keys`, `Array.prototype.map`, etc.' ,
34+ } ,
35+ {
36+ pattern : '**/node_modules/decimal.js/**' ,
37+ hint : 'Replace with native `BigInt` if full decimal precision isn’t required.' ,
38+ } ,
39+ {
40+ pattern : '**/node_modules/angular2-toaster/**' ,
41+ hint : 'Replace with actively maintained alternatives like `ngx-toastr` or `ngneat/hot-toast`.' ,
42+ } ,
43+
44+ // 🕒 Use lazy loading for heavy dependencies
45+ {
46+ pattern : '**/node_modules/socket.io-client/**' ,
47+ hint : 'Use lazy loading for real-time features. Replace with native WebSocket API or `ws` where possible.' ,
48+ } ,
49+ {
50+ pattern : '**/node_modules/launchdarkly-js-client-sdk/**' ,
51+ hint : 'Use lazy loading for feature flag SDKs to reduce initial bundle size.' ,
52+ } ,
53+ {
54+ pattern : '**/node_modules/@microsoft/**' ,
55+ hint : 'Use lazy loading for Microsoft SDKs due to their large size.' ,
56+ } ,
57+ {
58+ pattern : '**/node_modules/ngx-toastr/**' ,
59+ hint : 'Use lazy loading for notifications. Consider `ngneat/hot-toast` or `notiflix` as lighter alternatives.' ,
60+ } ,
61+ {
62+ pattern : '**/node_modules/ngx-scrollbar/**' ,
63+ hint : 'Use lazy loading for custom scrollbars. Replace with native CSS where possible.' ,
64+ } ,
65+ {
66+ pattern : '**/node_modules/@angular-slider/**' ,
67+ hint : 'Use lazy loading for sliders. Consider `ngx-slider-v2` or custom lightweight slider components.' ,
68+ } ,
69+ {
70+ pattern : '**/node_modules/howler/**' ,
71+ hint : 'Use lazy loading for audio libraries to reduce bundle size.' ,
72+ } ,
73+ {
74+ pattern : '**/node_modules/hls.js/**' ,
75+ hint : 'Use lazy loading for video streaming libraries like `hls.js`.' ,
76+ } ,
77+ {
78+ pattern : '**/node_modules/lottie-web/**' ,
79+ hint : 'Use lazy loading for animations. Consider `ngx-lottie` wrapper for Angular.' ,
80+ } ,
81+ {
82+ pattern : '**/node_modules/ngx-device-detector/**' ,
83+ hint : 'Use lazy loading for device detection logic or move detection server-side.' ,
84+ } ,
85+ {
86+ pattern : '**/node_modules/ua-parser-js/**' ,
87+ hint : 'Use lazy loading or replace with server-side detection if possible.' ,
88+ } ,
89+
90+ // 🚫 Exclude from production builds
91+ {
92+ pattern : '**/node_modules/@storybook/**' ,
93+ hint : 'Exclude Storybook packages from production bundles.' ,
94+ } ,
95+ {
96+ pattern : '**/node_modules/jest/**' ,
97+ hint : 'Exclude test frameworks like Jest from production builds.' ,
98+ } ,
99+ ] ;
2100
3101const nodeModulesGroup : GroupingRule [ ] = [
4- // General node_modules group (processed third due to reverse order )
102+ // Angular packages (processed first )
5103 {
6- patterns : [ '**/node_modules/**' , '**/node_modules/@*/**/*' ] ,
7- icon : '📦' ,
8- maxDepth : 2 ,
104+ patterns : [
105+ '**/node_modules/@angular/**' , // Catches @angular /core, @angular/common, @angular/router, etc.
106+ '**/node_modules/@ng*/**' , // Catches @ngrx /store, @ngrx/effects, etc.#
107+ '**/node_modules/@ngx-*/**' ,
108+ '**/node_modules/@angular-*/**' , // Catches @angular -slider, @angular-devkit, etc.
109+ '**/node_modules/@*angular*/**' , // Catches @rx -angular, @push-based-angular, etc.
110+ ] ,
111+ icon : '🅰️' ,
112+ numSegments : 3 , // Shows @angular /router, @angular/common, @ngrx/store, etc.
9113 } ,
10- // Non-scoped Angular packages (processed second due to reverse order )
114+ // Non-scoped Angular packages (processed second)
11115 {
12116 patterns : [
13117 '**/node_modules/ngx-*/**' ,
14118 '**/node_modules/ng-*/**' ,
15- '**/node_modules/*angular*' ,
119+ '**/node_modules/*angular*/**' , // Non-scoped packages containing "angular"
16120 ] ,
17121 icon : '🅰️' ,
18- maxDepth : 2 , // Gets ngx-toastr, ng-bootstrap, etc.
122+ numSegments : 2 , // Shows ngx-toastr, ng-bootstrap, etc.
19123 } ,
20- // Scoped Angular packages (processed first due to reverse order, takes precedence)
124+ // All scoped packages (processed third) - no title allows auto-derivation of individual package names
21125 {
22- patterns : [ '**/node_modules/@angular/**' , '**/node_modules/@ngrx/**' ] ,
23- icon : '🅰️' ,
24- maxDepth : 3 , // Gets @angular /router, @angular/common, @ngrx/store, etc.
126+ patterns : [ '**/node_modules/@*/**' ] ,
127+ icon : '📦' ,
128+ numSegments : 3 , // Shows @rx -angular/state, @push-based/test-lib, @ngx-translate/core, etc.
129+ } ,
130+ // General node_modules group (processed last - catches everything else)
131+ {
132+ title : 'Node Modules' ,
133+ patterns : [ '**/node_modules/**' ] ,
134+ icon : '📦' ,
135+ numSegments : 1 , // Shows individual unscoped packages
25136 } ,
26137] ;
27138
@@ -192,7 +303,7 @@ const badGroups: GroupingRule[] = [
192303 ] ,
193304 } ,
194305 {
195- title : '📚 Documentation in Bundle ' ,
306+ title : '🚨 📚 Documentation in Production ' ,
196307 patterns : [
197308 '**/node_modules/**/demo/**' ,
198309 '**/node_modules/**/examples/**' ,
@@ -233,43 +344,50 @@ const config = {
233344 artefactsPath :
234345 './packages/plugin-bundle-stats/mocks/fixtures/stats/angular-large.stats.json' ,
235346 selection : {
236- excludeOutputs : [ '**/*.map' ] , // Only exclude source maps as they're not part of runtime bundle
347+ excludeOutputs : [ '**/*.map' , '**/*.d.ts' ] , // Only exclude source maps as they're not part of runtime bundle
237348 } ,
238349 scoring : {
239350 penalty : {
240351 // Penalty for individual files that are too large
241352 // This highlights large files without hiding them
242- artefactSize : [ 0 , 3000000 ] , // 0-3MB range - penalty for files > 3MB
243- blacklist : [ ] ,
353+ artefactSize : [ 0 , 3_000_000 ] , // 0-3MB range - penalty for files > 3MB
354+ blacklist,
244355 } ,
245356 } ,
246- insights : [ ...productGroups , ...badGroups , ...nodeModulesGroup ] ,
357+ insights : [
358+ ...productGroups , // Process product groups first for better specificity
359+ ...badGroups , // Process bad/warning groups second
360+ ...nodeModulesGroup , // Process general node_modules groups last
361+ ] ,
247362 artefactTree : {
248- groups : [ ...productGroups , ...badGroups , ...nodeModulesGroup ] ,
363+ groups : [
364+ ...productGroups , // Process product groups first for better specificity
365+ ...nodeModulesGroup , // Process general node_modules groups last
366+ ] ,
249367 pruning : {
250- maxDepth : 5 ,
368+ maxChildren : 10 ,
369+ maxDepth : 3 ,
251370 minSize : 1_000 , // Reduced from 50_000 to show smaller files (1KB threshold)
252371 } ,
253372 } ,
254373 audits : [
255- /* {
374+ {
256375 title : 'All Files' ,
257376 description : 'All files in the bundle' ,
258377 selection : {
259- includeOutputs: ['**\/*'],
378+ // Use specific includeOutputs instead of global include for better control
379+ include : [ '**/*.js' ] ,
380+ // Exclude patterns to filter out unwanted files
381+ excludeOutputs : [
382+ '**/*.map' , // Source maps
383+ '**/*.d.ts' , // TypeScript declarations
384+ ] ,
260385 } ,
261386 scoring : {
262387 // Main bundle size threshold - warn when total exceeds 80MB
263- totalSize: 80000000 , // 80MB in bytes
388+ totalSize : 80_000_000 , // 80MB in bytes
264389 } ,
265- artefactTree: {
266- pruning: {
267- pathLength: 100,
268- maxChildren: 20,
269- maxDepth: 3,
270- },
271- },
272- },*/
390+ } ,
273391 // Initial bundle size audit
274392 {
275393 title : 'Initial Bundle Size' ,
@@ -284,14 +402,7 @@ const config = {
284402 ] ,
285403 } ,
286404 scoring : {
287- totalSize : 80_000_000 ,
288- } ,
289- artefactTree : {
290- groups : [
291- ...nodeModulesGroup ,
292- ...badGroups ,
293- ...productGroups , // Process product groups first for better specificity (last in array = first processed)
294- ] ,
405+ totalSize : 8_000_000 ,
295406 } ,
296407 } ,
297408 ] ,
0 commit comments