From 87716dbb72f566c9892de9f61b522a8f99701a97 Mon Sep 17 00:00:00 2001 From: 9aoy Date: Fri, 15 Nov 2024 22:02:28 +0800 Subject: [PATCH] feat: support print error module traces (#3986) --- .../config/stats-module-trace/index.test.ts | 17 +++++++++++++++++ .../config/stats-module-trace/rsbuild.config.ts | 14 ++++++++++++++ .../config/stats-module-trace/src/index.tsx | 1 + .../config/stats-module-trace/src/test.tsx | 1 + e2e/cases/config/stats-options/index.test.ts | 2 +- packages/core/src/client/format.ts | 17 ++++++++++++++++- packages/core/src/server/socketServer.ts | 17 +++++++++++++++-- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 e2e/cases/config/stats-module-trace/index.test.ts create mode 100644 e2e/cases/config/stats-module-trace/rsbuild.config.ts create mode 100644 e2e/cases/config/stats-module-trace/src/index.tsx create mode 100644 e2e/cases/config/stats-module-trace/src/test.tsx diff --git a/e2e/cases/config/stats-module-trace/index.test.ts b/e2e/cases/config/stats-module-trace/index.test.ts new file mode 100644 index 0000000000..e49bd92b47 --- /dev/null +++ b/e2e/cases/config/stats-module-trace/index.test.ts @@ -0,0 +1,17 @@ +import { build, proxyConsole } from '@e2e/helper'; +import { expect, test } from '@playwright/test'; + +test('should log error module trace when enable moduleTrace', async () => { + const { restore, logs } = proxyConsole(); + + await expect( + build({ + cwd: __dirname, + rsbuildConfig: {}, + }), + ).rejects.toThrowError('build failed'); + + expect(logs.some((log) => log.includes('@ ./src/index.tsx'))).toBeTruthy(); + + restore(); +}); diff --git a/e2e/cases/config/stats-module-trace/rsbuild.config.ts b/e2e/cases/config/stats-module-trace/rsbuild.config.ts new file mode 100644 index 0000000000..0a00f8dac1 --- /dev/null +++ b/e2e/cases/config/stats-module-trace/rsbuild.config.ts @@ -0,0 +1,14 @@ +export default { + tools: { + rspack: { + stats: { + moduleTrace: true, + }, + }, + webpack: { + stats: { + moduleTrace: true, + }, + }, + }, +}; diff --git a/e2e/cases/config/stats-module-trace/src/index.tsx b/e2e/cases/config/stats-module-trace/src/index.tsx new file mode 100644 index 0000000000..41e183492d --- /dev/null +++ b/e2e/cases/config/stats-module-trace/src/index.tsx @@ -0,0 +1 @@ +import './test'; diff --git a/e2e/cases/config/stats-module-trace/src/test.tsx b/e2e/cases/config/stats-module-trace/src/test.tsx new file mode 100644 index 0000000000..05147212a4 --- /dev/null +++ b/e2e/cases/config/stats-module-trace/src/test.tsx @@ -0,0 +1 @@ +import './test1'; diff --git a/e2e/cases/config/stats-options/index.test.ts b/e2e/cases/config/stats-options/index.test.ts index 6e0c6595ee..198dec8be4 100644 --- a/e2e/cases/config/stats-options/index.test.ts +++ b/e2e/cases/config/stats-options/index.test.ts @@ -13,7 +13,7 @@ test('should log warning by default', async () => { logs.some((log) => log.includes('Using / for division outside of calc() is deprecated'), ), - ); + ).toBeTruthy(); restore(); }); diff --git a/packages/core/src/client/format.ts b/packages/core/src/client/format.ts index 6c05668ed3..6fb0107a24 100644 --- a/packages/core/src/client/format.ts +++ b/packages/core/src/client/format.ts @@ -20,6 +20,20 @@ function resolveFileName(stats: StatsError) { return file ? `File: ${file}\n` : ''; } +function resolveModuleTrace(stats: StatsError) { + let traceStr = ''; + if (stats.moduleTrace) { + for (const trace of stats.moduleTrace) { + if (trace.originName) { + // TODO: missing moduleTrace.dependencies[].loc in rspack + traceStr += `\n @ ${trace.originName}`; + } + } + } + + return traceStr; +} + function hintUnknownFiles(message: string): string { const hint = 'You may need an appropriate loader to handle this file type.'; @@ -61,8 +75,9 @@ function formatMessage(stats: StatsError | string, verbose?: boolean) { const details = verbose && stats.details ? `\nDetails: ${stats.details}\n` : ''; const stack = verbose && stats.stack ? `\n${stats.stack}` : ''; + const moduleTrace = resolveModuleTrace(stats); - message = `${fileName}${mainMessage}${details}${stack}`; + message = `${fileName}${mainMessage}${details}${stack}${moduleTrace}`; } else { message = stats; } diff --git a/packages/core/src/server/socketServer.ts b/packages/core/src/server/socketServer.ts index 098fee4abd..bd6409a9e2 100644 --- a/packages/core/src/server/socketServer.ts +++ b/packages/core/src/server/socketServer.ts @@ -2,7 +2,11 @@ import type { IncomingMessage } from 'node:http'; import type { Socket } from 'node:net'; import { parse } from 'node:querystring'; import type Ws from 'ws'; -import { getAllStatsErrors, getAllStatsWarnings } from '../helpers'; +import { + getAllStatsErrors, + getAllStatsWarnings, + getStatsOptions, +} from '../helpers'; import { logger } from '../logger'; import type { DevConfig, Rspack } from '../types'; import { getCompilationId } from './helper'; @@ -203,7 +207,16 @@ export class SocketServer { children: true, }; - return curStats.toJson(defaultStats); + const statsOptions = getStatsOptions(curStats.compilation.compiler); + + const userOptions = + typeof statsOptions === 'string' + ? { preset: statsOptions } + : typeof statsOptions === 'object' + ? statsOptions + : {}; + + return curStats.toJson({ ...defaultStats, ...userOptions }); } // determine what message should send by stats