diff --git a/packages/core/src/build-utils/build/chunks/assetsModules.ts b/packages/core/src/build-utils/build/chunks/assetsModules.ts index f7592380..98ef6b63 100644 --- a/packages/core/src/build-utils/build/chunks/assetsModules.ts +++ b/packages/core/src/build-utils/build/chunks/assetsModules.ts @@ -1,17 +1,19 @@ -import { Plugin } from '@rsdoctor/types'; import { getAssetsModulesData as transform, ParsedModuleSizeData, } from '@/build-utils/common/chunks'; import { parseBundle } from '../utils'; +import { SDK } from '@rsdoctor/types'; export async function getAssetsModulesData( - bundleStats: Plugin.StatsCompilation, + moduleGraph: SDK.ModuleGraphInstance, + chunkGraph: SDK.ChunkGraphInstance, bundleDir: string, hasParseBundle = true, ): Promise { return transform( - bundleStats, + moduleGraph, + chunkGraph, bundleDir, hasParseBundle ? { parseBundle } : {}, ); diff --git a/packages/core/src/build-utils/build/utils/parseBundle.ts b/packages/core/src/build-utils/build/utils/parseBundle.ts index a5cad361..055ad334 100644 --- a/packages/core/src/build-utils/build/utils/parseBundle.ts +++ b/packages/core/src/build-utils/build/utils/parseBundle.ts @@ -5,7 +5,7 @@ import { filesize } from 'filesize'; import { parser } from '@rsdoctor/utils/ruleUtils'; import { extname } from 'path'; -import { Plugin } from '@rsdoctor/types'; +import { SDK } from '@rsdoctor/types'; import { ParseBundle } from '@/types'; import { debug } from '@rsdoctor/utils/logger'; @@ -22,7 +22,7 @@ import { debug } from '@rsdoctor/utils/logger'; // TODO: optimize type export const parseBundle: ParseBundle = ( bundlePath: string, - modulesData: Plugin.StatsModule[], + modulesData: Pick[], ) => { if (bundlePath.indexOf('.worker.') > 0) { return {}; @@ -253,13 +253,7 @@ export const parseBundle: ParseBundle = ( const moduleContent = modules[module]; const size = moduleContent && Buffer.byteLength(moduleContent); - const _filterModules = find(modulesData, { - id: Number(module), - }) as Plugin.StatsModule; - const identifier = - _filterModules?.identifier || - find(modulesData, { id: module })?.identifier || - ''; + const identifier = find(modulesData, { renderId: module })?.webpackId || ''; modulesObj[identifier] = { size, sizeConvert: filesize(size || 0), diff --git a/packages/core/src/build-utils/common/chunks/assetsModules.ts b/packages/core/src/build-utils/common/chunks/assetsModules.ts index 0d5fd9c8..c33deb58 100644 --- a/packages/core/src/build-utils/common/chunks/assetsModules.ts +++ b/packages/core/src/build-utils/common/chunks/assetsModules.ts @@ -2,9 +2,8 @@ import { isEmpty, pick } from 'lodash'; import path from 'path'; import { logger } from '@rsdoctor/utils/logger'; -import { Plugin, SDK } from '@rsdoctor/types'; +import { SDK } from '@rsdoctor/types'; import { ParseBundle } from '@/types'; -import { getModulesFromArray } from '../module-graph'; export type ParsedModuleSizeData = { [x: string]: { size: number; sizeConvert: string; content: string }; @@ -19,7 +18,8 @@ export type ParsedModuleSizeData = { * https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/44bd8d0f9aa3b098e271af220096ea70cc44bc9e/LICENSE */ export async function getAssetsModulesData( - bundleStats: Plugin.StatsCompilation, + moduleGraph: SDK.ModuleGraphInstance, + chunkGraph: SDK.ChunkGraphInstance, bundleDir: string, opts: { parseBundle?: ParseBundle; @@ -27,49 +27,23 @@ export async function getAssetsModulesData( ): Promise { const { parseBundle = () => ({}) as ReturnType } = opts || {}; - // Sometimes all the information is located in `children` array (e.g. problem in #10) - if (isEmpty(bundleStats.assets) && !isEmpty(bundleStats.children)) { - const { children } = bundleStats; - const _bundleStats = children?.[0]; - if (!children) { - return {}; - } - for (let i = 1; i < children.length; i++) { - children[i]?.assets?.forEach((asset: Plugin.StatsAsset) => { - _bundleStats?.assets?.push(asset); - }); - } - } else if (!isEmpty(bundleStats.children)) { - // Sometimes if there are additional child chunks produced add them as child assets - bundleStats?.children?.forEach((child: Plugin.StatsCompilation) => { - child?.assets?.forEach((asset: Plugin.StatsAsset) => { - bundleStats?.assets?.push(asset); - }); - }); - } + const assets = chunkGraph.getAssets(); + const modules = moduleGraph.getModules(); // Trying to parse bundle assets and get real module sizes if `bundleDir` is provided let bundlesSources: Record | null = null; let parsedModules: ParsedModuleSizeData | null = null; - if (bundleDir && bundleStats?.assets) { + if (bundleDir && assets.length) { bundlesSources = {}; parsedModules = {}; - for (const statAsset of bundleStats.assets) { - const assetFile = path.join(bundleDir, statAsset.name); + for (const asset of assets) { + const assetFile = path.join(bundleDir, asset.path); let bundleInfo: ReturnType; - const collectedModules: Plugin.StatsModule[] = []; - - getModulesFromArray(bundleStats.modules ?? [], collectedModules); - - // Add childCompiler's stats.modules - const childrenModules: Plugin.StatsModule[] = - bundleStats.children?.flatMap((c) => c.modules || []) || []; - collectedModules.push(...childrenModules); - try { - bundleInfo = await parseBundle(assetFile, collectedModules); + console.log(modules); + bundleInfo = parseBundle(assetFile, modules); } catch (err: any) { const { code = '', message } = err; const msg = code === 'ENOENT' ? 'no such file' : message; @@ -79,7 +53,7 @@ export async function getAssetsModulesData( continue; } - bundlesSources[statAsset.name] = pick(bundleInfo, 'src', 'runtimeSrc'); + bundlesSources[asset.path] = pick(bundleInfo, 'src', 'runtimeSrc'); Object.assign(parsedModules, bundleInfo?.modules || {}); } diff --git a/packages/core/src/build-utils/common/module-graph/transform.ts b/packages/core/src/build-utils/common/module-graph/transform.ts index f417b374..73fd02fb 100644 --- a/packages/core/src/build-utils/common/module-graph/transform.ts +++ b/packages/core/src/build-utils/common/module-graph/transform.ts @@ -92,6 +92,7 @@ export function getModuleGraphByStats( getGetModuleName(root, data), data.depth === 0, isConcatenated ? SDK.ModuleKind.Concatenation : SDK.ModuleKind.Normal, + data.id ? String(data.id) : undefined, data.layer!, ); @@ -132,6 +133,7 @@ export function getModuleGraphByStats( getGetModuleName(root, normal), normal.depth === 0, SDK.ModuleKind.Normal, + normal.id ? String(normal.id) : undefined, normal.layer, ); diff --git a/packages/core/src/build-utils/common/trans-utils/transStats.ts b/packages/core/src/build-utils/common/trans-utils/transStats.ts index 3443d29b..82d47ee7 100644 --- a/packages/core/src/build-utils/common/trans-utils/transStats.ts +++ b/packages/core/src/build-utils/common/trans-utils/transStats.ts @@ -8,7 +8,12 @@ export async function transStats(json: Plugin.StatsCompilation) { ); const moduleGraph = ModuleGraph.getModuleGraphByStats(json, '.', chunkGraph); const assetsModuleMap = - (await Chunks.getAssetsModulesData(json, json.outputPath || '', {})) || {}; + (await Chunks.getAssetsModulesData( + moduleGraph, + chunkGraph, + json.outputPath || '', + {}, + )) || {}; Chunks.transformAssetsModulesData(assetsModuleMap, moduleGraph); return { chunkGraph, moduleGraph }; } diff --git a/packages/core/src/inner-plugins/plugins/ensureModulesChunkGraph.ts b/packages/core/src/inner-plugins/plugins/ensureModulesChunkGraph.ts index c26f27e1..98529540 100644 --- a/packages/core/src/inner-plugins/plugins/ensureModulesChunkGraph.ts +++ b/packages/core/src/inner-plugins/plugins/ensureModulesChunkGraph.ts @@ -81,10 +81,10 @@ export const ensureModulesChunksGraphFn = ( /** transform modules graph */ const shouldParseBundle = _this.options.supports.parseBundle !== false; - await getModulesInfosByStats( + await getModulesInfos( compiler, - statsJson, _this.modulesGraph, + _this.chunkGraph, shouldParseBundle, ); @@ -127,10 +127,10 @@ export const ensureModulesChunksGraphFn = ( * @return {*} * @memberof RsdoctorWebpackPlugin */ -async function getModulesInfosByStats( +async function getModulesInfos( compiler: Plugin.BaseCompiler, - stats: Plugin.StatsCompilation, moduleGraph: SDK.ModuleGraphInstance, + chunkGraph: SDK.ChunkGraphInstance, parseBundle: boolean, ) { if (!moduleGraph) { @@ -139,7 +139,8 @@ async function getModulesInfosByStats( try { const parsedModulesData = (await ChunksBuildUtils.getAssetsModulesData( - stats, + moduleGraph, + chunkGraph, compiler.outputPath, parseBundle, )) || {}; diff --git a/packages/core/src/types/chunks.ts b/packages/core/src/types/chunks.ts index 73238ff8..9d2638d4 100644 --- a/packages/core/src/types/chunks.ts +++ b/packages/core/src/types/chunks.ts @@ -1,4 +1,4 @@ -import { Plugin } from '@rsdoctor/types'; +import { Plugin, SDK } from '@rsdoctor/types'; export type AssetsModules = { label?: string; @@ -8,7 +8,7 @@ export type AssetsModules = { export type ParseBundle = ( assetFile: string, - modules: Plugin.StatsModule[], + modules: Pick[], ) => { modules?: Record; src?: string; diff --git a/packages/core/tests/build/utils/parseBundle.test.ts b/packages/core/tests/build/utils/parseBundle.test.ts index 282dc27b..63402043 100644 --- a/packages/core/tests/build/utils/parseBundle.test.ts +++ b/packages/core/tests/build/utils/parseBundle.test.ts @@ -3,6 +3,7 @@ import fs from 'fs'; import os from 'os'; import { describe, it, expect } from 'vitest'; import { parseBundle } from '@/build-utils/build/utils/parseBundle'; +import { SDK } from '@rsdoctor/types'; const BUNDLES_DIR = `${__dirname}/bundles`; @@ -21,13 +22,13 @@ describe('parseBundle', function () { it(`should parse ${lowerCase(bundleName)}`, function () { const bundleFile = `${BUNDLES_DIR}/${bundleName}.js`; const modules = [ - { id: 0, identifier: '0' }, - { id: 1, identifier: '1' }, - { id: 2, identifier: '2' }, - { id: 3, identifier: '33' }, - { id: 5, identifier: '5' }, - { id: 6, identifier: '6' }, - { id: '/x1Yz5', identifier: '/x1Yz5' }, + { renderId: '0', webpackId: '0' }, + { renderId: '1', webpackId: '1' }, + { renderId: '2', webpackId: '2' }, + { renderId: '3', webpackId: '33' }, + { renderId: '5', webpackId: '5' }, + { renderId: '6', webpackId: '6' }, + { renderId: '/x1Yz5', webpackId: '/x1Yz5' }, ]; const bundle = parseBundle(bundleFile, modules); @@ -37,7 +38,8 @@ describe('parseBundle', function () { }), ); expect(bundle.src).toEqual(fs.readFileSync(bundleFile, 'utf8')); - os.EOL === '\n' && expect(bundle.modules).toEqual(expectedModules.modules); + os.EOL === '\n' && + expect(bundle.modules).toEqual(expectedModules.modules); }); }); }); diff --git a/packages/graph/src/graph/module-graph/graph.ts b/packages/graph/src/graph/module-graph/graph.ts index 0a33d578..af5807eb 100644 --- a/packages/graph/src/graph/module-graph/graph.ts +++ b/packages/graph/src/graph/module-graph/graph.ts @@ -28,6 +28,7 @@ export class ModuleGraph implements SDK.ModuleGraphInstance { item.path, item.isEntry, item.kind, + item.renderId, item.layer, ); (module as any).id = item.id; diff --git a/packages/graph/src/graph/module-graph/module.ts b/packages/graph/src/graph/module-graph/module.ts index 94783be6..bf821aad 100644 --- a/packages/graph/src/graph/module-graph/module.ts +++ b/packages/graph/src/graph/module-graph/module.ts @@ -18,6 +18,8 @@ export class Module implements SDK.ModuleInstance { readonly id: number; + readonly renderId: string | undefined; + readonly webpackId: string; readonly path: string; @@ -66,6 +68,7 @@ export class Module implements SDK.ModuleInstance { path: string, isEntry = false, kind = SDK.ModuleKind.Normal, + renderId: string | undefined = undefined, layer = '', ) { this.id = id++; @@ -73,6 +76,7 @@ export class Module implements SDK.ModuleInstance { this.path = path; this.isEntry = isEntry; this.kind = kind; + this.renderId = renderId; this.layer = layer; } @@ -316,6 +320,7 @@ export class Module implements SDK.ModuleInstance { const moduleName = getModuleName(this.webpackId); const data: SDK.ModuleData = { id: this.id, + renderId: this.renderId, webpackId: contextPath && moduleName.indexOf('.') > 0 ? path.relative(contextPath, moduleName) diff --git a/packages/types/src/sdk/module.ts b/packages/types/src/sdk/module.ts index 5f1eb3eb..25d285a0 100644 --- a/packages/types/src/sdk/module.ts +++ b/packages/types/src/sdk/module.ts @@ -98,6 +98,8 @@ export enum ToDataType { export interface ModuleInstance { /** Module identifier */ readonly id: number; + /** webpack render identifier */ + readonly renderId?: string; /** webpack identifier */ readonly webpackId: string; /** Module path */