@bundle-stats/utils 3.3.0-alpha.0 → 3.3.0
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 +40 -6
- package/lib/browsertime/index.js +5 -1
- package/lib/browsertime/index.js.map +1 -1
- package/lib/config/component-links.js +1 -0
- package/lib/config/component-links.js.map +1 -1
- package/lib/config/file-types.js +3 -3
- package/lib/config/file-types.js.map +1 -1
- package/lib/config/index.js +5 -1
- package/lib/config/index.js.map +1 -1
- package/lib/i18n.js +2 -1
- package/lib/i18n.js.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/lib/jobs/create-job.js +7 -3
- package/lib/jobs/create-job.js.map +1 -1
- package/lib/jobs/create-jobs.js +2 -2
- package/lib/jobs/create-jobs.js.map +1 -1
- package/lib/jobs/index.js +5 -1
- package/lib/jobs/index.js.map +1 -1
- package/lib/lighthouse/index.js +5 -1
- package/lib/lighthouse/index.js.map +1 -1
- package/lib/report/create.js +5 -1
- package/lib/report/create.js.map +1 -1
- package/lib/report/index.js +5 -1
- package/lib/report/index.js.map +1 -1
- package/lib/utils/component-links.js +15 -1
- package/lib/utils/component-links.js.map +1 -1
- package/lib/utils/format.js +5 -1
- package/lib/utils/format.js.map +1 -1
- package/lib/utils/index.js +5 -1
- package/lib/utils/index.js.map +1 -1
- package/lib/webpack/constants.js +14 -26
- package/lib/webpack/constants.js.map +1 -1
- package/lib/webpack/extract/assets-size-total-insight.js +4 -4
- package/lib/webpack/extract/assets-size-total-insight.js.map +1 -1
- package/lib/webpack/extract/assets-size.js +4 -3
- package/lib/webpack/extract/assets-size.js.map +1 -1
- package/lib/webpack/extract/index.js +1 -3
- package/lib/webpack/extract/index.js.map +1 -1
- package/lib/webpack/extract/modules.js +29 -2
- package/lib/webpack/extract/modules.js.map +1 -1
- package/lib/webpack/index.js +5 -1
- package/lib/webpack/index.js.map +1 -1
- package/lib/webpack/metrics.js +30 -27
- package/lib/webpack/metrics.js.map +1 -1
- package/lib-esm/config/component-links.js +1 -0
- package/lib-esm/config/component-links.js.map +1 -1
- package/lib-esm/config/file-types.js +3 -3
- package/lib-esm/config/file-types.js.map +1 -1
- package/lib-esm/i18n.js +2 -1
- package/lib-esm/i18n.js.map +1 -1
- package/lib-esm/jobs/create-job.js +2 -2
- package/lib-esm/jobs/create-job.js.map +1 -1
- package/lib-esm/jobs/create-jobs.js +2 -2
- package/lib-esm/jobs/create-jobs.js.map +1 -1
- package/lib-esm/utils/component-links.js +14 -0
- package/lib-esm/utils/component-links.js.map +1 -1
- package/lib-esm/webpack/constants.js +13 -25
- package/lib-esm/webpack/constants.js.map +1 -1
- package/lib-esm/webpack/extract/assets-size-total-insight.js +4 -4
- package/lib-esm/webpack/extract/assets-size-total-insight.js.map +1 -1
- package/lib-esm/webpack/extract/assets-size.js +4 -3
- package/lib-esm/webpack/extract/assets-size.js.map +1 -1
- package/lib-esm/webpack/extract/index.js +1 -3
- package/lib-esm/webpack/extract/index.js.map +1 -1
- package/lib-esm/webpack/extract/modules.js +29 -2
- package/lib-esm/webpack/extract/modules.js.map +1 -1
- package/lib-esm/webpack/metrics.js +30 -27
- package/lib-esm/webpack/metrics.js.map +1 -1
- package/package.json +16 -16
- package/src/config/component-links.js +1 -0
- package/src/config/file-types.js +3 -3
- package/src/constants.ts +3 -0
- package/src/i18n.js +2 -1
- package/src/jobs/create-job.js +2 -2
- package/src/jobs/create-jobs.js +2 -2
- package/src/utils/component-links.js +23 -7
- package/src/webpack/constants.js +91 -0
- package/src/webpack/extract/assets-size-total-insight.js +4 -4
- package/src/webpack/extract/assets-size.js +5 -3
- package/src/webpack/extract/index.js +5 -10
- package/src/webpack/extract/modules.ts +35 -4
- package/src/webpack/{metrics.ts → metrics.js} +30 -27
- package/types/config/component-links.d.ts +1 -0
- package/types/constants.d.ts +3 -0
- package/types/i18n.d.ts +1 -0
- package/types/jobs/create-job.d.ts +1 -1
- package/types/jobs/create-jobs.d.ts +1 -1
- package/types/utils/component-links.d.ts +26 -12
- package/types/webpack/constants.d.ts +9 -31
- package/types/webpack/extract/index.d.ts +1 -1
- package/types/webpack/metrics.d.ts +153 -102
- package/lib/webpack/extract/budgets-insights.js +0 -39
- package/lib/webpack/extract/budgets-insights.js.map +0 -1
- package/lib-esm/webpack/extract/budgets-insights.js +0 -33
- package/lib-esm/webpack/extract/budgets-insights.js.map +0 -1
- package/src/webpack/constants.ts +0 -96
- package/src/webpack/extract/budgets-insights.ts +0 -73
- package/types/webpack/extract/budgets-insights.d.ts +0 -22
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import isEmpty from 'lodash/isEmpty';
|
|
2
|
+
import round from 'lodash/round';
|
|
2
3
|
import { getModuleName, normalizeChunkId } from '../utils';
|
|
3
4
|
export const extractModules = (webpackStats) => {
|
|
4
5
|
const modulesSource = (webpackStats === null || webpackStats === void 0 ? void 0 : webpackStats.modules) || [];
|
|
5
6
|
if (!modulesSource) {
|
|
6
|
-
return {
|
|
7
|
+
return {
|
|
8
|
+
metrics: {
|
|
9
|
+
duplicateCode: { value: 0 },
|
|
10
|
+
duplicateModulesCount: { value: 0 },
|
|
11
|
+
modules: {},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
7
14
|
}
|
|
8
15
|
const allModules = modulesSource.reduce((agg, moduleEntry) => {
|
|
9
16
|
if (!moduleEntry.modules) {
|
|
@@ -16,19 +23,39 @@ export const extractModules = (webpackStats) => {
|
|
|
16
23
|
})));
|
|
17
24
|
return agg;
|
|
18
25
|
}, []);
|
|
26
|
+
let totalCodeSize = 0;
|
|
27
|
+
let duplicateCodeSize = 0;
|
|
28
|
+
let duplicateModulesCount = 0;
|
|
19
29
|
const modules = allModules.reduce((agg, moduleEntry) => {
|
|
20
30
|
const { name, size, chunks } = moduleEntry;
|
|
21
31
|
const normalizedName = getModuleName(name);
|
|
22
32
|
if (isEmpty(chunks)) {
|
|
23
33
|
return agg;
|
|
24
34
|
}
|
|
35
|
+
const instances = chunks.length;
|
|
36
|
+
const duplicateInstances = instances - 1;
|
|
37
|
+
duplicateModulesCount += duplicateInstances;
|
|
38
|
+
duplicateCodeSize += duplicateInstances * size;
|
|
39
|
+
totalCodeSize += instances * size;
|
|
25
40
|
agg[normalizedName] = {
|
|
26
41
|
name,
|
|
27
42
|
value: size,
|
|
28
43
|
chunkIds: chunks.map(normalizeChunkId),
|
|
44
|
+
duplicated: Boolean(duplicateInstances),
|
|
29
45
|
};
|
|
30
46
|
return agg;
|
|
31
47
|
}, {});
|
|
32
|
-
|
|
48
|
+
const duplicateCode = totalCodeSize ? round((duplicateCodeSize / totalCodeSize) * 100, 2) : 0;
|
|
49
|
+
return {
|
|
50
|
+
metrics: {
|
|
51
|
+
modules,
|
|
52
|
+
duplicateCode: {
|
|
53
|
+
value: duplicateCode,
|
|
54
|
+
},
|
|
55
|
+
duplicateModulesCount: {
|
|
56
|
+
value: duplicateModulesCount,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
33
60
|
};
|
|
34
61
|
//# sourceMappingURL=modules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../../src/webpack/extract/modules.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../../src/webpack/extract/modules.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,KAAK,MAAM,cAAc,CAAC;AAGjC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAe3D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,YAAkB,EAAyB,EAAE;IAC1E,MAAM,aAAa,GAAgD,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,OAAO,KAAI,EAAE,CAAC;IAE/F,IAAI,CAAC,aAAa,EAAE;QAClB,OAAO;YACL,OAAO,EAAE;gBACP,aAAa,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;gBAC3B,qBAAqB,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;gBACnC,OAAO,EAAE,EAAE;aACZ;SACF,CAAC;KACH;IAGD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE;QAC3D,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;YACxB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEtB,OAAO,GAAG,CAAC;SACZ;QAGD,GAAG,GAAG,GAAG,CAAC,MAAM,CACd,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;YAC/C,GAAG,kBAAkB;YAErB,MAAM,EAAE,WAAW,CAAC,MAAM;SAC3B,CAAC,CAAC,CACJ,CAAC;QAEF,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAA0B,CAAC,CAAC;IAE/B,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,IAAI,qBAAqB,GAAG,CAAC,CAAC;IAG9B,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE;QACrD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC;QAC3C,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAG3C,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE;YACnB,OAAO,GAAG,CAAC;SACZ;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;QAChC,MAAM,kBAAkB,GAAG,SAAS,GAAG,CAAC,CAAC;QAEzC,qBAAqB,IAAI,kBAAkB,CAAC;QAC5C,iBAAiB,IAAI,kBAAkB,GAAG,IAAI,CAAC;QAC/C,aAAa,IAAI,SAAS,GAAG,IAAI,CAAC;QAGlC,GAAG,CAAC,cAAc,CAAC,GAAG;YACpB,IAAI;YACJ,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,kBAAkB,CAAC;SACxC,CAAC;QAEF,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAkC,CAAC,CAAC;IAEvC,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,GAAG,aAAa,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9F,OAAO;QACL,OAAO,EAAE;YACP,OAAO;YACP,aAAa,EAAE;gBACb,KAAK,EAAE,aAAa;aACrB;YACD,qBAAqB,EAAE;gBACrB,KAAK,EAAE,qBAAqB;aAC7B;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1,63 +1,73 @@
|
|
|
1
1
|
import { METRIC_TYPE_FILE_SIZE, METRIC_TYPE_NUMERIC, METRIC_TYPE_PERCENTAGE, } from '../config/metrics';
|
|
2
|
-
import { MetricId, SizeByTypeMetricId } from './constants';
|
|
3
2
|
export const metrics = {
|
|
4
|
-
|
|
3
|
+
totalSizeByTypeALL: {
|
|
5
4
|
label: 'Bundle Size',
|
|
6
5
|
description: 'Sum of all assets emitted by webpack.',
|
|
7
6
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
8
7
|
type: METRIC_TYPE_FILE_SIZE,
|
|
9
|
-
biggerIsBetter: false,
|
|
10
8
|
},
|
|
11
|
-
|
|
9
|
+
totalInitialSizeJS: {
|
|
12
10
|
label: 'Initial JS',
|
|
13
11
|
description: 'Sum of all JavaScript assets that are labeled as initial(eg: vendor.js, app.js).',
|
|
14
12
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
15
13
|
type: METRIC_TYPE_FILE_SIZE,
|
|
16
|
-
biggerIsBetter: false,
|
|
17
14
|
},
|
|
18
|
-
|
|
15
|
+
totalInitialSizeCSS: {
|
|
19
16
|
label: 'Initial CSS',
|
|
20
17
|
description: 'Sum of all CSS assets that are labeled as initial(eg: vendor.css, app.css).',
|
|
21
18
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
22
19
|
type: METRIC_TYPE_FILE_SIZE,
|
|
23
|
-
biggerIsBetter: false,
|
|
24
20
|
},
|
|
25
|
-
|
|
21
|
+
cacheInvalidation: {
|
|
26
22
|
label: 'Cache Invalidation',
|
|
27
23
|
description: 'Ratio between the total changed assets and Bundle Size.',
|
|
28
24
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
29
25
|
type: METRIC_TYPE_PERCENTAGE,
|
|
30
26
|
biggerIsBetter: false,
|
|
31
27
|
},
|
|
32
|
-
|
|
28
|
+
chunkCount: {
|
|
33
29
|
label: 'Chunks',
|
|
34
30
|
description: 'Total number of chunks generated by webpack.',
|
|
35
31
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
36
32
|
type: METRIC_TYPE_NUMERIC,
|
|
37
33
|
biggerIsBetter: false,
|
|
38
34
|
},
|
|
39
|
-
|
|
35
|
+
assetCount: {
|
|
40
36
|
label: 'Assets',
|
|
41
37
|
description: 'Total number of assets emitted by webpack.',
|
|
42
38
|
url: 'https://relative-ci.com/documentation/metrics-and-data#assets',
|
|
43
39
|
type: METRIC_TYPE_NUMERIC,
|
|
44
40
|
biggerIsBetter: false,
|
|
45
41
|
},
|
|
46
|
-
|
|
42
|
+
moduleCount: {
|
|
47
43
|
label: 'Modules',
|
|
48
44
|
description: 'Total number of modules bundled by webpack.',
|
|
49
45
|
url: 'https://relative-ci.com/documentation/metrics-and-data#modules-1',
|
|
50
46
|
type: METRIC_TYPE_NUMERIC,
|
|
51
47
|
biggerIsBetter: false,
|
|
52
48
|
},
|
|
53
|
-
|
|
49
|
+
duplicateModulesCount: {
|
|
50
|
+
label: 'Duplicate Modules',
|
|
51
|
+
description: 'Total number of modules that belong to more than one chunk.',
|
|
52
|
+
url: 'https://relative-ci.com/documentation/metrics-and-data#modules-1',
|
|
53
|
+
type: METRIC_TYPE_NUMERIC,
|
|
54
|
+
biggerIsBetter: false,
|
|
55
|
+
},
|
|
56
|
+
duplicateCode: {
|
|
57
|
+
label: 'Duplicate Code',
|
|
58
|
+
description: 'The percentage of total duplicate module size from the total module size.',
|
|
59
|
+
url: 'https://relative-ci.com/documentation/metrics-and-data#modules-1',
|
|
60
|
+
type: METRIC_TYPE_PERCENTAGE,
|
|
61
|
+
biggerIsBetter: false,
|
|
62
|
+
},
|
|
63
|
+
packageCount: {
|
|
54
64
|
label: 'Packages',
|
|
55
65
|
description: 'Total number of packages bundled by webpack.',
|
|
56
66
|
url: 'https://relative-ci.com/documentation/metrics-and-data#packages',
|
|
57
67
|
type: METRIC_TYPE_NUMERIC,
|
|
58
68
|
biggerIsBetter: false,
|
|
59
69
|
},
|
|
60
|
-
|
|
70
|
+
duplicatePackagesCount: {
|
|
61
71
|
label: 'Duplicate Packages',
|
|
62
72
|
description: 'Total number of packages that are duplicated.',
|
|
63
73
|
url: 'https://relative-ci.com/documentation/metrics-and-data#packages',
|
|
@@ -65,40 +75,33 @@ export const metrics = {
|
|
|
65
75
|
biggerIsBetter: false,
|
|
66
76
|
},
|
|
67
77
|
sizes: {
|
|
68
|
-
|
|
78
|
+
totalSizeByTypeJS: {
|
|
69
79
|
label: 'JS',
|
|
70
80
|
type: METRIC_TYPE_FILE_SIZE,
|
|
71
|
-
biggerIsBetter: false,
|
|
72
81
|
},
|
|
73
|
-
|
|
82
|
+
totalSizeByTypeCSS: {
|
|
74
83
|
label: 'CSS',
|
|
75
84
|
type: METRIC_TYPE_FILE_SIZE,
|
|
76
|
-
biggerIsBetter: false,
|
|
77
85
|
},
|
|
78
|
-
|
|
86
|
+
totalSizeByTypeIMG: {
|
|
79
87
|
label: 'IMG',
|
|
80
88
|
type: METRIC_TYPE_FILE_SIZE,
|
|
81
|
-
biggerIsBetter: false,
|
|
82
89
|
},
|
|
83
|
-
|
|
90
|
+
totalSizeByTypeMEDIA: {
|
|
84
91
|
label: 'Media',
|
|
85
92
|
type: METRIC_TYPE_FILE_SIZE,
|
|
86
|
-
biggerIsBetter: false,
|
|
87
93
|
},
|
|
88
|
-
|
|
94
|
+
totalSizeByTypeFONT: {
|
|
89
95
|
label: 'Fonts',
|
|
90
96
|
type: METRIC_TYPE_FILE_SIZE,
|
|
91
|
-
biggerIsBetter: false,
|
|
92
97
|
},
|
|
93
|
-
|
|
98
|
+
totalSizeByTypeHTML: {
|
|
94
99
|
label: 'HTML',
|
|
95
100
|
type: METRIC_TYPE_FILE_SIZE,
|
|
96
|
-
biggerIsBetter: false,
|
|
97
101
|
},
|
|
98
|
-
|
|
102
|
+
totalSizeByTypeOTHER: {
|
|
99
103
|
label: 'Other',
|
|
100
104
|
type: METRIC_TYPE_FILE_SIZE,
|
|
101
|
-
biggerIsBetter: false,
|
|
102
105
|
},
|
|
103
106
|
},
|
|
104
107
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/webpack/metrics.
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/webpack/metrics.js"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,kBAAkB,EAAE;QAClB,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,uCAAuC;QACpD,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,qBAAqB;KAC5B;IACD,kBAAkB,EAAE;QAClB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,kFAAkF;QAC/F,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,qBAAqB;KAC5B;IACD,mBAAmB,EAAE;QACnB,KAAK,EAAE,aAAa;QACpB,WAAW,EAAE,6EAA6E;QAC1F,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,qBAAqB;KAC5B;IACD,iBAAiB,EAAE;QACjB,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,yDAAyD;QACtE,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,sBAAsB;QAC5B,cAAc,EAAE,KAAK;KACtB;IACD,UAAU,EAAE;QACV,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,8CAA8C;QAC3D,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,UAAU,EAAE;QACV,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,4CAA4C;QACzD,GAAG,EAAE,+DAA+D;QACpE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,WAAW,EAAE;QACX,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,6CAA6C;QAC1D,GAAG,EAAE,kEAAkE;QACvE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,qBAAqB,EAAE;QACrB,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,6DAA6D;QAC1E,GAAG,EAAE,kEAAkE;QACvE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,aAAa,EAAE;QACb,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,2EAA2E;QACxF,GAAG,EAAE,kEAAkE;QACvE,IAAI,EAAE,sBAAsB;QAC5B,cAAc,EAAE,KAAK;KACtB;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,8CAA8C;QAC3D,GAAG,EAAE,iEAAiE;QACtE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,sBAAsB,EAAE;QACtB,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,+CAA+C;QAC5D,GAAG,EAAE,iEAAiE;QACtE,IAAI,EAAE,mBAAmB;QACzB,cAAc,EAAE,KAAK;KACtB;IACD,KAAK,EAAE;QACL,iBAAiB,EAAE;YACjB,KAAK,EAAE,IAAI;YACX,IAAI,EAAE,qBAAqB;SAC5B;QACD,kBAAkB,EAAE;YAClB,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,qBAAqB;SAC5B;QACD,kBAAkB,EAAE;YAClB,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,qBAAqB;SAC5B;QACD,oBAAoB,EAAE;YACpB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,qBAAqB;SAC5B;QACD,mBAAmB,EAAE;YACnB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,qBAAqB;SAC5B;QACD,mBAAmB,EAAE;YACnB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,qBAAqB;SAC5B;QACD,oBAAoB,EAAE;YACpB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,qBAAqB;SAC5B;KACF;CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bundle-stats/utils",
|
|
3
|
-
"version": "3.3.0
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "BundleStats utils",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib-esm/index.js",
|
|
@@ -35,28 +35,28 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/relative-ci/bundle-stats/blob/master/packages/utils#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@bundle-stats/plugin-webpack-filter": "^3.
|
|
39
|
-
"@bundle-stats/plugin-webpack-validate": "^3.
|
|
40
|
-
"convert-units": "
|
|
41
|
-
"query-string": "
|
|
42
|
-
"serialize-query-params": "
|
|
38
|
+
"@bundle-stats/plugin-webpack-filter": "^3.3.0",
|
|
39
|
+
"@bundle-stats/plugin-webpack-validate": "^3.3.0",
|
|
40
|
+
"convert-units": "3.0.0-beta.2",
|
|
41
|
+
"query-string": "7.1.1",
|
|
42
|
+
"serialize-query-params": "1.3.6"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@types/jest": "27.
|
|
46
|
-
"@types/lodash": "4.14.
|
|
47
|
-
"core-js": "3.
|
|
48
|
-
"jest": "27.
|
|
49
|
-
"jest-cli": "27.
|
|
45
|
+
"@types/jest": "27.4.1",
|
|
46
|
+
"@types/lodash": "4.14.179",
|
|
47
|
+
"core-js": "3.20.2",
|
|
48
|
+
"jest": "27.5.1",
|
|
49
|
+
"jest-cli": "27.5.1",
|
|
50
50
|
"jest-date-mock": "1.0.8",
|
|
51
51
|
"lodash": "4.17.21",
|
|
52
52
|
"regenerator-runtime": "0.13.9",
|
|
53
53
|
"rimraf": "3.0.2",
|
|
54
|
-
"ts-jest": "27.1.
|
|
55
|
-
"typescript": "4.
|
|
54
|
+
"ts-jest": "27.1.3",
|
|
55
|
+
"typescript": "4.6.2"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"core-js": "
|
|
59
|
-
"lodash": "
|
|
58
|
+
"core-js": "3.20.2",
|
|
59
|
+
"lodash": "4.17.21"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "deb44e2ce6e24626147917c578ade82cf8ad36b6"
|
|
62
62
|
}
|
package/src/config/file-types.js
CHANGED
|
@@ -10,9 +10,9 @@ export const FILE_TYPE_OTHER = 'OTHER';
|
|
|
10
10
|
export const FILE_TYPE_PATTERNS = {
|
|
11
11
|
[FILE_TYPE_CSS]: /\.css$/,
|
|
12
12
|
[FILE_TYPE_JS]: /\.js$/,
|
|
13
|
-
[FILE_TYPE_IMG]: /\.(png|jpe?g|webp|gif|svg|ico)$/,
|
|
14
|
-
[FILE_TYPE_MEDIA]: /\.(mp4|mp3|mov)$/,
|
|
15
|
-
[FILE_TYPE_FONT]: /\.(woff|woff2|ttf|otf)$/,
|
|
13
|
+
[FILE_TYPE_IMG]: /\.(a?png|jpe?g|webp|gif|svg|ico|avif)$/,
|
|
14
|
+
[FILE_TYPE_MEDIA]: /\.(mp4|mp3|m4a|aac|mov|webm|wav|ogg)$/,
|
|
15
|
+
[FILE_TYPE_FONT]: /\.(woff|woff2|ttf|otf|eot)$/,
|
|
16
16
|
[FILE_TYPE_HTML]: /\.(html?)$/,
|
|
17
17
|
};
|
|
18
18
|
|
package/src/constants.ts
CHANGED
|
@@ -47,6 +47,7 @@ export interface Metric {
|
|
|
47
47
|
export interface ModuleMetric extends Metric {
|
|
48
48
|
name: string;
|
|
49
49
|
chunkIds: Array<String>;
|
|
50
|
+
duplicated: boolean;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export interface PackageMetric extends Metric {
|
|
@@ -55,6 +56,8 @@ export interface PackageMetric extends Metric {
|
|
|
55
56
|
|
|
56
57
|
export interface WebpackMetricsModules {
|
|
57
58
|
metrics: {
|
|
59
|
+
duplicateCode: MetricRun;
|
|
60
|
+
duplicateModulesCount: MetricRun;
|
|
58
61
|
modules: Record<string, ModuleMetric>;
|
|
59
62
|
};
|
|
60
63
|
}
|
package/src/i18n.js
CHANGED
|
@@ -6,9 +6,10 @@ export default {
|
|
|
6
6
|
COMPONENT_LINK_BUNDLE_ASSETS_COUNT: 'View all assets',
|
|
7
7
|
COMPONENT_LINK_BUNDLE_ASSETS_CHUNK_COUNT: 'View all chunks',
|
|
8
8
|
COMPONENT_LINK_MODULES: 'View modules',
|
|
9
|
+
COMPONENT_LINK_MODULES_DUPLICATE: 'View duplicate modules',
|
|
9
10
|
COMPONENT_LINK_CHUNK_MODULES: 'View chunk modules',
|
|
10
11
|
COMPONENT_LINK_PACKAGES_COUNT: 'View all packages',
|
|
11
12
|
COMPONENT_LINK_PACKAGES_DUPLICATE: 'View all duplicate packages',
|
|
12
13
|
COMPONENT_LINK_VIEW_PACKAGE: 'View package',
|
|
13
|
-
COMPONENT_LINK_BUNDLE_ASSETS_BY_FILE_TYPE: 'View all <%= label %> assets'
|
|
14
|
+
COMPONENT_LINK_BUNDLE_ASSETS_BY_FILE_TYPE: 'View all <%= label %> assets',
|
|
14
15
|
};
|
package/src/jobs/create-job.js
CHANGED
|
@@ -14,7 +14,7 @@ const GENERIC_PROPS = ['meta', 'insights', 'metrics'];
|
|
|
14
14
|
/*
|
|
15
15
|
* Create job from stats
|
|
16
16
|
*/
|
|
17
|
-
export const createJob = (source, baseline
|
|
17
|
+
export const createJob = (source, baseline) => SOURCE_PATHS.reduce((agg, sourcePath) => {
|
|
18
18
|
const rawData = get(source, sourcePath);
|
|
19
19
|
|
|
20
20
|
if (!rawData) {
|
|
@@ -27,7 +27,7 @@ export const createJob = (source, baseline, options = {}) => SOURCE_PATHS.reduce
|
|
|
27
27
|
return agg;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const extractedData = sourceModule.extract(rawData, baseline
|
|
30
|
+
const extractedData = sourceModule.extract(rawData, baseline);
|
|
31
31
|
const summary = createSummary(
|
|
32
32
|
SOURCE_FNS[sourcePath].SUMMARY_METRIC_PATHS,
|
|
33
33
|
get(baseline, `metrics.${sourcePath}`, {}),
|
package/src/jobs/create-jobs.js
CHANGED
|
@@ -6,9 +6,9 @@ import { createJob } from './create-job';
|
|
|
6
6
|
/*
|
|
7
7
|
* Create jobs from sources
|
|
8
8
|
*/
|
|
9
|
-
export const createJobs = (sources
|
|
9
|
+
export const createJobs = (sources) => {
|
|
10
10
|
const jobs = reverse([...sources]).reduce((agg, source, idx) => {
|
|
11
|
-
const job = createJob(source, last(agg)
|
|
11
|
+
const job = createJob(source, last(agg));
|
|
12
12
|
const internalBuildNumber = job.internalBuildNumber || idx + 1;
|
|
13
13
|
const label = `Job #${internalBuildNumber}`;
|
|
14
14
|
|
|
@@ -45,13 +45,14 @@ export const getModuleSourceTypeFilters = (value = true) => ({
|
|
|
45
45
|
[`${MODULE_SOURCE_TYPE}.${MODULE_FILTERS.THIRD_PARTY}`]: value,
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
export const getModuleChunkFilters = (chunkIds, value) =>
|
|
49
|
-
(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
export const getModuleChunkFilters = (chunkIds, value) =>
|
|
49
|
+
chunkIds.reduce(
|
|
50
|
+
(agg, chunkId) => ({
|
|
51
|
+
...agg,
|
|
52
|
+
[`${MODULE_CHUNK}.${chunkId}`]: value,
|
|
53
|
+
}),
|
|
54
|
+
{},
|
|
55
|
+
);
|
|
55
56
|
|
|
56
57
|
export const getModuleFileTypeFilters = (value = true) =>
|
|
57
58
|
MODULE_SOURCE_FILE_TYPES.reduce(
|
|
@@ -148,6 +149,19 @@ export const BUNDLE_MODULES = {
|
|
|
148
149
|
},
|
|
149
150
|
};
|
|
150
151
|
|
|
152
|
+
export const BUNDLE_MODULES_DUPLICATE = {
|
|
153
|
+
section: SECTIONS.MODULES,
|
|
154
|
+
title: I18N.COMPONENT_LINK_MODULES_DUPLICATE,
|
|
155
|
+
params: {
|
|
156
|
+
[COMPONENT.BUNDLE_MODULES]: {
|
|
157
|
+
filters: {
|
|
158
|
+
[MODULE_FILTERS.CHANGED]: false,
|
|
159
|
+
[MODULE_FILTERS.DUPLICATED]: true,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
151
165
|
export const getBundleModulesBySearch = (search) => ({
|
|
152
166
|
section: SECTIONS.MODULES,
|
|
153
167
|
title: I18N.COMPONENT_LINK_MODULES,
|
|
@@ -257,6 +271,8 @@ export const METRIC_COMPONENT_LINKS = new Map([
|
|
|
257
271
|
['webpack.assetCount', { link: BUNDLE_ASSETS_COUNT }],
|
|
258
272
|
['webpack.chunkCount', { link: BUNDLE_ASSETS_CHUNK_COUNT }],
|
|
259
273
|
['webpack.moduleCount', { link: BUNDLE_MODULES }],
|
|
274
|
+
['webpack.duplicateModulesCount', { link: BUNDLE_MODULES_DUPLICATE }],
|
|
275
|
+
['webpack.duplicateCode', { link: BUNDLE_MODULES_DUPLICATE }],
|
|
260
276
|
['webpack.packageCount', { link: BUNLDE_PACKAGES_COUNT }],
|
|
261
277
|
['webpack.duplicatePackagesCount', { link: BUNDLE_PACKAGES_DUPLICATE }],
|
|
262
278
|
]);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export const SECTION_WEBPACK_STATS = 'stats';
|
|
2
|
+
export const SECTION_WEBPACK_SIZES = 'sizes';
|
|
3
|
+
export const SECTION_WEBPACK_ASSETS = 'assets';
|
|
4
|
+
export const SECTION_WEBPACK_MODULES = 'modules';
|
|
5
|
+
export const SECTION_WEBPACK_PACKAGES = 'packages';
|
|
6
|
+
|
|
7
|
+
export const SECTIONS = [
|
|
8
|
+
SECTION_WEBPACK_STATS,
|
|
9
|
+
SECTION_WEBPACK_SIZES,
|
|
10
|
+
SECTION_WEBPACK_ASSETS,
|
|
11
|
+
SECTION_WEBPACK_MODULES,
|
|
12
|
+
SECTION_WEBPACK_PACKAGES,
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export const SUMMARY_METRIC_PATHS = [
|
|
16
|
+
'totalSizeByTypeALL',
|
|
17
|
+
'totalInitialSizeJS',
|
|
18
|
+
'totalInitialSizeCSS',
|
|
19
|
+
'cacheInvalidation',
|
|
20
|
+
'moduleCount',
|
|
21
|
+
'duplicateModulesCount',
|
|
22
|
+
'duplicateCode',
|
|
23
|
+
'chunkCount',
|
|
24
|
+
'assetCount',
|
|
25
|
+
'packageCount',
|
|
26
|
+
'duplicatePackagesCount',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const PACKAGE_PREFIX = /(?:node_modules|~)(?:\/\.pnpm)?/;
|
|
30
|
+
const PACKAGE_SLUG = /[a-zA-Z0-9]+(?:[-|_|.]+[a-zA-Z0-9]+)*/;
|
|
31
|
+
const VERSION = /@[\w|\-|_|.]+/;
|
|
32
|
+
|
|
33
|
+
// Extract package paths from module path
|
|
34
|
+
// https://regex101.com/r/22Leep/6
|
|
35
|
+
/* eslint-disable prettier/prettier */
|
|
36
|
+
export const MODULE_PATH_PACKAGES = new RegExp(
|
|
37
|
+
[
|
|
38
|
+
// match dependency directory (eg: `node_modules/`, `node_modules/.pnpm/`)
|
|
39
|
+
`(?:${PACKAGE_PREFIX.source}/)`,
|
|
40
|
+
// match package name
|
|
41
|
+
'(?:',
|
|
42
|
+
// match `@organization/` or `@organization+`(pnpm)
|
|
43
|
+
`(?:@${PACKAGE_SLUG.source}[/|+])?`,
|
|
44
|
+
// match github.com+organization+
|
|
45
|
+
`(?:${PACKAGE_SLUG.source}\\+)*`,
|
|
46
|
+
// match package name
|
|
47
|
+
`(?:${PACKAGE_SLUG.source})`,
|
|
48
|
+
// match version
|
|
49
|
+
`(?:${VERSION.source})?`,
|
|
50
|
+
')',
|
|
51
|
+
|
|
52
|
+
// Match pnpm peer dependencies (eg: package-a@version_package-b@version)
|
|
53
|
+
'(?:_',
|
|
54
|
+
`(?:@${PACKAGE_SLUG.source}[/|+])?`,
|
|
55
|
+
`(?:${PACKAGE_SLUG.source})`,
|
|
56
|
+
`(?:@${PACKAGE_SLUG.source})?`,
|
|
57
|
+
')*',
|
|
58
|
+
'/',
|
|
59
|
+
].join(''),
|
|
60
|
+
'g',
|
|
61
|
+
);
|
|
62
|
+
/* eslint-enable prettier/prettier */
|
|
63
|
+
|
|
64
|
+
// Extract package name from package path
|
|
65
|
+
// https://regex101.com/r/tTlU0W/6
|
|
66
|
+
/* eslint-disable prettier/prettier */
|
|
67
|
+
export const PACKAGE_PATH_NAME = new RegExp(
|
|
68
|
+
[
|
|
69
|
+
`(?:${PACKAGE_PREFIX.source}/)`,
|
|
70
|
+
// match dependency
|
|
71
|
+
'(?:',
|
|
72
|
+
'(',
|
|
73
|
+
`(?:@${PACKAGE_SLUG.source}[/|+])?`,
|
|
74
|
+
`(?:(?:${PACKAGE_SLUG.source}\\+)*)`,
|
|
75
|
+
`(?:${PACKAGE_SLUG.source})`,
|
|
76
|
+
')',
|
|
77
|
+
`(?:${VERSION.source})?`,
|
|
78
|
+
')',
|
|
79
|
+
// match peer dependency
|
|
80
|
+
'(?:_',
|
|
81
|
+
'(',
|
|
82
|
+
`(?:@${PACKAGE_SLUG.source}[/|+])?`,
|
|
83
|
+
`(?:${PACKAGE_SLUG.source})`,
|
|
84
|
+
')',
|
|
85
|
+
`(?:@${PACKAGE_SLUG.source})`,
|
|
86
|
+
')*',
|
|
87
|
+
'/',
|
|
88
|
+
].join(''),
|
|
89
|
+
'g',
|
|
90
|
+
);
|
|
91
|
+
/* eslint-enable prettier/prettier */
|
|
@@ -4,21 +4,21 @@ import template from 'lodash/template';
|
|
|
4
4
|
import { INSIGHT_INFO } from '../../config/insights';
|
|
5
5
|
import { getMetricRunInfo } from '../../utils/metrics';
|
|
6
6
|
import { getMetricType } from '../utils';
|
|
7
|
-
import { MetricId } from '../constants';
|
|
8
7
|
|
|
9
8
|
const INFO_TEMPLATE = template(
|
|
10
9
|
'<%= metric %> — <%= displayValue %> (<%= displayDeltaPercentage %>).',
|
|
11
10
|
);
|
|
11
|
+
const METRIC_NAME = 'totalSizeByTypeALL';
|
|
12
12
|
|
|
13
13
|
export const extractAssetsSizeTotalInsight = (
|
|
14
14
|
webpackStats,
|
|
15
15
|
currentExtractedData,
|
|
16
16
|
baselineBundleStats,
|
|
17
17
|
) => {
|
|
18
|
-
const currentValue = get(currentExtractedData, ['metrics',
|
|
19
|
-
const baselineValue = get(baselineBundleStats, ['metrics', 'webpack',
|
|
18
|
+
const currentValue = get(currentExtractedData, ['metrics', METRIC_NAME, 'value'], 0);
|
|
19
|
+
const baselineValue = get(baselineBundleStats, ['metrics', 'webpack', METRIC_NAME, 'value'], 0);
|
|
20
20
|
|
|
21
|
-
const metric = getMetricType(
|
|
21
|
+
const metric = getMetricType(METRIC_NAME);
|
|
22
22
|
const info = getMetricRunInfo(metric, currentValue, baselineValue);
|
|
23
23
|
const { displayDeltaPercentage, displayValue } = info;
|
|
24
24
|
|
|
@@ -4,9 +4,11 @@ import sum from 'lodash/sum';
|
|
|
4
4
|
|
|
5
5
|
import { FILE_TYPE_CSS, FILE_TYPE_JS, FILE_TYPES } from '../../config/file-types';
|
|
6
6
|
import { getFileType } from '../../utils/file-types';
|
|
7
|
-
import { SIZE_BY_TYPE_METRIC_ID_PREFIX, SIZE_BY_TYPE_METRIC_ID_ALL } from '../constants';
|
|
8
7
|
|
|
9
|
-
const
|
|
8
|
+
const METRIC_NAME_ALL = 'ALL';
|
|
9
|
+
const METRIC_NAME_PREFIX = 'totalSizeByType';
|
|
10
|
+
|
|
11
|
+
const getMetricName = (fileType) => `${METRIC_NAME_PREFIX}${fileType}`;
|
|
10
12
|
|
|
11
13
|
const generateInitialSizeByType = () => FILE_TYPES.reduce((accumulator, fileType) => ({
|
|
12
14
|
...accumulator,
|
|
@@ -50,7 +52,7 @@ export const extractAssetsSize = (webpackStats, currentExtractedData) => {
|
|
|
50
52
|
|
|
51
53
|
const sizes = calculateTotalByType(bundleAssets);
|
|
52
54
|
const generic = {
|
|
53
|
-
[getMetricName(
|
|
55
|
+
[getMetricName(METRIC_NAME_ALL)]: {
|
|
54
56
|
value: sum(map(bundleAssets, 'value')),
|
|
55
57
|
},
|
|
56
58
|
...calculateInitialTotals(bundleAssets),
|
|
@@ -12,7 +12,6 @@ import { extractModulesCount } from './modules-count';
|
|
|
12
12
|
import { extractModulesPackages } from './modules-packages';
|
|
13
13
|
import { extractModulesPackagesCount } from './modules-packages-count';
|
|
14
14
|
import { extractModulesPackagesDuplicate } from './modules-packages-duplicate';
|
|
15
|
-
import extractBudgetsInsights from './budgets-insights';
|
|
16
15
|
|
|
17
16
|
const extractFns = [
|
|
18
17
|
extractAssets,
|
|
@@ -27,14 +26,10 @@ const extractFns = [
|
|
|
27
26
|
extractModulesPackages,
|
|
28
27
|
extractModulesPackagesCount,
|
|
29
28
|
extractModulesPackagesDuplicate,
|
|
30
|
-
extractBudgetsInsights,
|
|
31
29
|
];
|
|
32
30
|
|
|
33
|
-
export const extract = (webpackStats, baseline
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
),
|
|
39
|
-
{}
|
|
40
|
-
);
|
|
31
|
+
export const extract = (webpackStats, baseline) => extractFns.reduce((agg, extractFn) => merge(
|
|
32
|
+
{},
|
|
33
|
+
agg,
|
|
34
|
+
extractFn(webpackStats, agg, baseline),
|
|
35
|
+
), {});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import isEmpty from 'lodash/isEmpty';
|
|
2
|
+
import round from 'lodash/round';
|
|
2
3
|
|
|
3
4
|
import { ModuleMetric, WebpackMetricsModules } from '../../constants';
|
|
4
5
|
import { getModuleName, normalizeChunkId } from '../utils';
|
|
@@ -10,7 +11,7 @@ interface WebpackModule {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
interface WebpackModuleWithConcatenatedModules extends WebpackModule {
|
|
13
|
-
modules
|
|
14
|
+
modules: Array<Pick<WebpackModule, 'name' | 'size'>>;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/*
|
|
@@ -20,7 +21,13 @@ export const extractModules = (webpackStats?: any): WebpackMetricsModules => {
|
|
|
20
21
|
const modulesSource: Array<WebpackModuleWithConcatenatedModules> = webpackStats?.modules || [];
|
|
21
22
|
|
|
22
23
|
if (!modulesSource) {
|
|
23
|
-
return {
|
|
24
|
+
return {
|
|
25
|
+
metrics: {
|
|
26
|
+
duplicateCode: { value: 0 },
|
|
27
|
+
duplicateModulesCount: { value: 0 },
|
|
28
|
+
modules: {},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
// Flatten concatenated modules
|
|
@@ -43,25 +50,49 @@ export const extractModules = (webpackStats?: any): WebpackMetricsModules => {
|
|
|
43
50
|
return agg;
|
|
44
51
|
}, [] as Array<WebpackModule>);
|
|
45
52
|
|
|
53
|
+
let totalCodeSize = 0;
|
|
54
|
+
let duplicateCodeSize = 0;
|
|
55
|
+
let duplicateModulesCount = 0;
|
|
56
|
+
|
|
46
57
|
// Normalize module entries
|
|
47
58
|
const modules = allModules.reduce((agg, moduleEntry) => {
|
|
48
59
|
const { name, size, chunks } = moduleEntry;
|
|
49
60
|
const normalizedName = getModuleName(name);
|
|
50
61
|
|
|
51
|
-
// skip modules
|
|
62
|
+
// skip modules that do not belong to any chunk
|
|
52
63
|
if (isEmpty(chunks)) {
|
|
53
64
|
return agg;
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
const instances = chunks.length;
|
|
68
|
+
const duplicateInstances = instances - 1;
|
|
69
|
+
|
|
70
|
+
duplicateModulesCount += duplicateInstances;
|
|
71
|
+
duplicateCodeSize += duplicateInstances * size;
|
|
72
|
+
totalCodeSize += instances * size;
|
|
73
|
+
|
|
56
74
|
// eslint-disable-next-line no-param-reassign
|
|
57
75
|
agg[normalizedName] = {
|
|
58
76
|
name,
|
|
59
77
|
value: size,
|
|
60
78
|
chunkIds: chunks.map(normalizeChunkId),
|
|
79
|
+
duplicated: Boolean(duplicateInstances),
|
|
61
80
|
};
|
|
62
81
|
|
|
63
82
|
return agg;
|
|
64
83
|
}, {} as Record<string, ModuleMetric>);
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
const duplicateCode = totalCodeSize ? round((duplicateCodeSize / totalCodeSize) * 100, 2) : 0;
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
metrics: {
|
|
89
|
+
modules,
|
|
90
|
+
duplicateCode: {
|
|
91
|
+
value: duplicateCode,
|
|
92
|
+
},
|
|
93
|
+
duplicateModulesCount: {
|
|
94
|
+
value: duplicateModulesCount,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
67
98
|
};
|