-
-
Notifications
You must be signed in to change notification settings - Fork 7.8k
feat: build stats functionality with tests and CLI options #21485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Can you explain why you need this? Could you write a Vite plugin that extracts some of the information instead? Or use the manifest option? |
| if (jsonOutput && builder._buildStats) { | ||
| const { writeBuildStats } = await import('./buildStats') | ||
| await writeBuildStats( | ||
| builder._buildStats.getStats(true), | ||
| jsonOutput === true ? true : jsonOutput, | ||
| ) | ||
| } | ||
| } catch (e) { | ||
| createLogger(options.logLevel).error( | ||
| colors.red(`error during build:\n${e.stack}`), | ||
| { error: e }, | ||
| ) | ||
| // If JSON output is requested, output error as JSON | ||
| if (jsonOutput) { | ||
| const { BuildStatsCollector, writeBuildStats } = | ||
| await import('./buildStats') | ||
| const errorCollector = new BuildStatsCollector(false) | ||
| errorCollector.start() | ||
| errorCollector.addError(e.message || 'Build failed') | ||
| await writeBuildStats( | ||
| errorCollector.getStats(false), | ||
| jsonOutput === true ? true : jsonOutput, | ||
| ) | ||
| } else { | ||
| createLogger(options.logLevel).error( | ||
| colors.red(`error during build:\n${e.stack}`), | ||
| { error: e }, | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error handling logic is broken. If writeBuildStats() fails after a successful build, the catch block will create a new stats object with the write error message instead of the build stats, resulting in incorrect JSON output that reports build failure when the build actually succeeded. The try-catch should be restructured to separate build errors from stats writing errors.
try {
const inlineConfig: InlineConfig = { /* ... */ }
const builder = await createBuilder(inlineConfig, null)
await builder.buildApp()
// Output JSON stats if requested
if (jsonOutput && builder._buildStats) {
const { writeBuildStats } = await import('./buildStats')
try {
await writeBuildStats(
builder._buildStats.getStats(true),
jsonOutput === true ? true : jsonOutput,
)
} catch (writeError) {
// Handle stats writing error separately
if (!jsonOutput || jsonOutput !== true) {
createLogger(options.logLevel).error(
colors.red(`Failed to write stats: ${writeError.message}`),
)
}
process.exit(1)
}
}
} catch (e) {
// Build error handling
if (jsonOutput) {
const { BuildStatsCollector, writeBuildStats } = await import('./buildStats')
const errorCollector = new BuildStatsCollector(false)
errorCollector.start()
errorCollector.addError(e.message || 'Build failed')
await writeBuildStats(
errorCollector.getStats(false),
jsonOutput === true ? true : jsonOutput,
)
} else {
createLogger(options.logLevel).error(
colors.red(`error during build:\n${e.stack}`),
{ error: e },
)
}
process.exit(1)
}| if (jsonOutput && builder._buildStats) { | |
| const { writeBuildStats } = await import('./buildStats') | |
| await writeBuildStats( | |
| builder._buildStats.getStats(true), | |
| jsonOutput === true ? true : jsonOutput, | |
| ) | |
| } | |
| } catch (e) { | |
| createLogger(options.logLevel).error( | |
| colors.red(`error during build:\n${e.stack}`), | |
| { error: e }, | |
| ) | |
| // If JSON output is requested, output error as JSON | |
| if (jsonOutput) { | |
| const { BuildStatsCollector, writeBuildStats } = | |
| await import('./buildStats') | |
| const errorCollector = new BuildStatsCollector(false) | |
| errorCollector.start() | |
| errorCollector.addError(e.message || 'Build failed') | |
| await writeBuildStats( | |
| errorCollector.getStats(false), | |
| jsonOutput === true ? true : jsonOutput, | |
| ) | |
| } else { | |
| createLogger(options.logLevel).error( | |
| colors.red(`error during build:\n${e.stack}`), | |
| { error: e }, | |
| ) | |
| } | |
| if (jsonOutput && builder._buildStats) { | |
| const { writeBuildStats } = await import('./buildStats') | |
| try { | |
| await writeBuildStats( | |
| builder._buildStats.getStats(true), | |
| jsonOutput === true ? true : jsonOutput, | |
| ) | |
| } catch (writeError) { | |
| // Handle stats writing error separately | |
| createLogger(options.logLevel).error( | |
| colors.red(`Failed to write stats: ${writeError.message}`), | |
| ) | |
| process.exit(1) | |
| } | |
| } | |
| } catch (e) { | |
| // If JSON output is requested, output error as JSON | |
| if (jsonOutput) { | |
| const { BuildStatsCollector, writeBuildStats } = | |
| await import('./buildStats') | |
| const errorCollector = new BuildStatsCollector(false) | |
| errorCollector.start() | |
| errorCollector.addError(e.message || 'Build failed') | |
| await writeBuildStats( | |
| errorCollector.getStats(false), | |
| jsonOutput === true ? true : jsonOutput, | |
| ) | |
| } else { | |
| createLogger(options.logLevel).error( | |
| colors.red(`error during build:\n${e.stack}`), | |
| { error: e }, | |
| ) | |
| } | |
| process.exit(1) |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
Problem
Vite's build command cannot output build statistics in a machine-readable format. Adding build stats feature with tests and CLI options
Expected Behavior
CLI:
vite build --json- Output JSON to stdout, suppress normal logsvite build --json <filename>- Write JSON to file, create parent directoriesOutput Structure:
{
"version": "...",
"timestamp": ...,
"duration": ...,
"success": true,
"outputs": {
"": {
"outDir": "...",
"chunks": [
{
"name": "...",
"type": "chunk",
"size": ...,
"gzipSize": ...,
"isEntry": ...,
"isDynamicEntry": ...,
"modules": [...],
"imports": [...],
"dynamicImports": [...]
}
],
"assets": [
{
"name": "...",
"type": "asset",
"size": ...,
"gzipSize": ...
}
],
"totals": {
"chunkCount": ...,
"assetCount": ...,
"totalSize": ...,
"totalGzipSize": ...
}
}
},
"warnings": [{ "message": "..." }],
"errors": [{ "message": "..." }]
}
Requirements:
*.mapfilesgzipSizeis null for non-compressible files or whenbuild.reportCompressedSizeis falsetotalSizeis sum of all chunk and asset sizestotalGzipSizeis sum of all non-null gzip sizes (null whenbuild.reportCompressedSizeis false)success: falseoutDirmust be absolute path