Skip to content

Commit a74bd22

Browse files
authored
fix: json module's size problem (#1424)
1 parent f368b80 commit a74bd22

5 files changed

Lines changed: 220 additions & 2 deletions

File tree

packages/core/src/inner-plugins/plugins/ensureModulesChunkGraph.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ async function doneHandler(
137137
hash: true,
138138
errors: true,
139139
warnings: true,
140+
nestedModules: true,
141+
cachedModules: true,
142+
orphanModules: true,
143+
runtimeModules: true,
140144
});
141145
return cached;
142146
};

packages/graph/src/transform/module-graph/transform.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ function getGetModuleName(root: string, data: Plugin.StatsModule) {
2323
return path.isAbsolute(name) ? name : path.join(root, name);
2424
}
2525

26+
function isJsonFile(filePath: string): boolean {
27+
return path.extname(filePath).toLowerCase() === '.json';
28+
}
29+
2630
function getModuleFromChildren(
2731
module: Plugin.StatsModule,
2832
collectedModules: Plugin.StatsModule[],
@@ -132,6 +136,14 @@ export function getModuleGraphByStats(
132136
sourceSize: data.size,
133137
transformedSize: data.size,
134138
});
139+
const sizeData: Partial<SDK.ModuleSize> = {
140+
sourceSize: data.size,
141+
transformedSize: data.size,
142+
};
143+
if (isJsonFile(concatenatedModule.path)) {
144+
sizeData.parsedSize = data.size;
145+
}
146+
concatenatedModule.setSize(sizeData);
135147
}
136148

137149
for (const normal of data.modules ?? []) {
@@ -194,6 +206,15 @@ export function getModuleGraphByStats(
194206
sourceSize: normal.size,
195207
transformedSize: normal.size,
196208
});
209+
const sizeData: Partial<SDK.ModuleSize> = {
210+
sourceSize: normal.size,
211+
transformedSize: normal.size,
212+
};
213+
// Since JSON modules do not generate sourcemaps, the parsedSize for JSON modules can only be added from the stats JSON.
214+
if (isJsonFile(normalModule.path)) {
215+
sizeData.parsedSize = normal.size;
216+
}
217+
normalModule.setSize(sizeData);
197218
}
198219

199220
moduleGraph.addModule(normalModule);

