1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = generateBuildMetrics;
|
7 |
|
8 | var _sourceMap = _interopRequireDefault(require("@parcel/source-map"));
|
9 |
|
10 | var _nullthrows = _interopRequireDefault(require("nullthrows"));
|
11 |
|
12 | var _path = _interopRequireDefault(require("path"));
|
13 |
|
14 | var _ = require("./");
|
15 |
|
16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
17 |
|
18 | async function getSourcemapSizes(filePath, fs, projectRoot) {
|
19 | let bundleContents = await fs.readFile(filePath, 'utf-8');
|
20 | let mapUrlData = await (0, _.loadSourceMapUrl)(fs, filePath, bundleContents);
|
21 |
|
22 | if (!mapUrlData) {
|
23 | return null;
|
24 | }
|
25 |
|
26 | let rawMap = mapUrlData.map;
|
27 | let sourceMap = new _sourceMap.default();
|
28 | sourceMap.addRawMappings(rawMap);
|
29 | let parsedMapData = sourceMap.getMap();
|
30 |
|
31 | if (parsedMapData.mappings.length > 2) {
|
32 | let sources = parsedMapData.sources.map(s => _path.default.normalize(_path.default.join(projectRoot, s)));
|
33 | let currLine = 1;
|
34 | let currColumn = 0;
|
35 | let currMappingIndex = 0;
|
36 | let currMapping = parsedMapData.mappings[currMappingIndex];
|
37 | let nextMapping = parsedMapData.mappings[currMappingIndex + 1];
|
38 | let sourceSizes = new Array(sources.length).fill(0);
|
39 | let unknownOrigin = 0;
|
40 |
|
41 | for (let i = 0; i < bundleContents.length; i++) {
|
42 | let character = bundleContents[i];
|
43 |
|
44 | while (nextMapping && nextMapping.generated.line === currLine && nextMapping.generated.column <= currColumn) {
|
45 | currMappingIndex++;
|
46 | currMapping = parsedMapData.mappings[currMappingIndex];
|
47 | nextMapping = parsedMapData.mappings[currMappingIndex + 1];
|
48 | }
|
49 |
|
50 | let currentSource = currMapping.source;
|
51 | let charSize = Buffer.byteLength(character, 'utf8');
|
52 |
|
53 | if (currentSource != null && currMapping.generated.line === currLine && currMapping.generated.column <= currColumn) {
|
54 | sourceSizes[currentSource] += charSize;
|
55 | } else {
|
56 | unknownOrigin += charSize;
|
57 | }
|
58 |
|
59 | if (character === '\n') {
|
60 | currColumn = 0;
|
61 | currLine++;
|
62 | } else {
|
63 | currColumn++;
|
64 | }
|
65 | }
|
66 |
|
67 | let sizeMap = new Map();
|
68 |
|
69 | for (let i = 0; i < sourceSizes.length; i++) {
|
70 | sizeMap.set(sources[i], sourceSizes[i]);
|
71 | }
|
72 |
|
73 | sizeMap.set('', unknownOrigin);
|
74 | return sizeMap;
|
75 | }
|
76 | }
|
77 |
|
78 | async function createBundleStats(bundle, fs, projectRoot) {
|
79 | let filePath = bundle.filePath;
|
80 | let sourcemapSizes = await getSourcemapSizes(filePath, fs, projectRoot);
|
81 | let assets = new Map();
|
82 | bundle.traverseAssets(asset => {
|
83 | let filePath = _path.default.normalize(asset.filePath);
|
84 |
|
85 | assets.set(filePath, {
|
86 | filePath,
|
87 | size: asset.stats.size,
|
88 | originalSize: asset.stats.size,
|
89 | time: asset.stats.time
|
90 | });
|
91 | });
|
92 | let assetsReport = [];
|
93 |
|
94 | if (sourcemapSizes && sourcemapSizes.size) {
|
95 | assetsReport = Array.from(sourcemapSizes.keys()).map(filePath => {
|
96 | let foundSize = sourcemapSizes.get(filePath) || 0;
|
97 | let stats = assets.get(filePath) || {
|
98 | filePath,
|
99 | size: foundSize,
|
100 | originalSize: foundSize,
|
101 | time: 0
|
102 | };
|
103 | return { ...stats,
|
104 | size: foundSize
|
105 | };
|
106 | });
|
107 | } else {
|
108 | assetsReport = Array.from(assets.values());
|
109 | }
|
110 |
|
111 | return {
|
112 | filePath: (0, _nullthrows.default)(bundle.filePath),
|
113 | size: bundle.stats.size,
|
114 | time: bundle.stats.time,
|
115 | assets: assetsReport.sort((a, b) => b.size - a.size)
|
116 | };
|
117 | }
|
118 |
|
119 | async function generateBuildMetrics(bundles, fs, projectRoot) {
|
120 | bundles.sort((a, b) => b.stats.size - a.stats.size).filter(b => !!b.filePath);
|
121 | return {
|
122 | bundles: (await Promise.all(bundles.map(b => createBundleStats(b, fs, projectRoot)))).filter(e => !!e)
|
123 | };
|
124 | } |
\ | No newline at end of file |