package-build-stats 8.0.3 → 8.1.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/build/config/makeRspackConfig.js +7 -1
- package/build/utils/build.utils.js +5 -1
- package/build/utils/exports.utils.d.ts +1 -0
- package/build/utils/exports.utils.js +34 -10
- package/package.json +1 -1
- package/src/config/makeRspackConfig.ts +7 -1
- package/src/utils/build.utils.ts +8 -1
- package/src/utils/exports.utils.ts +48 -12
|
@@ -21,9 +21,15 @@ function makeRspackConfig({ packageName: _packageName, entry, externals, debug:
|
|
|
21
21
|
mode: 'production',
|
|
22
22
|
devtool: _debug ? 'source-map' : false,
|
|
23
23
|
optimization: {
|
|
24
|
-
|
|
24
|
+
// Use 'multiple' to create a separate runtime chunk per entry point
|
|
25
|
+
// 'single' or { name: 'runtime' } shares one runtime across all entries,
|
|
26
|
+
// which breaks tree-shaking when building many exports simultaneously
|
|
27
|
+
runtimeChunk: 'multiple',
|
|
25
28
|
realContentHash: false,
|
|
26
29
|
minimize: minify,
|
|
30
|
+
// Enable tree-shaking optimizations
|
|
31
|
+
usedExports: true, // Mark unused exports for removal
|
|
32
|
+
sideEffects: true, // Respect package.json sideEffects field
|
|
27
33
|
// Rspack automatically uses its built-in default minifiers:
|
|
28
34
|
// - SwcJsMinimizerRspackPlugin for JS (SWC-based, very fast)
|
|
29
35
|
// - LightningCssMinimizerRspackPlugin for CSS (Lightning CSS-based)
|
|
@@ -199,7 +199,11 @@ const BuildUtils = {
|
|
|
199
199
|
gzip,
|
|
200
200
|
};
|
|
201
201
|
};
|
|
202
|
-
const assetStatsPromises = ((_a = jsonStats === null || jsonStats === void 0 ? void 0 : jsonStats.assets) === null || _a === void 0 ? void 0 : _a.filter(asset => {
|
|
202
|
+
const assetStatsPromises = ((_a = jsonStats === null || jsonStats === void 0 ? void 0 : jsonStats.assets) === null || _a === void 0 ? void 0 : _a.filter(asset => {
|
|
203
|
+
var _a;
|
|
204
|
+
return !((_a = asset.chunkNames) === null || _a === void 0 ? void 0 : _a.some(name => name === 'runtime' ||
|
|
205
|
+
(typeof name === 'string' && name.startsWith('runtime~'))));
|
|
206
|
+
}).filter(asset => !asset.name.endsWith('LICENSE.txt')).map(getAssetStats)) || [];
|
|
203
207
|
const assetStats = await Promise.all(assetStatsPromises);
|
|
204
208
|
telemetry_utils_1.default.assetsGZIPParseTime(name, perf_hooks_1.performance.now());
|
|
205
209
|
let dependencySizeResults = {};
|
|
@@ -17,6 +17,7 @@ export declare function getAllExports(packageString: string, context: string, lo
|
|
|
17
17
|
* Get exports details from code (compatibility function)
|
|
18
18
|
*
|
|
19
19
|
* This provides the same API as the existing getExportsDetails for backward compatibility
|
|
20
|
+
* Returns simple string arrays for exports (without moduleRequest info)
|
|
20
21
|
*/
|
|
21
22
|
export declare function getExportsDetails(code: string, filename?: string): {
|
|
22
23
|
exports: string[];
|
|
@@ -51,6 +51,7 @@ function getExportsFromStaticExports(staticExports) {
|
|
|
51
51
|
const exportAllLocations = [];
|
|
52
52
|
staticExports.forEach(staticExport => {
|
|
53
53
|
staticExport.entries.forEach((entry) => {
|
|
54
|
+
var _a, _b;
|
|
54
55
|
// Skip type-only exports (TypeScript type exports)
|
|
55
56
|
if (entry.isType) {
|
|
56
57
|
return;
|
|
@@ -67,10 +68,16 @@ function getExportsFromStaticExports(staticExports) {
|
|
|
67
68
|
case 'None': // export const foo = 1
|
|
68
69
|
// Get the export name
|
|
69
70
|
if (entry.exportName.kind === 'Name' && entry.exportName.name) {
|
|
70
|
-
exports.push(
|
|
71
|
+
exports.push({
|
|
72
|
+
name: entry.exportName.name,
|
|
73
|
+
moduleRequest: (_a = entry.moduleRequest) === null || _a === void 0 ? void 0 : _a.value, // Track the source module for re-exports
|
|
74
|
+
});
|
|
71
75
|
}
|
|
72
76
|
else if (entry.exportName.kind === 'Default') {
|
|
73
|
-
exports.push(
|
|
77
|
+
exports.push({
|
|
78
|
+
name: 'default',
|
|
79
|
+
moduleRequest: (_b = entry.moduleRequest) === null || _b === void 0 ? void 0 : _b.value,
|
|
80
|
+
});
|
|
74
81
|
}
|
|
75
82
|
break;
|
|
76
83
|
}
|
|
@@ -113,15 +120,26 @@ async function walkExportsRecursive(context, lookupPath, visited, rootContext, i
|
|
|
113
120
|
}
|
|
114
121
|
const { exports, exportAllLocations } = getExportsFromStaticExports(parseResult.module.staticExports);
|
|
115
122
|
const resolvedExports = {};
|
|
116
|
-
// Add direct exports from this module
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
// Add direct exports from this module, resolving re-exports to their source files
|
|
124
|
+
for (const exp of exports) {
|
|
125
|
+
let sourcePath = resolvedPath;
|
|
126
|
+
// If this is a re-export (export { foo } from './module'), resolve to the source file
|
|
127
|
+
if (exp.moduleRequest) {
|
|
128
|
+
try {
|
|
129
|
+
sourcePath = await resolveModule(path_1.default.dirname(resolvedPath), exp.moduleRequest);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// If resolution fails, fall back to current file
|
|
133
|
+
sourcePath = resolvedPath;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Use path.relative() to calculate the relative path from root to sourcePath
|
|
119
137
|
// This works correctly since symlinks are not resolved (symlinks: false in resolver config)
|
|
120
138
|
const relativePath = root
|
|
121
|
-
? path_1.default.relative(root,
|
|
122
|
-
: path_1.default.basename(
|
|
123
|
-
resolvedExports[exp] = relativePath;
|
|
124
|
-
}
|
|
139
|
+
? path_1.default.relative(root, sourcePath)
|
|
140
|
+
: path_1.default.basename(sourcePath);
|
|
141
|
+
resolvedExports[exp.name] = relativePath;
|
|
142
|
+
}
|
|
125
143
|
// Recursively process export * statements
|
|
126
144
|
const promises = exportAllLocations.map(async (location) => {
|
|
127
145
|
const starExports = await walkExportsRecursive(path_1.default.dirname(resolvedPath), location, visited, root);
|
|
@@ -166,10 +184,16 @@ async function getAllExports(packageString, context, lookupPath, installPath) {
|
|
|
166
184
|
* Get exports details from code (compatibility function)
|
|
167
185
|
*
|
|
168
186
|
* This provides the same API as the existing getExportsDetails for backward compatibility
|
|
187
|
+
* Returns simple string arrays for exports (without moduleRequest info)
|
|
169
188
|
*/
|
|
170
189
|
function getExportsDetails(code, filename = 'module.js') {
|
|
171
190
|
const parseResult = (0, oxc_parser_1.parseSync)(filename, code, {
|
|
172
191
|
sourceType: 'module',
|
|
173
192
|
});
|
|
174
|
-
|
|
193
|
+
const result = getExportsFromStaticExports(parseResult.module.staticExports);
|
|
194
|
+
// Return simple string array for backward compatibility
|
|
195
|
+
return {
|
|
196
|
+
exports: result.exports.map(exp => exp.name),
|
|
197
|
+
exportAllLocations: result.exportAllLocations,
|
|
198
|
+
};
|
|
175
199
|
}
|
package/package.json
CHANGED
|
@@ -35,9 +35,15 @@ export default function makeRspackConfig({
|
|
|
35
35
|
mode: 'production',
|
|
36
36
|
devtool: _debug ? 'source-map' : false,
|
|
37
37
|
optimization: {
|
|
38
|
-
|
|
38
|
+
// Use 'multiple' to create a separate runtime chunk per entry point
|
|
39
|
+
// 'single' or { name: 'runtime' } shares one runtime across all entries,
|
|
40
|
+
// which breaks tree-shaking when building many exports simultaneously
|
|
41
|
+
runtimeChunk: 'multiple',
|
|
39
42
|
realContentHash: false,
|
|
40
43
|
minimize: minify,
|
|
44
|
+
// Enable tree-shaking optimizations
|
|
45
|
+
usedExports: true, // Mark unused exports for removal
|
|
46
|
+
sideEffects: true, // Respect package.json sideEffects field
|
|
41
47
|
// Rspack automatically uses its built-in default minifiers:
|
|
42
48
|
// - SwcJsMinimizerRspackPlugin for JS (SWC-based, very fast)
|
|
43
49
|
// - LightningCssMinimizerRspackPlugin for CSS (Lightning CSS-based)
|
package/src/utils/build.utils.ts
CHANGED
|
@@ -306,7 +306,14 @@ const BuildUtils = {
|
|
|
306
306
|
|
|
307
307
|
const assetStatsPromises =
|
|
308
308
|
jsonStats?.assets
|
|
309
|
-
?.filter(
|
|
309
|
+
?.filter(
|
|
310
|
+
asset =>
|
|
311
|
+
!asset.chunkNames?.some(
|
|
312
|
+
name =>
|
|
313
|
+
name === 'runtime' ||
|
|
314
|
+
(typeof name === 'string' && name.startsWith('runtime~')),
|
|
315
|
+
),
|
|
316
|
+
)
|
|
310
317
|
.filter(asset => !asset.name.endsWith('LICENSE.txt'))
|
|
311
318
|
.map(getAssetStats) || []
|
|
312
319
|
const assetStats = await Promise.all(assetStatsPromises)
|
|
@@ -39,14 +39,22 @@ const resolver = new ResolverFactory({
|
|
|
39
39
|
symlinks: false, // Don't resolve symlinks to match enhanced-resolve behavior
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Represents a named export with its optional source module
|
|
44
|
+
*/
|
|
45
|
+
type NamedExport = {
|
|
46
|
+
name: string
|
|
47
|
+
moduleRequest?: string // The source module for re-exports like `export { foo } from './module'`
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* Extract export information from parsed oxc module
|
|
44
52
|
*/
|
|
45
53
|
function getExportsFromStaticExports(staticExports: StaticExport[]): {
|
|
46
|
-
exports:
|
|
54
|
+
exports: NamedExport[]
|
|
47
55
|
exportAllLocations: string[]
|
|
48
56
|
} {
|
|
49
|
-
const exports:
|
|
57
|
+
const exports: NamedExport[] = []
|
|
50
58
|
const exportAllLocations: string[] = []
|
|
51
59
|
|
|
52
60
|
staticExports.forEach(staticExport => {
|
|
@@ -69,9 +77,15 @@ function getExportsFromStaticExports(staticExports: StaticExport[]): {
|
|
|
69
77
|
case 'None': // export const foo = 1
|
|
70
78
|
// Get the export name
|
|
71
79
|
if (entry.exportName.kind === 'Name' && entry.exportName.name) {
|
|
72
|
-
exports.push(
|
|
80
|
+
exports.push({
|
|
81
|
+
name: entry.exportName.name,
|
|
82
|
+
moduleRequest: entry.moduleRequest?.value, // Track the source module for re-exports
|
|
83
|
+
})
|
|
73
84
|
} else if (entry.exportName.kind === 'Default') {
|
|
74
|
-
exports.push(
|
|
85
|
+
exports.push({
|
|
86
|
+
name: 'default',
|
|
87
|
+
moduleRequest: entry.moduleRequest?.value,
|
|
88
|
+
})
|
|
75
89
|
}
|
|
76
90
|
break
|
|
77
91
|
}
|
|
@@ -138,16 +152,31 @@ async function walkExportsRecursive(
|
|
|
138
152
|
|
|
139
153
|
const resolvedExports: ResolvedExports = {}
|
|
140
154
|
|
|
141
|
-
// Add direct exports from this module
|
|
142
|
-
|
|
143
|
-
|
|
155
|
+
// Add direct exports from this module, resolving re-exports to their source files
|
|
156
|
+
for (const exp of exports) {
|
|
157
|
+
let sourcePath = resolvedPath
|
|
158
|
+
|
|
159
|
+
// If this is a re-export (export { foo } from './module'), resolve to the source file
|
|
160
|
+
if (exp.moduleRequest) {
|
|
161
|
+
try {
|
|
162
|
+
sourcePath = await resolveModule(
|
|
163
|
+
path.dirname(resolvedPath),
|
|
164
|
+
exp.moduleRequest,
|
|
165
|
+
)
|
|
166
|
+
} catch {
|
|
167
|
+
// If resolution fails, fall back to current file
|
|
168
|
+
sourcePath = resolvedPath
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Use path.relative() to calculate the relative path from root to sourcePath
|
|
144
173
|
// This works correctly since symlinks are not resolved (symlinks: false in resolver config)
|
|
145
174
|
const relativePath = root
|
|
146
|
-
? path.relative(root,
|
|
147
|
-
: path.basename(
|
|
175
|
+
? path.relative(root, sourcePath)
|
|
176
|
+
: path.basename(sourcePath)
|
|
148
177
|
|
|
149
|
-
resolvedExports[exp] = relativePath
|
|
150
|
-
}
|
|
178
|
+
resolvedExports[exp.name] = relativePath
|
|
179
|
+
}
|
|
151
180
|
|
|
152
181
|
// Recursively process export * statements
|
|
153
182
|
const promises = exportAllLocations.map(async location => {
|
|
@@ -214,11 +243,18 @@ export async function getAllExports(
|
|
|
214
243
|
* Get exports details from code (compatibility function)
|
|
215
244
|
*
|
|
216
245
|
* This provides the same API as the existing getExportsDetails for backward compatibility
|
|
246
|
+
* Returns simple string arrays for exports (without moduleRequest info)
|
|
217
247
|
*/
|
|
218
248
|
export function getExportsDetails(code: string, filename = 'module.js') {
|
|
219
249
|
const parseResult = parseSync(filename, code, {
|
|
220
250
|
sourceType: 'module',
|
|
221
251
|
})
|
|
222
252
|
|
|
223
|
-
|
|
253
|
+
const result = getExportsFromStaticExports(parseResult.module.staticExports)
|
|
254
|
+
|
|
255
|
+
// Return simple string array for backward compatibility
|
|
256
|
+
return {
|
|
257
|
+
exports: result.exports.map(exp => exp.name),
|
|
258
|
+
exportAllLocations: result.exportAllLocations,
|
|
259
|
+
}
|
|
224
260
|
}
|