package-build-stats 8.0.0-beta.6 → 8.0.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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/bin/cli.js +5 -0
  4. package/build/common.types.d.ts +10 -13
  5. package/build/common.types.js +0 -1
  6. package/build/config/{index.d.ts → config.d.ts} +0 -2
  7. package/build/config/{index.js → config.js} +0 -2
  8. package/build/config/makeRspackConfig.d.ts +11 -0
  9. package/build/config/makeRspackConfig.js +168 -0
  10. package/build/errors/CustomError.d.ts +0 -1
  11. package/build/errors/CustomError.js +0 -1
  12. package/build/getDependencySizeTree.d.ts +6 -0
  13. package/build/getDependencySizeTree.js +277 -0
  14. package/build/getPackageExportSizes.d.ts +5 -7
  15. package/build/getPackageExportSizes.js +21 -21
  16. package/build/getPackageStats.d.ts +15 -20
  17. package/build/getPackageStats.js +19 -40
  18. package/build/index.d.ts +0 -2
  19. package/build/index.js +6 -5
  20. package/build/utils/build.utils.d.ts +38 -41
  21. package/build/utils/build.utils.js +176 -185
  22. package/build/utils/common.utils.d.ts +2 -23
  23. package/build/utils/common.utils.js +13 -102
  24. package/build/utils/exports.utils.d.ts +18 -11
  25. package/build/utils/exports.utils.js +139 -218
  26. package/build/utils/installation.utils.d.ts +2 -2
  27. package/build/utils/installation.utils.js +107 -39
  28. package/build/utils/telemetry.utils.d.ts +3 -2
  29. package/build/utils/telemetry.utils.js +16 -2
  30. package/package.json +77 -73
  31. package/src/common.types.ts +8 -10
  32. package/src/config/{index.ts → config.ts} +0 -1
  33. package/src/config/makeRspackConfig.ts +188 -0
  34. package/src/getDependencySizeTree.ts +355 -0
  35. package/src/getPackageExportSizes.ts +32 -43
  36. package/src/getPackageStats.ts +31 -78
  37. package/src/index.ts +0 -1
  38. package/src/types/is-valid-npm-name.d.ts +9 -0
  39. package/src/utils/build.utils.ts +232 -264
  40. package/src/utils/common.utils.ts +15 -148
  41. package/src/utils/exports.utils.ts +170 -251
  42. package/src/utils/installation.utils.ts +171 -65
  43. package/src/utils/telemetry.utils.ts +33 -10
  44. package/.parcelrc +0 -37
  45. package/build/common.types.d.ts.map +0 -1
  46. package/build/common.types.js.map +0 -1
  47. package/build/config/index.d.ts.map +0 -1
  48. package/build/config/index.js.map +0 -1
  49. package/build/errors/CustomError.d.ts.map +0 -1
  50. package/build/errors/CustomError.js.map +0 -1
  51. package/build/fixed/fixed/parseReference.js +0 -5388
  52. package/build/fixed/parseReference.js +0 -5388
  53. package/build/getPackageExportSizes.d.ts.map +0 -1
  54. package/build/getPackageExportSizes.js.map +0 -1
  55. package/build/getPackageStats.d.ts.map +0 -1
  56. package/build/getPackageStats.js.map +0 -1
  57. package/build/getParseTime.d.ts +0 -9
  58. package/build/getParseTime.d.ts.map +0 -1
  59. package/build/getParseTime.js +0 -50
  60. package/build/getParseTime.js.map +0 -1
  61. package/build/index.d.ts.map +0 -1
  62. package/build/index.js.map +0 -1
  63. package/build/utils/build.utils.d.ts.map +0 -1
  64. package/build/utils/build.utils.js.map +0 -1
  65. package/build/utils/common.utils.d.ts.map +0 -1
  66. package/build/utils/common.utils.js.map +0 -1
  67. package/build/utils/exports.utils.d.ts.map +0 -1
  68. package/build/utils/exports.utils.js.map +0 -1
  69. package/build/utils/installation.utils.d.ts.map +0 -1
  70. package/build/utils/installation.utils.js.map +0 -1
  71. package/build/utils/telemetry.utils.d.ts.map +0 -1
  72. package/build/utils/telemetry.utils.js.map +0 -1
  73. package/src/errors/CustomError.d.ts +0 -42
  74. package/src/errors/CustomError.js +0 -81
  75. package/src/errors/CustomError.js.map +0 -1
  76. package/src/fixed/parseReference.js +0 -5388
  77. package/src/getParseTime.ts +0 -66
  78. package/src/typings/is-valid-npm-name.d.ts +0 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Shubham Kanodia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ <img src="https://img.shields.io/npm/v/package-build-stats.svg" /> <img src="https://img.shields.io/npm/l/package-build-stats.svg" /> <img src="https://img.shields.io/github/workflow/status/pastelsky/package-build-stats/CI/master"/>