packages/graph/tests/module-graph.test.ts

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import path from 'path';
22
import { expect, describe, it } from '@rstest/core';
3-
import { SDK } from '@rsdoctor/types';
3+
import { SDK, Plugin } from '@rsdoctor/types';
44
import { Module, ModuleGraph, PackageGraph } from '../src/graph';
5+
import { getModuleGraphByStats } from '../src/transform/module-graph/transform';
6+
import { chunkTransform } from '../src/transform/chunks/chunkTransform';
57
// TODO: simplify the module-graph-basic.json data size.
68
const resolveFixture = (...paths: string[]) => {
79
return path.resolve(__dirname, 'fixture', ...paths);
@@ -231,4 +233,168 @@ describe('module graph', () => {
231233
const result = moduleGraph.getModuleByFile(filePath, 'modern');
232234
expect(result).toEqual([]);
233235
});
236+
237+
describe('JSON file parsedSize handling', () => {
238+
it('should set parsedSize for JSON files from stats size', () => {
239+
const root = '/test/root';
240+
const stats: Plugin.StatsCompilation = {
241+
modules: [
242+
{
243+
identifier: 'json-module-1',
244+
name: './data.json',
245+
nameForCondition: './data.json',
246+
size: 1024,
247+
type: 'module',
248+
id: 1,
249+
},
250+
{
251+
identifier: 'js-module-1',
252+
name: './script.js',
253+
nameForCondition: './script.js',
254+
size: 2048,
255+
type: 'module',
256+
id: 2,
257+
},
258+
{
259+
identifier: 'json-module-2',
260+
name: './config.JSON',
261+
nameForCondition: './config.JSON',
262+
size: 512,
263+
type: 'module',
264+
id: 3,
265+
},
266+
],
267+
chunks: [],
268+
assets: [],
269+
};
270+
271+
const chunkGraph = chunkTransform(new Map(), stats);
272+
const moduleGraph = getModuleGraphByStats(stats, root, chunkGraph);
273+
274+
// Check JSON file with lowercase extension
275+
const jsonModule1 = moduleGraph.getModuleByWebpackId('json-module-1');
276+
expect(jsonModule1).toBeTruthy();
277+
expect(jsonModule1?.getSize().parsedSize).toBe(1024);
278+
expect(jsonModule1?.getSize().sourceSize).toBe(1024);
279+
expect(jsonModule1?.getSize().transformedSize).toBe(1024);
280+
281+
// Check JSON file with uppercase extension
282+
const jsonModule2 = moduleGraph.getModuleByWebpackId('json-module-2');
283+
expect(jsonModule2).toBeTruthy();
284+
expect(jsonModule2?.getSize().parsedSize).toBe(512);
285+
expect(jsonModule2?.getSize().sourceSize).toBe(512);
286+
expect(jsonModule2?.getSize().transformedSize).toBe(512);
287+
288+
// Check non-JSON file should not have parsedSize set by this logic
289+
const jsModule = moduleGraph.getModuleByWebpackId('js-module-1');
290+
expect(jsModule).toBeTruthy();
291+
expect(jsModule?.getSize().sourceSize).toBe(2048);
292+
expect(jsModule?.getSize().transformedSize).toBe(2048);
293+
// parsedSize should be 0 (default) for non-JSON files
294+
expect(jsModule?.getSize().parsedSize).toBe(0);
295+
});
296+
297+
it('should handle JSON files in concatenated modules', () => {
298+
const root = '/test/root';
299+
const stats: Plugin.StatsCompilation = {
300+
modules: [
301+
{
302+
identifier: 'concatenated-module',
303+
name: './concatenated.js',
304+
nameForCondition: './concatenated.js',
305+
size: 3072,
306+
type: 'module',
307+
id: 1,
308+
modules: [
309+
{
310+
identifier: 'json-in-concat',
311+
name: './nested.json',
312+
nameForCondition: './nested.json',
313+
size: 1024,
314+
type: 'module',
315+
id: 2,
316+
},
317+
{
318+
identifier: 'js-in-concat',
319+
name: './nested.js',
320+
nameForCondition: './nested.js',
321+
size: 2048,
322+
type: 'module',
323+
id: 3,
324+
},
325+
],
326+
},
327+
],
328+
chunks: [],
329+
assets: [],
330+
};
331+
332+
const chunkGraph = chunkTransform(new Map(), stats);
333+
const moduleGraph = getModuleGraphByStats(stats, root, chunkGraph);
334+
335+
// Check JSON file inside concatenated module
336+
const jsonModule = moduleGraph.getModuleByWebpackId('json-in-concat');
337+
expect(jsonModule).toBeTruthy();
338+
expect(jsonModule?.getSize().parsedSize).toBe(1024);
339+
expect(jsonModule?.getSize().sourceSize).toBe(1024);
340+
expect(jsonModule?.getSize().transformedSize).toBe(1024);
341+
342+
// Check non-JSON file inside concatenated module
343+
const jsModule = moduleGraph.getModuleByWebpackId('js-in-concat');
344+
expect(jsModule).toBeTruthy();
345+
expect(jsModule?.getSize().sourceSize).toBe(2048);
346+
expect(jsModule?.getSize().transformedSize).toBe(2048);
347+
expect(jsModule?.getSize().parsedSize).toBe(0);
348+
});
349+
350+
it('should handle files without size property', () => {
351+
const root = '/test/root';
352+
const stats: Plugin.StatsCompilation = {
353+
modules: [
354+
{
355+
identifier: 'json-no-size',
356+
name: './data.json',
357+
nameForCondition: './data.json',
358+
type: 'module',
359+
id: 1,
360+
},
361+
],
362+
chunks: [],
363+
assets: [],
364+
};
365+
366+
const chunkGraph = chunkTransform(new Map(), stats);
367+
const moduleGraph = getModuleGraphByStats(stats, root, chunkGraph);
368+
369+
const jsonModule = moduleGraph.getModuleByWebpackId('json-no-size');
370+
expect(jsonModule).toBeTruthy();
371+
// When size is not provided, parsedSize should remain 0 (default)
372+
expect(jsonModule?.getSize().parsedSize).toBe(0);
373+
});
374+
375+
it('should handle JSON files with absolute paths', () => {
376+
const root = '/test/root';
377+
const stats: Plugin.StatsCompilation = {
378+
modules: [
379+
{
380+
identifier: 'json-absolute',
381+
name: '/absolute/path/to/data.json',
382+
nameForCondition: '/absolute/path/to/data.json',
383+
size: 256,
384+
type: 'module',
385+
id: 1,
386+
},
387+
],
388+
chunks: [],
389+
assets: [],
390+
};
391+
392+
const chunkGraph = chunkTransform(new Map(), stats);
393+
const moduleGraph = getModuleGraphByStats(stats, root, chunkGraph);
394+
395+
const jsonModule = moduleGraph.getModuleByWebpackId('json-absolute');
396+
expect(jsonModule).toBeTruthy();
397+
expect(jsonModule?.getSize().parsedSize).toBe(256);
398+
});
399+
});
234400
});

packages/types/src/plugin/baseStats.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ interface StatsOptionsObj {
1515
chunkModules?: boolean;
1616
hash?: boolean;
1717
ids?: boolean;
18-
18+
orphanModules?: boolean;
19+
runtimeModules?: boolean;
20+
cachedModules?: boolean;
21+
nestedModules?: boolean;
1922
/** Rspack not support below opts */
2023
cachedAssets?: boolean;
2124
groupAssetsByInfo?: boolean;
@@ -69,6 +72,10 @@ export interface StatsModule {
6972
assets?: Array<string | number>;
7073
reasons?: Array<StatsModuleReason>;
7174
source?: string | Buffer;
75+
orphanModules?: Array<StatsModule>;
76+
runtimeModules?: Array<StatsModule>;
77+
cachedModules?: Array<StatsModule>;
78+
nestedModules?: Array<StatsModule>;
7279
nameForCondition?: string; // rspack is lack of nameForCondition type
7380
depth?: number | string; // rspack is lack of nameForCondition type ? packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts , impact tree-shaking analysis ability.
7481
loc?: string; // rspack is lack of nameForCondition type ? packages/rspack/src/stats/DefaultStatsPrinterPlugin.ts

pnpm-lock.yaml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)