package-build-stats 8.0.2 → 8.0.3
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.
|
@@ -46,16 +46,31 @@ async function getAllPackageExports(packageString, options = {}) {
|
|
|
46
46
|
}
|
|
47
47
|
async function getPackageExportSizes(packageString, options = {}) {
|
|
48
48
|
const startTime = perf_hooks_1.performance.now();
|
|
49
|
+
const timings = {};
|
|
49
50
|
const { name: packageName, normalPath } = (0, common_utils_1.parsePackageString)(packageString);
|
|
51
|
+
const preparePathStart = perf_hooks_1.performance.now();
|
|
50
52
|
const installPath = await installation_utils_1.default.preparePath(packageName);
|
|
53
|
+
timings.preparePath = perf_hooks_1.performance.now() - preparePathStart;
|
|
54
|
+
console.log(`[PERF] [ExportSizes] preparePath: ${timings.preparePath.toFixed(2)}ms`);
|
|
51
55
|
try {
|
|
56
|
+
const installStart = perf_hooks_1.performance.now();
|
|
52
57
|
await installPackage(packageString, installPath, options);
|
|
58
|
+
timings.install = perf_hooks_1.performance.now() - installStart;
|
|
59
|
+
console.log(`[PERF] [ExportSizes] installPackage: ${timings.install.toFixed(2)}ms`);
|
|
53
60
|
// The package is installed in node_modules subdirectory
|
|
54
61
|
const packagePath = normalPath || path_1.default.join(installPath, 'node_modules', packageName);
|
|
62
|
+
const getAllExportsStart = perf_hooks_1.performance.now();
|
|
55
63
|
const exportMap = await (0, exports_utils_1.getAllExports)(packageString, packagePath, packageName, installPath);
|
|
64
|
+
timings.getAllExports = perf_hooks_1.performance.now() - getAllExportsStart;
|
|
65
|
+
console.log(`[PERF] [ExportSizes] getAllExports: ${timings.getAllExports.toFixed(2)}ms`);
|
|
56
66
|
const exports = Object.keys(exportMap).filter(exp => !(exp === 'default'));
|
|
57
67
|
debug('Got %d exports for %s', exports.length, packageString);
|
|
68
|
+
console.log(`[PERF] [ExportSizes] Found ${exports.length} exports`);
|
|
69
|
+
const externalsStart = perf_hooks_1.performance.now();
|
|
58
70
|
const externals = (0, common_utils_1.getExternals)(packageName, installPath);
|
|
71
|
+
timings.getExternals = perf_hooks_1.performance.now() - externalsStart;
|
|
72
|
+
console.log(`[PERF] [ExportSizes] getExternals: ${timings.getExternals.toFixed(2)}ms`);
|
|
73
|
+
const buildStart = perf_hooks_1.performance.now();
|
|
59
74
|
const builtDetails = await build_utils_1.default.buildPackageIgnoringMissingDeps({
|
|
60
75
|
name: packageName,
|
|
61
76
|
installPath,
|
|
@@ -66,6 +81,8 @@ async function getPackageExportSizes(packageString, options = {}) {
|
|
|
66
81
|
includeDependencySizes: false,
|
|
67
82
|
},
|
|
68
83
|
});
|
|
84
|
+
timings.build = perf_hooks_1.performance.now() - buildStart;
|
|
85
|
+
console.log(`[PERF] [ExportSizes] buildPackage: ${timings.build.toFixed(2)}ms`);
|
|
69
86
|
telemetry_utils_1.default.packageExportsSizes(packageString, startTime, true, options);
|
|
70
87
|
return {
|
|
71
88
|
...builtDetails,
|
package/build/getPackageStats.js
CHANGED
|
@@ -40,9 +40,14 @@ function getPackageJSONDetails(packageName, installPath) {
|
|
|
40
40
|
}
|
|
41
41
|
async function getPackageStats(packageString, options = {}) {
|
|
42
42
|
const startTime = perf_hooks_1.performance.now();
|
|
43
|
+
const timings = {};
|
|
43
44
|
const { name: packageName, isLocal } = (0, common_utils_1.parsePackageString)(packageString);
|
|
45
|
+
const preparePathStart = perf_hooks_1.performance.now();
|
|
44
46
|
const installPath = await installation_utils_1.default.preparePath(packageName, options.client);
|
|
47
|
+
timings.preparePath = perf_hooks_1.performance.now() - preparePathStart;
|
|
48
|
+
console.log(`[PERF] preparePath: ${timings.preparePath.toFixed(2)}ms`);
|
|
45
49
|
try {
|
|
50
|
+
const installStart = perf_hooks_1.performance.now();
|
|
46
51
|
await installation_utils_1.default.installPackage(packageString, installPath, {
|
|
47
52
|
isLocal,
|
|
48
53
|
client: options.client,
|
|
@@ -50,7 +55,13 @@ async function getPackageStats(packageString, options = {}) {
|
|
|
50
55
|
networkConcurrency: options.networkConcurrency,
|
|
51
56
|
installTimeout: options.installTimeout,
|
|
52
57
|
});
|
|
58
|
+
timings.install = perf_hooks_1.performance.now() - installStart;
|
|
59
|
+
console.log(`[PERF] installPackage: ${timings.install.toFixed(2)}ms`);
|
|
60
|
+
const externalsStart = perf_hooks_1.performance.now();
|
|
53
61
|
const externals = (0, common_utils_1.getExternals)(packageName, installPath);
|
|
62
|
+
timings.getExternals = perf_hooks_1.performance.now() - externalsStart;
|
|
63
|
+
console.log(`[PERF] getExternals: ${timings.getExternals.toFixed(2)}ms`);
|
|
64
|
+
const parallelStart = perf_hooks_1.performance.now();
|
|
54
65
|
const [pacakgeJSONDetails, builtDetails] = await Promise.all([
|
|
55
66
|
getPackageJSONDetails(packageName, installPath),
|
|
56
67
|
build_utils_1.default.buildPackageIgnoringMissingDeps({
|
|
@@ -65,6 +76,8 @@ async function getPackageStats(packageString, options = {}) {
|
|
|
65
76
|
},
|
|
66
77
|
}),
|
|
67
78
|
]);
|
|
79
|
+
timings.parallelBuild = perf_hooks_1.performance.now() - parallelStart;
|
|
80
|
+
console.log(`[PERF] parallel (packageJSON + build): ${timings.parallelBuild.toFixed(2)}ms`);
|
|
68
81
|
const hasCSSAsset = builtDetails.assets.some(asset => asset.type === 'css');
|
|
69
82
|
const mainAsset = builtDetails.assets.find(asset => asset.name === 'main' && asset.type === (hasCSSAsset ? 'css' : 'js'));
|
|
70
83
|
if (!mainAsset) {
|
|
@@ -18,9 +18,13 @@ const promises_1 = __importDefault(require("fs/promises"));
|
|
|
18
18
|
const telemetry_utils_1 = __importDefault(require("./telemetry.utils"));
|
|
19
19
|
const perf_hooks_1 = require("perf_hooks");
|
|
20
20
|
// Initialize resolver with ESM-first configuration
|
|
21
|
-
// Following oxc-linter's resolver configuration:
|
|
22
21
|
// - main_fields: ["module", "main"] - prioritize ESM entry points
|
|
23
|
-
// - condition_names: ["
|
|
22
|
+
// - condition_names: ["import", "default", "require"] - ESM-first export conditions
|
|
23
|
+
// NOTE: We intentionally exclude "node" because Node.js conditional exports resolution
|
|
24
|
+
// uses the PACKAGE's exports field order (not our conditionNames order) to determine
|
|
25
|
+
// priority. Packages like Vue have "node" before "import" in their exports, so including
|
|
26
|
+
// "node" would resolve to CJS files instead of ESM. We keep "require" as a fallback for
|
|
27
|
+
// packages that only export via "require" condition.
|
|
24
28
|
// - extensions: all common JS/TS extensions
|
|
25
29
|
// - symlinks: false - keep paths as-is without resolving symlinks (matches enhanced-resolve behavior)
|
|
26
30
|
const resolver = new oxc_resolver_1.ResolverFactory({
|
|
@@ -35,8 +39,8 @@ const resolver = new oxc_resolver_1.ResolverFactory({
|
|
|
35
39
|
'.cts',
|
|
36
40
|
'.json',
|
|
37
41
|
],
|
|
38
|
-
mainFields: ['module', 'main'], // ESM-first: prioritize
|
|
39
|
-
conditionNames: ['import', '
|
|
42
|
+
mainFields: ['module', 'main'], // ESM-first: prioritize "module" field over "main"
|
|
43
|
+
conditionNames: ['import', 'default', 'require'], // ESM-first: exclude "node" which resolves to CJS
|
|
40
44
|
symlinks: false, // Don't resolve symlinks to match enhanced-resolve behavior
|
|
41
45
|
});
|
|
42
46
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "package-build-stats",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.3",
|
|
4
4
|
"author": "Shubham Kanodia <shubham.kanodia10@gmail.com>",
|
|
5
5
|
"repository": "https://github.com/pastelsky/package-build-stats",
|
|
6
6
|
"publishConfig": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"compare:test": "tsx scripts/index.ts test",
|
|
39
39
|
"compare:top": "tsx scripts/index.ts top",
|
|
40
40
|
"compare:advanced": "tsx scripts/index.ts compare",
|
|
41
|
+
"perf:test": "tsx scripts/performance-test.ts",
|
|
41
42
|
"prepublish": "rm -rf build && yarn check && tsc && yarn format"
|
|
42
43
|
},
|
|
43
44
|
"prettier": {
|
|
@@ -62,27 +62,53 @@ export async function getPackageExportSizes(
|
|
|
62
62
|
options: GetPackageStatsOptions = {},
|
|
63
63
|
) {
|
|
64
64
|
const startTime = performance.now()
|
|
65
|
+
const timings: Record<string, number> = {}
|
|
66
|
+
|
|
65
67
|
const { name: packageName, normalPath } = parsePackageString(packageString)
|
|
68
|
+
|
|
69
|
+
const preparePathStart = performance.now()
|
|
66
70
|
const installPath = await InstallationUtils.preparePath(packageName)
|
|
71
|
+
timings.preparePath = performance.now() - preparePathStart
|
|
72
|
+
console.log(
|
|
73
|
+
`[PERF] [ExportSizes] preparePath: ${timings.preparePath.toFixed(2)}ms`,
|
|
74
|
+
)
|
|
67
75
|
|
|
68
76
|
try {
|
|
77
|
+
const installStart = performance.now()
|
|
69
78
|
await installPackage(packageString, installPath, options)
|
|
79
|
+
timings.install = performance.now() - installStart
|
|
80
|
+
console.log(
|
|
81
|
+
`[PERF] [ExportSizes] installPackage: ${timings.install.toFixed(2)}ms`,
|
|
82
|
+
)
|
|
70
83
|
|
|
71
84
|
// The package is installed in node_modules subdirectory
|
|
72
85
|
const packagePath =
|
|
73
86
|
normalPath || path.join(installPath, 'node_modules', packageName)
|
|
87
|
+
|
|
88
|
+
const getAllExportsStart = performance.now()
|
|
74
89
|
const exportMap = await getAllExports(
|
|
75
90
|
packageString,
|
|
76
91
|
packagePath,
|
|
77
92
|
packageName,
|
|
78
93
|
installPath, // Pass installPath as base for relative path calculation
|
|
79
94
|
)
|
|
95
|
+
timings.getAllExports = performance.now() - getAllExportsStart
|
|
96
|
+
console.log(
|
|
97
|
+
`[PERF] [ExportSizes] getAllExports: ${timings.getAllExports.toFixed(2)}ms`,
|
|
98
|
+
)
|
|
80
99
|
|
|
81
100
|
const exports = Object.keys(exportMap).filter(exp => !(exp === 'default'))
|
|
82
101
|
debug('Got %d exports for %s', exports.length, packageString)
|
|
102
|
+
console.log(`[PERF] [ExportSizes] Found ${exports.length} exports`)
|
|
83
103
|
|
|
104
|
+
const externalsStart = performance.now()
|
|
84
105
|
const externals = getExternals(packageName, installPath)
|
|
106
|
+
timings.getExternals = performance.now() - externalsStart
|
|
107
|
+
console.log(
|
|
108
|
+
`[PERF] [ExportSizes] getExternals: ${timings.getExternals.toFixed(2)}ms`,
|
|
109
|
+
)
|
|
85
110
|
|
|
111
|
+
const buildStart = performance.now()
|
|
86
112
|
const builtDetails = await BuildUtils.buildPackageIgnoringMissingDeps({
|
|
87
113
|
name: packageName,
|
|
88
114
|
installPath,
|
|
@@ -93,6 +119,10 @@ export async function getPackageExportSizes(
|
|
|
93
119
|
includeDependencySizes: false,
|
|
94
120
|
},
|
|
95
121
|
})
|
|
122
|
+
timings.build = performance.now() - buildStart
|
|
123
|
+
console.log(
|
|
124
|
+
`[PERF] [ExportSizes] buildPackage: ${timings.build.toFixed(2)}ms`,
|
|
125
|
+
)
|
|
96
126
|
|
|
97
127
|
Telemetry.packageExportsSizes(packageString, startTime, true, options)
|
|
98
128
|
return {
|
package/src/getPackageStats.ts
CHANGED
|
@@ -53,14 +53,20 @@ export default async function getPackageStats(
|
|
|
53
53
|
options: GetPackageStatsOptions = {},
|
|
54
54
|
) {
|
|
55
55
|
const startTime = performance.now()
|
|
56
|
+
const timings: Record<string, number> = {}
|
|
56
57
|
|
|
57
58
|
const { name: packageName, isLocal } = parsePackageString(packageString)
|
|
58
59
|
|
|
60
|
+
const preparePathStart = performance.now()
|
|
59
61
|
const installPath = await InstallationUtils.preparePath(
|
|
60
62
|
packageName,
|
|
61
63
|
options.client,
|
|
62
64
|
)
|
|
65
|
+
timings.preparePath = performance.now() - preparePathStart
|
|
66
|
+
console.log(`[PERF] preparePath: ${timings.preparePath.toFixed(2)}ms`)
|
|
67
|
+
|
|
63
68
|
try {
|
|
69
|
+
const installStart = performance.now()
|
|
64
70
|
await InstallationUtils.installPackage(packageString, installPath, {
|
|
65
71
|
isLocal,
|
|
66
72
|
client: options.client,
|
|
@@ -68,9 +74,15 @@ export default async function getPackageStats(
|
|
|
68
74
|
networkConcurrency: options.networkConcurrency,
|
|
69
75
|
installTimeout: options.installTimeout,
|
|
70
76
|
})
|
|
77
|
+
timings.install = performance.now() - installStart
|
|
78
|
+
console.log(`[PERF] installPackage: ${timings.install.toFixed(2)}ms`)
|
|
71
79
|
|
|
80
|
+
const externalsStart = performance.now()
|
|
72
81
|
const externals = getExternals(packageName, installPath)
|
|
82
|
+
timings.getExternals = performance.now() - externalsStart
|
|
83
|
+
console.log(`[PERF] getExternals: ${timings.getExternals.toFixed(2)}ms`)
|
|
73
84
|
|
|
85
|
+
const parallelStart = performance.now()
|
|
74
86
|
const [pacakgeJSONDetails, builtDetails] = await Promise.all([
|
|
75
87
|
getPackageJSONDetails(packageName, installPath),
|
|
76
88
|
BuildUtils.buildPackageIgnoringMissingDeps({
|
|
@@ -85,6 +97,10 @@ export default async function getPackageStats(
|
|
|
85
97
|
},
|
|
86
98
|
}),
|
|
87
99
|
])
|
|
100
|
+
timings.parallelBuild = performance.now() - parallelStart
|
|
101
|
+
console.log(
|
|
102
|
+
`[PERF] parallel (packageJSON + build): ${timings.parallelBuild.toFixed(2)}ms`,
|
|
103
|
+
)
|
|
88
104
|
|
|
89
105
|
const hasCSSAsset = builtDetails.assets.some(asset => asset.type === 'css')
|
|
90
106
|
const mainAsset = builtDetails.assets.find(
|
|
@@ -13,9 +13,13 @@ import Telemetry from './telemetry.utils'
|
|
|
13
13
|
import { performance } from 'perf_hooks'
|
|
14
14
|
|
|
15
15
|
// Initialize resolver with ESM-first configuration
|
|
16
|
-
// Following oxc-linter's resolver configuration:
|
|
17
16
|
// - main_fields: ["module", "main"] - prioritize ESM entry points
|
|
18
|
-
// - condition_names: ["
|
|
17
|
+
// - condition_names: ["import", "default", "require"] - ESM-first export conditions
|
|
18
|
+
// NOTE: We intentionally exclude "node" because Node.js conditional exports resolution
|
|
19
|
+
// uses the PACKAGE's exports field order (not our conditionNames order) to determine
|
|
20
|
+
// priority. Packages like Vue have "node" before "import" in their exports, so including
|
|
21
|
+
// "node" would resolve to CJS files instead of ESM. We keep "require" as a fallback for
|
|
22
|
+
// packages that only export via "require" condition.
|
|
19
23
|
// - extensions: all common JS/TS extensions
|
|
20
24
|
// - symlinks: false - keep paths as-is without resolving symlinks (matches enhanced-resolve behavior)
|
|
21
25
|
const resolver = new ResolverFactory({
|
|
@@ -30,8 +34,8 @@ const resolver = new ResolverFactory({
|
|
|
30
34
|
'.cts',
|
|
31
35
|
'.json',
|
|
32
36
|
],
|
|
33
|
-
mainFields: ['module', 'main'], // ESM-first: prioritize
|
|
34
|
-
conditionNames: ['import', '
|
|
37
|
+
mainFields: ['module', 'main'], // ESM-first: prioritize "module" field over "main"
|
|
38
|
+
conditionNames: ['import', 'default', 'require'], // ESM-first: exclude "node" which resolves to CJS
|
|
35
39
|
symlinks: false, // Don't resolve symlinks to match enhanced-resolve behavior
|
|
36
40
|
})
|
|
37
41
|
|