2
+
3
+ This is the function that powers the core of building, minifying and gzipping of packages in bundlephobia.
4
+
5
+ ## Usage
6
+
7
+ ```js
8
+ const { getPackageStats } = require('package-build-stats')
9
+ ```
10
+
11
+ #### Building packages from npm
12
+
13
+ ##### Building the latest stable version
14
+
15
+ ```js
16
+ const results = await getPackageStats('moment')
17
+ ```
18
+
19
+ ##### Building a specific version / tag
20
+
21
+ ```js
22
+ const results = await getPackageStats('moment@2.24.0')
23
+ ```
24
+
25
+ ##### Building local packages (beta)
26
+
27
+ ```js
28
+ const results = await getPackageStats('~/dev/my-npm-package') // must have a package.json
29
+ ```
30
+
31
+ ##### Using different package managers
32
+
33
+ ```js
34
+ // Use Bun for 13x faster installs!
35
+ const results = await getPackageStats('lodash', { client: 'bun' })
36
+
37
+ // Or use pnpm
38
+ const results = await getPackageStats('lodash', { client: 'pnpm' })
39
+
40
+ // Or use yarn
41
+ const results = await getPackageStats('lodash', { client: 'yarn' })
42
+ ```
43
+
44
+ #### Passing options to the build
45
+
46
+ ```js
47
+ const results = await getBuiltPackageStats('moment', options)
48
+ ```
49
+
50
+ ##### Options
51
+
52
+ | Option | Values | Default | Description |
53
+ | ------------------ | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | client | `npm`, `yarn`, `pnpm`, or `bun` | `npm` | Which client to use to install package for building. **Bun is 13x faster!** |
55
+ | limitConcurrency | `true` or `false` | `false` | When using `yarn` as the client, use the network mutex to limit concurrency |
56
+ | networkConcurrency | `number` | `false` | When using `yarn` or `bun` as client, limit simultaneous installs to this number. |
57
+ | customImports | `Array<string>` | `null` | By default, the default export is used for calculating sizes. Setting this option allows calculation of package stats based on more granular top-level exports. |
58
+ | minifier | `terser` or `esbuild` | `terser` | ESbuild is faster, albeit with marginally larger file sizes |
59
+ | installTimeout | number (ms) | 30000 | Timeout for package install |
60
+
61
+ ## Listening to events
62
+
63
+ `package-build-stats` emits various lifecycle events when building a package.
64
+ You can listen to these events by subscribing to the event emitter (based on [mitt](https://github.com/developit/mitt)).
65
+
66
+ ```js
67
+ import { eventQueue } from 'package-build-stats'
68
+
69
+ // Listen to all events
70
+ eventQueue.on('*', callback)
71
+
72
+ // Listen to specific events
73
+ eventQueue.on('TASK_PACKAGE_BUILD', callback)
74
+ ```
75
+
76
+ For a list of all events, see [this](src/utils/telemetry.utils.ts).
77
+
78
+ ## Contributing
79
+
80
+ See [contributing guide.](CONTRIBUTING.md)
package/bin/cli.js ADDED
@@ -0,0 +1,5 @@
1
+ require('esbuild-register/dist/node').register({
2
+ target: 'es2020',
3
+ })
4
+
5
+ require('./cli.ts')
@@ -1,29 +1,26 @@
1
- export declare type Minifier = 'esbuild' | 'terser';
2
- export declare type AllOptions = {
1
+ type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
2
+ type AllOptions = {
3
3
  customImports?: Array<string>;
4
4
  splitCustomImports?: boolean;
5
5
  debug?: boolean;
6
- calcParse?: boolean;
6
+ minify?: boolean;
7
7
  esm?: boolean;
8
8
  entryFilename?: string;
9
- client?: 'npm' | 'yarn';
9
+ client?: PackageManager | PackageManager[];
10
10
  limitConcurrency?: boolean;
11
11
  networkConcurrency?: number;
12
12
  additionalPackages?: Array<string>;
13
13
  isLocal?: boolean;
14
14
  installTimeout?: number;
15
15
  };
16
- export declare type BuildPackageOptions = Pick<AllOptions, 'customImports' | 'splitCustomImports' | 'debug' | 'calcParse'> & {
16
+ export type BuildPackageOptions = Pick<AllOptions, 'customImports' | 'splitCustomImports' | 'debug' | 'minify'> & {
17
17
  includeDependencySizes: boolean;
18
- minifier: Minifier;
19
18
  };
20
- export declare type CreateEntryPointOptions = Pick<AllOptions, 'esm' | 'customImports' | 'entryFilename'>;
21
- export declare type InstallPackageOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'additionalPackages' | 'isLocal' | 'installTimeout'>;
22
- export declare type GetPackageStatsOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'debug' | 'customImports' | 'installTimeout'> & {
23
- minifier?: Minifier;
24
- };
25
- export declare type Externals = {
19
+ export type CreateEntryPointOptions = Pick<AllOptions, 'esm' | 'customImports' | 'entryFilename'>;
20
+ export type InstallPackageOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'additionalPackages' | 'isLocal' | 'installTimeout' | 'debug'>;
21
+ export type GetPackageStatsOptions = Pick<AllOptions, 'client' | 'limitConcurrency' | 'networkConcurrency' | 'debug' | 'customImports' | 'installTimeout' | 'minify'>;
22
+ export type Externals = {
26
23
  externalPackages: Array<string>;
27
24
  externalBuiltIns: Array<string>;
28
25
  };
29
- //# sourceMappingURL=common.types.d.ts.map
26
+ export {};
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=common.types.js.map
@@ -1,6 +1,4 @@
1
1
  declare const _default: {
2
2
  tmp: string;
3
- compileConcurrency: number;
4
3
  };
5
4
  export default _default;
6
- //# sourceMappingURL=index.d.ts.map
@@ -7,6 +7,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const path_1 = __importDefault(require("path"));
8
8
  exports.default = {
9
9
  tmp: path_1.default.join('/tmp', 'tmp-build'),
10
- compileConcurrency: 2,
11
10
  };
12
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ import type { Entry, Configuration } from '@rspack/core';
2
+ import { Externals } from '../common.types';
3
+ type MakeRspackConfigOptions = {
4
+ packageName: string;
5
+ externals: Externals;
6
+ debug?: boolean;
7
+ minify?: boolean;
8
+ entry: Entry;
9
+ };
10
+ export default function makeRspackConfig({ packageName: _packageName, entry, externals, debug: _debug, minify, }: MakeRspackConfigOptions): Configuration;
11
+ export {};
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = makeRspackConfig;
7
+ const autoprefixer_1 = __importDefault(require("autoprefixer"));
8
+ const escape_string_regexp_1 = __importDefault(require("escape-string-regexp"));
9
+ const core_1 = __importDefault(require("@rspack/core"));
10
+ function makeRspackConfig({ packageName: _packageName, entry, externals, debug: _debug, minify = true, }) {
11
+ const externalsRegex = makeExternalsRegex(externals.externalPackages);
12
+ const isExternalRequest = (request) => {
13
+ const isPeerDep = externals.externalPackages.length
14
+ ? externalsRegex.test(request)
15
+ : false;
16
+ const isBuiltIn = externals.externalBuiltIns.includes(request);
17
+ return isPeerDep || isBuiltIn;
18
+ };
19
+ const configuration = {
20
+ entry: entry,
21
+ mode: 'production',
22
+ devtool: _debug ? 'source-map' : false,
23
+ optimization: {
24
+ runtimeChunk: { name: 'runtime' },
25
+ realContentHash: false,
26
+ minimize: minify,
27
+ // Rspack automatically uses its built-in default minifiers:
28
+ // - SwcJsMinimizerRspackPlugin for JS (SWC-based, very fast)
29
+ // - LightningCssMinimizerRspackPlugin for CSS (Lightning CSS-based)
30
+ // See: https://rspack.rs/guide/optimization/production
31
+ splitChunks: {
32
+ cacheGroups: {
33
+ styles: {
34
+ name: 'main',
35
+ test: /\.css$/,
36
+ chunks: 'all',
37
+ },
38
+ },
39
+ },
40
+ },
41
+ stats: {
42
+ source: true,
43
+ modules: true,
44
+ nestedModules: true,
45
+ reasons: true,
46
+ depth: true,
47
+ chunkModules: true,
48
+ },
49
+ resolve: {
50
+ modules: ['node_modules'],
51
+ extensions: [
52
+ '.web.mjs',
53
+ '.mjs',
54
+ '.web.js',
55
+ '.js',
56
+ '.mjs',
57
+ '.json',
58
+ '.css',
59
+ '.sass',
60
+ '.scss',
61
+ ],
62
+ mainFields: ['browser', 'module', 'main', 'style'],
63
+ },
64
+ module: {
65
+ rules: [
66
+ {
67
+ type: 'javascript/auto',
68
+ test: /\.mjs$/,
69
+ use: [],
70
+ },
71
+ {
72
+ test: /\.css$/,
73
+ type: 'javascript/auto',
74
+ use: [
75
+ core_1.default.CssExtractRspackPlugin.loader,
76
+ require.resolve('css-loader'),
77
+ ],
78
+ },
79
+ {
80
+ test: /\.(html|svelte)$/,
81
+ use: {
82
+ loader: require.resolve('svelte-loader'),
83
+ options: {
84
+ emitCss: true,
85
+ },
86
+ },
87
+ },
88
+ // {
89
+ // test: /\.vue$/,
90
+ // loader: require.resolve('vue-loader'),
91
+ // },
92
+ {
93
+ test: /\.(scss|sass)$/,
94
+ type: 'javascript/auto',
95
+ use: [
96
+ core_1.default.CssExtractRspackPlugin.loader,
97
+ require.resolve('css-loader'),
98
+ {
99
+ loader: require.resolve('postcss-loader'),
100
+ options: {
101
+ postcssOptions: {
102
+ plugins: [(0, autoprefixer_1.default)()],
103
+ },
104
+ },
105
+ },
106
+ require.resolve('sass-loader'),
107
+ ],
108
+ },
109
+ {
110
+ test: /\.less$/,
111
+ type: 'javascript/auto',
112
+ use: [
113
+ core_1.default.CssExtractRspackPlugin.loader,
114
+ require.resolve('css-loader'),
115
+ {
116
+ loader: require.resolve('postcss-loader'),
117
+ options: {
118
+ postcssOptions: {
119
+ plugins: [
120
+ (0, autoprefixer_1.default)({
121
+ overrideBrowserslist: [
122
+ 'last 5 Chrome versions',
123
+ 'last 5 Firefox versions',
124
+ 'Safari >= 8',
125
+ 'Explorer >= 10',
126
+ 'edge >= 12',
127
+ ],
128
+ }),
129
+ ],
130
+ },
131
+ },
132
+ },
133
+ {
134
+ loader: require.resolve('less-loader'),
135
+ options: {
136
+ lessOptions: {
137
+ javascriptEnabled: true,
138
+ },
139
+ },
140
+ },
141
+ ],
142
+ },
143
+ ],
144
+ },
145
+ plugins: [
146
+ new core_1.default.CssExtractRspackPlugin({
147
+ filename: '[name].bundle.css',
148
+ }),
149
+ ],
150
+ node: {
151
+ global: false,
152
+ },
153
+ output: {
154
+ filename: '[name].bundle.js',
155
+ },
156
+ externals: ({ request }, callback) => isExternalRequest(request || '')
157
+ ? callback(undefined, 'commonjs ' + request)
158
+ : callback(undefined),
159
+ };
160
+ return configuration;
161
+ }
162
+ function makeExternalsRegex(externals) {
163
+ let externalsRegex = externals
164
+ .map(dep => `^${(0, escape_string_regexp_1.default)(dep)}$|^${(0, escape_string_regexp_1.default)(dep)}\\/`)
165
+ .join('|');
166
+ externalsRegex = `(${externalsRegex})`;
167
+ return new RegExp(externalsRegex);
168
+ }
@@ -40,4 +40,3 @@ export declare class UnexpectedBuildError extends CustomError {
40
40
  constructor(originalError: any, extra?: any);
41
41
  }
42
42
  export {};
43
- //# sourceMappingURL=CustomError.d.ts.map
@@ -78,4 +78,3 @@ class UnexpectedBuildError extends CustomError {
78
78
  }
79
79
  }
80
80
  exports.UnexpectedBuildError = UnexpectedBuildError;
81
- //# sourceMappingURL=CustomError.js.map
@@ -0,0 +1,6 @@
1
+ type RspackStatsCompilation = NonNullable<ReturnType<NonNullable<import('@rspack/core').Stats['toJson']>>>;
2
+ declare function bundleSizeTree(packageName: string, stats: RspackStatsCompilation): Promise<{
3
+ name: string;
4
+ approximateSize: number;
5
+ }[]>;
6
+ export default bundleSizeTree;
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
7
+ const core_1 = require("@swc/core");
8
+ const CustomError_1 = require("./errors/CustomError");
9
+ const telemetry_utils_1 = __importDefault(require("./utils/telemetry.utils"));
10
+ const perf_hooks_1 = require("perf_hooks");
11
+ function modulePath(identifier) {
12
+ // the format of module paths is
13
+ // '(<loader expression>!)?/path/to/module.js'
14
+ // OR
15
+ // 'javascript/esm|/some/path'
16
+ let loaderRegex = /.*!/;
17
+ const withoutLoader = identifier.replace(loaderRegex, '');
18
+ if (withoutLoader.includes('|'))
19
+ return withoutLoader.split('|')[1];
20
+ return withoutLoader;
21
+ }
22
+ function getUtf8Size(value) {
23
+ const size = Buffer.byteLength(value, 'utf8');
24
+ if (process.env.DEBUG_SIZE && Math.random() < 0.01) {
25
+ // Only debug 1% to avoid spam
26
+ console.log(`Size: ${size} bytes`);
27
+ }
28
+ return size;
29
+ }
30
+ /**
31
+ * Extract all package names from a module path to build a dependency chain.
32
+ * For example: /node_modules/a/node_modules/b/index.js returns ['a', 'b']
33
+ * This preserves the old behavior of showing nested dependencies.
34
+ */
35
+ function extractPackageNamesFromPath(moduleFilePath) {
36
+ // pnpm will serve packages from a global symlink (.pnpm/package@version/node_modules/package)
37
+ // needs to be stripped off
38
+ const pnpmPrefix = '.pnpm\\' + path_1.default.sep + '.+\\' + path_1.default.sep + 'node_modules\\' + path_1.default.sep;
39
+ const packages = moduleFilePath.split(new RegExp('\\' + path_1.default.sep + 'node_modules\\' + path_1.default.sep + `(?:${pnpmPrefix})?`));
40
+ if (packages.length <= 1)
41
+ return [];
42
+ const lastSegment = packages.pop();
43
+ if (!lastSegment)
44
+ return [];
45
+ // Extract the package name from the last segment
46
+ let lastPackageName;
47
+ if (lastSegment[0] === '@') {
48
+ // package is a scoped package
49
+ const offset = lastSegment.indexOf(path_1.default.sep) + 1;
50
+ lastPackageName = lastSegment.slice(0, offset + lastSegment.slice(offset).indexOf(path_1.default.sep));
51
+ }
52
+ else {
53
+ lastPackageName = lastSegment.slice(0, lastSegment.indexOf(path_1.default.sep));
54
+ }
55
+ packages.push(lastPackageName);
56
+ packages.shift(); // Remove the first empty element
57
+ return packages;
58
+ }
59
+ async function minifyDependencyCode(source) {
60
+ if (process.env.DEBUG_SIZE) {
61
+ console.log('Minifying dependency code...');
62
+ }
63
+ try {
64
+ const startTime = Date.now();
65
+ const result = await (0, core_1.minify)(source, {
66
+ compress: true,
67
+ mangle: true,
68
+ module: true, // Treat as ES module to support import/export
69
+ });
70
+ const minifyTime = Date.now() - startTime;
71
+ if (process.env.DEBUG_SIZE) {
72
+ console.log(`Minify completed in ${minifyTime}ms`);
73
+ }
74
+ return { code: result.code };
75
+ }
76
+ catch (error) {
77
+ if (process.env.DEBUG_SIZE) {
78
+ console.log('Minify error occurred');
79
+ }
80
+ console.error('SWC minify error:', error);
81
+ throw error;
82
+ }
83
+ }
84
+ function normaliseModuleSource(mod) {
85
+ const identifier = mod.identifier || '';
86
+ const isJSON = identifier.endsWith('.json');
87
+ const rawSource = mod.source;
88
+ if (process.env.DEBUG_SIZE) {
89
+ console.log(`Normalising module: ${identifier}`);
90
+ }
91
+ if (rawSource === undefined || rawSource === null) {
92
+ if (process.env.DEBUG_SIZE) {
93
+ console.log(`No source for module: ${identifier}`);
94
+ }
95
+ return null;
96
+ }
97
+ let source;
98
+ if (typeof rawSource === 'string') {
99
+ source = rawSource;
100
+ if (process.env.DEBUG_SIZE) {
101
+ console.log(`Source is string`);
102
+ }
103
+ }
104
+ else if (Buffer.isBuffer(rawSource)) {
105
+ source = rawSource.toString('utf8');
106
+ if (process.env.DEBUG_SIZE) {
107
+ console.log(`Source is buffer`);
108
+ }
109
+ }
110
+ else {
111
+ source = String(rawSource);
112
+ if (process.env.DEBUG_SIZE) {
113
+ console.log(`Source is other type`);
114
+ }
115
+ }
116
+ const finalSource = isJSON ? `$a$=${source}` : source;
117
+ if (process.env.DEBUG_SIZE) {
118
+ console.log(`Module source normalised (length: ${finalSource.length})`);
119
+ }
120
+ return finalSource;
121
+ }
122
+ async function bundleSizeTree(packageName, stats) {
123
+ const startTime = perf_hooks_1.performance.now();
124
+ const statsTree = {
125
+ packageName: '<root>',
126
+ sources: [],
127
+ children: [],
128
+ };
129
+ if (!stats.modules)
130
+ return [];
131
+ // Collect modules with their sources
132
+ const modules = [];
133
+ const makeModule = (mod) => {
134
+ const identifier = mod.identifier || '';
135
+ const resolvedPath = modulePath(identifier);
136
+ const source = normaliseModuleSource(mod);
137
+ if (!source)
138
+ return null;
139
+ return {
140
+ path: resolvedPath,
141
+ source,
142
+ };
143
+ };
144
+ const filteredModules = stats.modules.filter(mod => { var _a; return !(((_a = mod.name) === null || _a === void 0 ? void 0 : _a.startsWith('external')) || mod.moduleType === 'runtime'); });
145
+ if (process.env.DEBUG_SIZE) {
146
+ console.log(`\n[LOCAL] ==================== ${packageName} ====================`);
147
+ }
148
+ filteredModules.forEach(mod => {
149
+ if (mod.modules) {
150
+ if (process.env.DEBUG_SIZE) {
151
+ console.log(`Module has ${mod.modules.length} sub-modules`);
152
+ }
153
+ mod.modules.forEach(subMod => {
154
+ const made = makeModule(subMod);
155
+ if (made)
156
+ modules.push(made);
157
+ });
158
+ }
159
+ else {
160
+ const made = makeModule(mod);
161
+ if (made)
162
+ modules.push(made);
163
+ }
164
+ });
165
+ if (process.env.DEBUG_SIZE) {
166
+ console.log(`Collected ${modules.length} total modules`);
167
+ }
168
+ modules.sort((a, b) => {
169
+ if (a === b) {
170
+ return 0;
171
+ }
172
+ else {
173
+ return a < b ? -1 : 1;
174
+ }
175
+ });
176
+ // Build tree structure from module paths
177
+ modules.forEach((mod, modIndex) => {
178
+ const packages = extractPackageNamesFromPath(mod.path);
179
+ if (process.env.DEBUG_SIZE && modIndex < 5) {
180
+ console.log(`[${modIndex}] Extracted packages: ${packages.join(' > ')}`);
181
+ }
182
+ if (packages.length === 0) {
183
+ if (process.env.DEBUG_SIZE && modIndex < 5) {
184
+ console.log(`[${modIndex}] No packages found in path`);
185
+ }
186
+ return;
187
+ }
188
+ let parent = statsTree;
189
+ packages.forEach((pkg, pkgIndex) => {
190
+ const existing = parent.children.filter(child => child.packageName === pkg);
191
+ if (existing.length > 0) {
192
+ existing[0].sources.push(mod.source);
193
+ if (process.env.DEBUG_SIZE && modIndex < 5) {
194
+ console.log(`[${modIndex}] Added to existing package: ${pkg}`);
195
+ }
196
+ parent = existing[0];
197
+ }
198
+ else {
199
+ const newChild = {
200
+ path: mod.path,
201
+ packageName: pkg,
202
+ sources: [mod.source],
203
+ children: [],
204
+ };
205
+ parent.children.push(newChild);
206
+ if (process.env.DEBUG_SIZE && modIndex < 5) {
207
+ console.log(`[${modIndex}] Created new package: ${pkg}`);
208
+ }
209
+ parent = newChild;
210
+ }
211
+ });
212
+ });
213
+ // The old webpack implementation returned only the first-level children
214
+ // We need to preserve that behavior
215
+ const flattenedItems = statsTree.children;
216
+ if (process.env.DEBUG_SIZE) {
217
+ console.log(`\n[LOCAL] Tree structure built with ${flattenedItems.length} top-level dependencies:`);
218
+ }
219
+ const resultPromises = flattenedItems
220
+ .map(treeItem => ({
221
+ ...treeItem,
222
+ sources: treeItem.sources.filter(source => !!source),
223
+ }))
224
+ .filter(treeItem => treeItem.sources.length)
225
+ .map(async (treeItem) => {
226
+ if (process.env.DEBUG_SIZE) {
227
+ console.log(`\n[LOCAL] Processing dependency: ${treeItem.packageName}`);
228
+ }
229
+ const sourceMinifiedPromises = treeItem.sources.map(async (code, idx) => {
230
+ const originalSize = getUtf8Size(code);
231
+ if (process.env.DEBUG_SIZE) {
232
+ console.log(`Source ${idx}: ${originalSize} bytes (original)`);
233
+ }
234
+ const minified = await minifyDependencyCode(code);
235
+ const minifiedSize = getUtf8Size(minified.code || '');
236
+ const minifiedCode = minified.code || '';
237
+ if (process.env.DEBUG_SIZE) {
238
+ console.log(`Source ${idx}: ${minifiedSize} bytes (minified)`);
239
+ }
240
+ return minified;
241
+ });
242
+ try {
243
+ const sources = await Promise.all(sourceMinifiedPromises);
244
+ const size = sources.reduce((acc, source, idx) => {
245
+ const sourceSize = getUtf8Size(source.code || '');
246
+ if (process.env.DEBUG_SIZE) {
247
+ console.log(`Total accumulation at idx ${idx}: ${acc + sourceSize} bytes`);
248
+ }
249
+ return acc + sourceSize;
250
+ }, 0);
251
+ if (process.env.DEBUG_SIZE) {
252
+ console.log(`Final size for ${treeItem.packageName}: ${size} bytes`);
253
+ }
254
+ return {
255
+ name: treeItem.packageName,
256
+ approximateSize: size,
257
+ };
258
+ }
259
+ catch (error) {
260
+ const { message, filename } = error;
261
+ throw new CustomError_1.MinifyError(error, {
262
+ message: message,
263
+ filePath: filename,
264
+ });
265
+ }
266
+ });
267
+ try {
268
+ const results = await Promise.all(resultPromises);
269
+ telemetry_utils_1.default.dependencySizes(packageName, startTime, true, { minifier: 'swc' });
270
+ return results;
271
+ }
272
+ catch (e) {
273
+ telemetry_utils_1.default.dependencySizes(packageName, startTime, false, { minifier: 'swc' }, e);
274
+ throw e;
275
+ }
276
+ }
277
+ exports.default = bundleSizeTree;
@@ -2,19 +2,17 @@ import { GetPackageStatsOptions, InstallPackageOptions } from './common.types';
2
2
  export declare function getAllPackageExports(packageString: string, options?: InstallPackageOptions): Promise<{
3
3
  [key: string]: string;
4
4
  }>;
5
- export declare function getExportSize(packageString: string, exportName: string): Promise<void>;
6
5
  export declare function getPackageExportSizes(packageString: string, options?: GetPackageStatsOptions): Promise<{
7
- buildVersion: any;
8
6
  assets: {
9
7
  path: string;
10
8
  name: string;
11
9
  type: string;
12
10
  size: number;
13
11
  gzip: number;
14
- parse: {
15
- baseParseTime?: number | undefined;
16
- scriptParseTime?: number | undefined;
17
- } | null;
18
12
  }[];
13
+ dependencySizes?: Array<{
14
+ name: string;
15
+ approximateSize: number;
16
+ }>;
17
+ ignoredMissingDependencies?: Array<string>;
19
18
  }>;
20
- //# sourceMappingURL=getPackageExportSizes.d.ts.map