0
# Plugin System
1
2
Vite's plugin system provides extensible architecture compatible with Rollup plugins. It supports hooks for all phases of development and build processes, with environment-specific plugin capabilities and comprehensive lifecycle management.
3
4
## Capabilities
5
6
### Plugin Interface
7
8
Core plugin interface extending Rollup plugins with Vite-specific hooks.
9
10
```typescript { .api }
11
interface Plugin extends RollupPlugin {
12
/** Plugin name (required) */
13
name: string;
14
/** Plugin enforcement order */
15
enforce?: 'pre' | 'post';
16
/** When to apply plugin */
17
apply?: 'build' | 'serve' | ((config: UserConfig, env: ConfigEnv) => boolean);
18
/** Config modification hook */
19
config?: (config: UserConfig, env: ConfigEnv) => void | UserConfig | Promise<void | UserConfig>;
20
/** Config resolved hook */
21
configResolved?: (config: ResolvedConfig) => void | Promise<void>;
22
/** Configure server hook */
23
configureServer?: (server: ViteDevServer) => void | Promise<void>;
24
/** Configure preview server hook */
25
configurePreviewServer?: (server: PreviewServer) => void | Promise<void>;
26
/** Build start hook */
27
buildStart?: (opts: InputOptions) => void | Promise<void>;
28
/** Build end hook */
29
buildEnd?: (err?: Error) => void | Promise<void>;
30
/** Write bundle hook */
31
writeBundle?: (options: OutputOptions, bundle: OutputBundle) => void | Promise<void>;
32
/** Close bundle hook */
33
closeBundle?: () => void | Promise<void>;
34
/** Generate bundle hook */
35
generateBundle?: (options: OutputOptions, bundle: OutputBundle) => void | Promise<void>;
36
/** Render chunk hook */
37
renderChunk?: (code: string, chunk: RenderedChunk, options: OutputOptions) => string | { code: string; map?: SourceMapInput } | null | Promise<string | { code: string; map?: SourceMapInput } | null>;
38
/** Transform hook */
39
transform?: (code: string, id: string) => string | { code: string; map?: SourceMapInput } | null | Promise<string | { code: string; map?: SourceMapInput } | null>;
40
/** Load hook */
41
load?: (id: string) => string | { code: string; map?: SourceMapInput } | null | Promise<string | { code: string; map?: SourceMapInput } | null>;
42
/** Resolve ID hook */
43
resolveId?: (id: string, importer?: string, options?: { custom?: any; isEntry: boolean }) => string | { id: string; external?: boolean } | null | Promise<string | { id: string; external?: boolean } | null>;
44
/** Handle HMR update */
45
handleHotUpdate?: (ctx: HmrContext) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>;
46
}
47
48
type PluginOption = Plugin | false | null | undefined | PluginOption[];
49
50
/**
51
* Plugin hook handler with context
52
*/
53
interface HookHandler<T, O> {
54
handler: T;
55
order?: 'pre' | 'post' | null;
56
once?: boolean;
57
}
58
```
59
60
**Usage Examples:**
61
62
```typescript
63
import type { Plugin } from "vite";
64
65
// Basic plugin
66
function myPlugin(): Plugin {
67
return {
68
name: 'my-plugin',
69
config(config, { command }) {
70
if (command === 'serve') {
71
config.define = config.define || {};
72
config.define.__DEV__ = true;
73
}
74
},
75
configureServer(server) {
76
server.middlewares.use('/api', myApiHandler);
77
}
78
};
79
}
80
81
// Plugin with options
82
interface MyPluginOptions {
83
prefix?: string;
84
debug?: boolean;
85
}
86
87
function myPluginWithOptions(options: MyPluginOptions = {}): Plugin {
88
return {
89
name: 'my-plugin-with-options',
90
enforce: 'pre',
91
apply: 'build',
92
transform(code, id) {
93
if (options.debug) {
94
console.log(`Transforming: ${id}`);
95
}
96
return options.prefix ? `${options.prefix}\n${code}` : code;
97
}
98
};
99
}
100
```
101
102
### Per-Environment Plugin
103
104
Create environment-specific plugins that can behave differently across environments.
105
106
```typescript { .api }
107
/**
108
* Create environment-specific plugin
109
* @param name - Plugin name
110
* @param factory - Factory function returning environment-specific plugin
111
* @returns Plugin that adapts to different environments
112
*/
113
function perEnvironmentPlugin(
114
name: string,
115
factory: (environment: Environment) => Plugin
116
): Plugin;
117
```
118
119
### Plugin Context
120
121
Context objects available to plugin hooks for accessing Vite functionality.
122
123
```typescript { .api }
124
interface ConfigPluginContext {
125
/** Add watch files */
126
addWatchFile(file: string): void;
127
/** Get watch files */
128
getWatchFiles(): string[];
129
}
130
131
interface MinimalPluginContextWithoutEnvironment {
132
/** Emit file */
133
emitFile(file: EmittedFile): string;
134
/** Get file name */
135
getFileName(referenceId: string): string;
136
/** Get module info */
137
getModuleInfo(id: string): ModuleInfo | null;
138
/** Get module IDs */
139
getModuleIds(): IterableIterator<string>;
140
/** Parse */
141
parse(input: string, options?: any): any;
142
/** Resolve */
143
resolve(id: string, importer?: string, options?: ResolveOptions): Promise<ResolveIdResult | null>;
144
/** Set asset source */
145
setAssetSource(referenceId: string, source: string | Uint8Array): void;
146
/** Error */
147
error(message: string | RollupError, position?: number | { column: number; line: number }): never;
148
/** Warn */
149
warn(message: string | RollupError, position?: number | { column: number; line: number }): void;
150
}
151
```
152
153
### Plugin Utilities
154
155
Utility interfaces and types for plugin development.
156
157
```typescript { .api }
158
interface PluginHookUtils {
159
/** Get combined transforms */
160
getCombinedSourcemap(): SourceMap;
161
}
162
163
/**
164
* Plugin with required hook constraint
165
*/
166
type PluginWithRequiredHook<K extends keyof Plugin> = Plugin & Required<Pick<Plugin, K>>;
167
168
/**
169
* Falsy plugin type for conditional plugins
170
*/
171
type FalsyPlugin = false | null | undefined;
172
```
173
174
### Plugin Container
175
176
Container that manages and executes plugins during development and build.
177
178
```typescript { .api }
179
interface PluginContainer {
180
/** Build start */
181
buildStart(options: InputOptions): Promise<void>;
182
/** Resolve ID */
183
resolveId(id: string, importer?: string, options?: ResolveOptions): Promise<string | null>;
184
/** Load module */
185
load(id: string, options?: { ssr?: boolean }): Promise<LoadResult | null>;
186
/** Transform code */
187
transform(code: string, id: string, options?: TransformOptions): Promise<TransformResult | null>;
188
/** Close container */
189
close(): Promise<void>;
190
}
191
192
interface SkipInformation {
193
/** Skipped plugin names */
194
skipped: Set<string>;
195
/** Skip reason */
196
reason: string;
197
}
198
```
199
200
## Built-in Plugin Hooks
201
202
### Configuration Hooks
203
204
Hooks for modifying and accessing configuration.
205
206
```typescript { .api }
207
/**
208
* Modify configuration before resolution
209
* @param config - User configuration
210
* @param env - Configuration environment
211
* @returns Modified config or void
212
*/
213
type ConfigHook = (
214
config: UserConfig,
215
env: ConfigEnv
216
) => void | UserConfig | Promise<void | UserConfig>;
217
218
/**
219
* Access resolved configuration
220
* @param config - Resolved configuration
221
*/
222
type ConfigResolvedHook = (config: ResolvedConfig) => void | Promise<void>;
223
```
224
225
### Server Hooks
226
227
Hooks for configuring development and preview servers.
228
229
```typescript { .api }
230
/**
231
* Configure development server
232
* @param server - Vite dev server instance
233
*/
234
type ConfigureServerHook = (server: ViteDevServer) => void | Promise<void>;
235
236
/**
237
* Configure preview server
238
* @param server - Preview server instance
239
*/
240
type ConfigurePreviewServerHook = (server: PreviewServer) => void | Promise<void>;
241
```
242
243
### HMR Hooks
244
245
Hooks for handling Hot Module Replacement.
246
247
```typescript { .api }
248
/**
249
* Handle HMR update
250
* @param ctx - HMR context with file and modules information
251
* @returns Array of modules to update or void
252
*/
253
type HandleHotUpdateHook = (
254
ctx: HmrContext
255
) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>;
256
257
interface HmrContext {
258
/** File path that changed */
259
file: string;
260
/** Timestamp of change */
261
timestamp: number;
262
/** Affected modules */
263
modules: Set<ModuleNode>;
264
/** Read file contents */
265
read: () => string | Promise<string>;
266
/** Vite dev server */
267
server: ViteDevServer;
268
}
269
```
270
271
## Plugin Development Patterns
272
273
### Conditional Plugins
274
275
Apply plugins conditionally based on environment or configuration.
276
277
```typescript { .api }
278
// Environment-based application
279
const myPlugin = (): Plugin => ({
280
name: 'my-plugin',
281
apply: 'build', // Only during build
282
// ... plugin implementation
283
});
284
285
// Function-based application
286
const conditionalPlugin = (): Plugin => ({
287
name: 'conditional-plugin',
288
apply: (config, { command, mode }) => {
289
return command === 'build' && mode === 'production';
290
},
291
// ... plugin implementation
292
});
293
```
294
295
### Plugin Ordering
296
297
Control plugin execution order with enforcement.
298
299
```typescript { .api }
300
// Pre-plugins run before Vite's internal plugins
301
const prePlugin = (): Plugin => ({
302
name: 'pre-plugin',
303
enforce: 'pre',
304
// ... runs early
305
});
306
307
// Post-plugins run after Vite's internal plugins
308
const postPlugin = (): Plugin => ({
309
name: 'post-plugin',
310
enforce: 'post',
311
// ... runs late
312
});
313
```