0
# Build Reporting
1
2
The Reporter plugin reports build progress, errors, and other events to users and external tools. Reporters provide feedback about the build process and can integrate with development tools and CI/CD systems.
3
4
## Capabilities
5
6
### Reporter Class
7
8
Base class for creating build reporting plugins.
9
10
```typescript { .api }
11
/**
12
* Base class for build reporting plugins
13
*/
14
export declare class Reporter {
15
constructor(opts: ReporterOpts);
16
}
17
18
/**
19
* Reporter plugin configuration interface
20
*/
21
interface ReporterOpts {
22
/** Report build events (required) */
23
report(args: {
24
event: ReporterEvent;
25
options: PluginOptions;
26
logger: PluginLogger;
27
tracer: PluginTracer;
28
}): Promise<void>;
29
}
30
```
31
32
### Reporter Events
33
34
```typescript { .api }
35
/**
36
* Events that can be reported during builds
37
*/
38
type ReporterEvent =
39
| BuildStartEvent
40
| BuildProgressEvent
41
| BuildSuccessEvent
42
| BuildFailureEvent
43
| WatchEvent
44
| LogEvent;
45
46
/**
47
* Build started event
48
*/
49
interface BuildStartEvent {
50
type: 'buildStart';
51
options: PluginOptions;
52
}
53
54
/**
55
* Build progress event
56
*/
57
interface BuildProgressEvent {
58
type: 'buildProgress';
59
phase: string;
60
message: string;
61
}
62
63
/**
64
* Build completed successfully
65
*/
66
interface BuildSuccessEvent {
67
type: 'buildSuccess';
68
bundleGraph: BundleGraph<NamedBundle>;
69
buildTime: number;
70
changedAssets: Map<string, Asset>;
71
}
72
73
/**
74
* Build failed event
75
*/
76
interface BuildFailureEvent {
77
type: 'buildFailure';
78
diagnostics: Array<Diagnostic>;
79
}
80
81
/**
82
* File watch event
83
*/
84
interface WatchEvent {
85
type: 'watchStart' | 'watchEnd';
86
subscription?: AsyncSubscription;
87
}
88
89
/**
90
* Log event
91
*/
92
interface LogEvent {
93
type: 'log';
94
level: 'error' | 'warn' | 'info' | 'verbose' | 'progress' | 'success';
95
diagnostics?: Array<Diagnostic>;
96
message?: string;
97
}
98
```
99
100
**Usage Example:**
101
102
```javascript
103
import { Reporter } from "@parcel/plugin";
104
import chalk from "chalk";
105
106
export default new Reporter({
107
// Report build events (required)
108
async report({event, options, logger}) {
109
switch (event.type) {
110
case 'buildStart':
111
console.log(chalk.blue('π Build started...'));
112
this.startTime = Date.now();
113
break;
114
115
case 'buildProgress':
116
const progressBar = this.getProgressBar(event.phase);
117
console.log(chalk.yellow(`${progressBar} ${event.message}`));
118
break;
119
120
case 'buildSuccess':
121
const duration = Date.now() - this.startTime;
122
const bundles = event.bundleGraph.getBundles();
123
124
console.log(chalk.green('β Build completed successfully!'));
125
console.log(chalk.gray(` Built ${bundles.length} bundles in ${duration}ms`));
126
127
// Log bundle information
128
this.reportBundles(bundles);
129
break;
130
131
case 'buildFailure':
132
console.log(chalk.red('β Build failed!'));
133
134
// Report errors
135
for (const diagnostic of event.diagnostics) {
136
this.reportDiagnostic(diagnostic);
137
}
138
break;
139
140
case 'watchStart':
141
console.log(chalk.cyan('π Watching for changes...'));
142
break;
143
144
case 'log':
145
this.reportLog(event);
146
break;
147
}
148
},
149
150
getProgressBar(phase) {
151
const phases = {
152
'resolving': 'π¦',
153
'transforming': 'π',
154
'bundling': 'π¦',
155
'packaging': 'π¦',
156
'optimizing': 'β‘'
157
};
158
return phases[phase] || 'β³';
159
},
160
161
reportBundles(bundles) {
162
console.log(chalk.gray('\nBundle Summary:'));
163
164
for (const bundle of bundles) {
165
const size = this.formatSize(bundle.stats.size);
166
const type = bundle.type.toUpperCase();
167
const name = bundle.displayName || bundle.name || 'unnamed';
168
169
console.log(chalk.gray(` ${type} ${name} (${size})`));
170
}
171
},
172
173
reportDiagnostic(diagnostic) {
174
const level = diagnostic.level || 'error';
175
const color = level === 'error' ? chalk.red : chalk.yellow;
176
177
console.log(color(`\n${level.toUpperCase()}: ${diagnostic.message}`));
178
179
if (diagnostic.codeFrame) {
180
console.log(diagnostic.codeFrame);
181
}
182
183
if (diagnostic.filePath) {
184
console.log(chalk.gray(` at ${diagnostic.filePath}:${diagnostic.start?.line || 0}`));
185
}
186
},
187
188
reportLog(event) {
189
const colors = {
190
error: chalk.red,
191
warn: chalk.yellow,
192
info: chalk.blue,
193
success: chalk.green,
194
verbose: chalk.gray,
195
progress: chalk.cyan
196
};
197
198
const color = colors[event.level] || chalk.white;
199
200
if (event.message) {
201
console.log(color(event.message));
202
}
203
204
if (event.diagnostics) {
205
for (const diagnostic of event.diagnostics) {
206
this.reportDiagnostic(diagnostic);
207
}
208
}
209
},
210
211
formatSize(bytes) {
212
if (bytes < 1024) return `${bytes}B`;
213
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
214
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
215
}
216
});
217
```
218
219
### Diagnostic Information
220
221
```typescript { .api }
222
/**
223
* Diagnostic information for errors and warnings
224
*/
225
interface Diagnostic {
226
/** Diagnostic level */
227
level?: 'error' | 'warning' | 'info';
228
229
/** Main diagnostic message */
230
message: string;
231
232
/** Source file path */
233
filePath?: FilePath;
234
235
/** Source code location */
236
start?: SourceLocation;
237
end?: SourceLocation;
238
239
/** Code frame showing the error location */
240
codeFrame?: string;
241
242
/** Hints for fixing the issue */
243
hints?: Array<string>;
244
245
/** Documentation URL */
246
documentationURL?: string;
247
}
248
```