0
# Plugin System
1
2
Size Limit uses a modular plugin architecture that allows different bundlers, measurement tools, and analysis features to be combined flexibly.
3
4
## Capabilities
5
6
### Plugin Interface
7
8
The plugin system defines a standard interface for extending Size Limit functionality.
9
10
```javascript { .api }
11
// Plugin interface for plugin developers
12
interface Plugin {
13
// Plugin identification
14
name: string; // Plugin name (e.g., "@size-limit/webpack")
15
16
// Lifecycle hooks
17
before?(config: object, check: Check): Promise<void>;
18
finally?(config: object, check: Check): Promise<void>;
19
20
// Processing steps (0-100 available)
21
step0?(config: object, check: Check): Promise<void>;
22
step1?(config: object, check: Check): Promise<void>;
23
// ... step2 through step99
24
step100?(config: object, check: Check): Promise<void>;
25
26
// Progress messages for steps
27
wait0?: string; // Progress message for step0
28
wait1?: string; // Progress message for step1
29
// ... wait2 through wait100
30
}
31
32
// Plugin loading system
33
class Plugins {
34
constructor(list: Plugin[]);
35
list: Plugin[]; // Array of loaded plugins
36
isEmpty: boolean; // True if no plugins loaded
37
has(type: string): boolean; // Check if plugin type is available
38
}
39
```
40
41
### Core Plugins
42
43
Official plugins that provide essential Size Limit functionality.
44
45
```javascript { .api }
46
// File measurement plugin
47
// Package: @size-limit/file
48
// Provides: Basic file size measurement with compression options
49
50
// Webpack integration plugin
51
// Package: @size-limit/webpack
52
// Provides: Webpack bundling, tree-shaking, custom config support
53
54
// ESBuild integration plugin
55
// Package: @size-limit/esbuild
56
// Provides: ESBuild bundling, fast compilation, modern JS support
57
58
// Time measurement plugin
59
// Package: @size-limit/time
60
// Provides: Browser execution time measurement, network simulation
61
62
// CSS support plugin
63
// Package: @size-limit/webpack-css
64
// Provides: CSS processing and measurement with webpack
65
66
// Bundle analysis plugins
67
// Package: @size-limit/webpack-why
68
// Package: @size-limit/esbuild-why
69
// Provides: Detailed bundle analysis, dependency graphs, size breakdowns
70
```
71
72
### Plugin Installation
73
74
Plugins are installed as separate npm packages and automatically detected.
75
76
**Usage Examples:**
77
78
```bash
79
# Install individual plugins
80
npm install --save-dev @size-limit/file
81
npm install --save-dev @size-limit/webpack
82
npm install --save-dev @size-limit/time
83
84
# Install preset bundles
85
npm install --save-dev @size-limit/preset-app
86
npm install --save-dev @size-limit/preset-big-lib
87
npm install --save-dev @size-limit/preset-small-lib
88
```
89
90
### Plugin Detection
91
92
Size Limit automatically detects and loads available plugins from project dependencies.
93
94
```javascript { .api }
95
// Plugin detection rules:
96
// 1. Scans package.json dependencies, devDependencies, optionalDependencies
97
// 2. Matches packages with names starting with "@size-limit/" or "size-limit-"
98
// 3. Dynamically imports matching packages
99
// 4. Flattens plugin arrays (plugins can export multiple plugins)
100
// 5. Creates Plugins instance with loaded plugin list
101
102
async function loadPlugins(pkg: PackageInfo): Promise<Plugins>;
103
104
interface PackageInfo {
105
packageJson: {
106
dependencies?: Record<string, string>;
107
devDependencies?: Record<string, string>;
108
optionalDependencies?: Record<string, string>;
109
};
110
path: string;
111
}
112
```
113
114
### Configuration-Based Plugin Usage
115
116
Plugins are activated based on configuration options in each check.
117
118
```javascript { .api }
119
// Plugin activation mapping
120
const PLUGIN_OPTIONS = {
121
brotli: "file", // @size-limit/file
122
gzip: "file", // @size-limit/file
123
webpack: "webpack", // @size-limit/webpack
124
config: ["webpack", "esbuild"], // @size-limit/webpack or @size-limit/esbuild
125
entry: "webpack", // @size-limit/webpack
126
ignore: ["webpack", "esbuild"], // @size-limit/webpack or @size-limit/esbuild
127
import: ["webpack", "esbuild"], // @size-limit/webpack or @size-limit/esbuild
128
modifyWebpackConfig: "webpack", // @size-limit/webpack
129
modifyEsbuildConfig: "esbuild", // @size-limit/esbuild
130
running: "time", // @size-limit/time
131
time: "time", // @size-limit/time
132
uiReports: "webpack", // @size-limit/webpack
133
compareWith: "webpack" // @size-limit/webpack
134
};
135
```
136
137
**Configuration Examples:**
138
139
```json
140
{
141
"size-limit": [
142
{
143
"name": "File only",
144
"path": "dist/lib.js",
145
"webpack": false,
146
"running": false
147
},
148
{
149
"name": "Webpack + Time",
150
"path": "src/app.js",
151
"webpack": true,
152
"running": true,
153
"time": {
154
"networkSpeed": "3G"
155
}
156
},
157
{
158
"name": "ESBuild",
159
"path": "src/modern.js",
160
"config": "esbuild.config.js",
161
"modifyEsbuildConfig": "(config) => ({ ...config, target: 'es2020' })"
162
}
163
]
164
}
165
```
166
167
### Preset Packages
168
169
Preset packages provide pre-configured plugin combinations for common use cases.
170
171
```javascript { .api }
172
// @size-limit/preset-app
173
// Includes: @size-limit/webpack, @size-limit/time, @size-limit/file
174
// Use case: Large applications with custom bundlers
175
176
// @size-limit/preset-big-lib
177
// Includes: @size-limit/webpack, @size-limit/file
178
// Use case: Libraries > 10kB that need bundling
179
180
// @size-limit/preset-small-lib
181
// Includes: @size-limit/file
182
// Use case: Small libraries < 10kB that don't need bundling
183
```
184
185
**Preset Usage:**
186
187
```bash
188
# Install preset
189
npm install --save-dev @size-limit/preset-app
190
191
# Configuration automatically uses included plugins
192
{
193
"size-limit": [
194
{
195
"path": "dist/app.js",
196
"limit": "100 kB"
197
}
198
]
199
}
200
```
201
202
### Plugin Execution Flow
203
204
Size Limit executes plugins through a structured lifecycle with numbered steps.
205
206
```javascript { .api }
207
// Plugin execution order:
208
// 1. before() hook for all plugins
209
// 2. step0() through step100() for all plugins (in sequence)
210
// 3. finally() hook for all plugins (always executed, even on error)
211
212
// Example execution flow:
213
async function executePlugins(plugins: Plugins, config: object) {
214
try {
215
// Before phase
216
for (let plugin of plugins.list) {
217
if (plugin.before) {
218
await plugin.before(config, check);
219
}
220
}
221
222
// Step phases
223
for (let stepNumber = 0; stepNumber <= 100; stepNumber++) {
224
for (let plugin of plugins.list) {
225
const stepMethod = `step${stepNumber}`;
226
if (plugin[stepMethod]) {
227
await plugin[stepMethod](config, check);
228
}
229
}
230
}
231
} finally {
232
// Finally phase
233
for (let plugin of plugins.list) {
234
if (plugin.finally) {
235
await plugin.finally(config, check);
236
}
237
}
238
}
239
}
240
```
241
242
### Creating Custom Plugins
243
244
Developers can create custom plugins following the standard interface.
245
246
**Custom Plugin Example:**
247
248
```javascript
249
// custom-plugin.js
250
export default {
251
name: "custom-size-plugin",
252
253
// Initialize plugin
254
async before(config, check) {
255
console.log(`Starting analysis for ${check.name}`);
256
},
257
258
// Main processing step
259
async step50(config, check) {
260
// Custom size calculation logic
261
const customSize = await calculateCustomSize(check.files);
262
check.customMetric = customSize;
263
},
264
265
// Cleanup
266
async finally(config, check) {
267
console.log(`Finished analysis for ${check.name}`);
268
},
269
270
// Progress messages
271
wait50: "Calculating custom metrics..."
272
};
273
274
// Usage with programmatic API
275
import sizeLimit from "size-limit";
276
import filePlugin from "@size-limit/file";
277
import customPlugin from "./custom-plugin.js";
278
279
const results = await sizeLimit(
280
[filePlugin, customPlugin],
281
["dist/bundle.js"]
282
);
283
```
284
285
### Plugin Development Guidelines
286
287
Guidelines for developing Size Limit plugins.
288
289
```javascript { .api }
290
// Plugin development best practices:
291
// 1. Use descriptive plugin names with @size-limit/ or size-limit- prefix
292
// 2. Implement appropriate lifecycle hooks (before/finally for setup/cleanup)
293
// 3. Use numbered steps (step0-step100) for main processing
294
// 4. Provide wait messages for long-running steps
295
// 5. Handle errors gracefully and clean up resources in finally
296
// 6. Modify check objects to add measurements
297
// 7. Respect existing check properties and plugin interactions
298
// 8. Document plugin configuration options and requirements
299
```
300
301
### Error Handling in Plugins
302
303
Plugin errors are handled gracefully with proper cleanup.
304
305
```javascript { .api }
306
// Error handling flow:
307
// 1. If any step throws an error, execution stops
308
// 2. finally() hooks are always called for cleanup
309
// 3. Progress spinners are marked as failed
310
// 4. Error is propagated to CLI or API caller
311
312
// Error handling example in plugin:
313
export default {
314
name: "example-plugin",
315
316
async step10(config, check) {
317
try {
318
await riskyOperation(check);
319
} catch (error) {
320
// Log error context
321
console.error(`Plugin ${this.name} failed:`, error);
322
// Re-throw to stop execution
323
throw error;
324
}
325
},
326
327
async finally(config, check) {
328
// Always cleanup, even on error
329
await cleanup();
330
}
331
};
332
```