0
# Plugin System
1
2
Comprehensive plugin system supporting both server-side and client-side plugins with hook management, plugin registration, and execution control.
3
4
## Capabilities
5
6
### Plugin Application Types
7
8
Enumeration defining how plugins are applied and executed.
9
10
```typescript { .api }
11
/**
12
* Plugin application types for different execution patterns
13
*/
14
enum ApplyPluginsType {
15
compose = "compose", // Function composition pattern
16
modify = "modify", // Value modification pattern
17
event = "event" // Event-driven pattern
18
}
19
```
20
21
### Plugin Manager
22
23
Client-side plugin manager for registering and executing plugins with type safety and validation.
24
25
```typescript { .api }
26
/**
27
* Client-side plugin manager for hook registration and execution
28
*/
29
class PluginManager {
30
/**
31
* Creates a new plugin manager instance
32
* @param opts - Configuration with valid hook keys
33
*/
34
constructor(opts: PluginManagerOpts);
35
36
/**
37
* Register a plugin with the manager
38
* @param plugin - Plugin definition with apply methods
39
*/
40
register(plugin: IPlugin): void;
41
42
/**
43
* Get hooks for a specific key, supporting dot notation
44
* @param keyWithDot - Hook key, optionally with member access (e.g., "key.member")
45
* @returns Array of registered hooks for the key
46
*/
47
getHooks(keyWithDot: string): any[];
48
49
/**
50
* Apply plugins for a specific hook key
51
* @param opts - Plugin application options
52
* @returns Result based on application type
53
*/
54
applyPlugins(opts: ApplyPluginsOpts): any;
55
56
/**
57
* Create and initialize a plugin manager with plugins
58
* @param opts - Manager configuration with plugins
59
* @returns Configured plugin manager instance
60
*/
61
static create(opts: CreatePluginManagerOpts): PluginManager;
62
}
63
64
interface PluginManagerOpts {
65
validKeys: string[]; // Array of valid hook keys
66
}
67
68
interface IPlugin {
69
path?: string; // Plugin file path for debugging
70
apply: Record<string, any>; // Hook implementations
71
}
72
73
interface ApplyPluginsOpts {
74
key: string; // Hook key to apply
75
type: ApplyPluginsType; // Application type
76
initialValue?: any; // Initial value for modify type
77
args?: object; // Arguments passed to hooks
78
async?: boolean; // Whether to use async execution
79
}
80
81
interface CreatePluginManagerOpts {
82
validKeys: string[];
83
plugins: IPlugin[];
84
}
85
```
86
87
**Usage Examples:**
88
89
```typescript
90
import { PluginManager, ApplyPluginsType } from "umi/client";
91
92
// Create plugin manager
93
const pluginManager = new PluginManager({
94
validKeys: ["modifyRoutes", "onRouteChange", "render"],
95
});
96
97
// Register a plugin
98
pluginManager.register({
99
path: "./my-plugin.js",
100
apply: {
101
modifyRoutes: (routes) => {
102
return routes.concat([
103
{ path: "/custom", component: "CustomPage" }
104
]);
105
},
106
onRouteChange: ({ location }) => {
107
console.log("Route changed to:", location.pathname);
108
},
109
},
110
});
111
112
// Apply plugins with modify pattern
113
const modifiedRoutes = pluginManager.applyPlugins({
114
key: "modifyRoutes",
115
type: ApplyPluginsType.modify,
116
initialValue: baseRoutes,
117
});
118
119
// Apply plugins with event pattern
120
await pluginManager.applyPlugins({
121
key: "onRouteChange",
122
type: ApplyPluginsType.event,
123
args: { location: { pathname: "/new-route" } },
124
});
125
126
// Create manager with plugins in one step
127
const manager = PluginManager.create({
128
validKeys: ["beforeRender", "afterRender"],
129
plugins: [
130
{
131
apply: {
132
beforeRender: () => console.log("Before render"),
133
afterRender: () => console.log("After render"),
134
},
135
},
136
],
137
});
138
```
139
140
### Plugin Utilities
141
142
Utility functions and exports for plugin development and server-side functionality.
143
144
```typescript { .api }
145
/**
146
* Create server routes for API handling
147
* Re-exported from @umijs/server
148
*/
149
function createServerRoutes(...args: any[]): any;
150
151
/**
152
* Express server instance
153
* Re-exported from @umijs/bundler-utils
154
*/
155
const express: any;
156
157
/**
158
* HTTP proxy middleware for development
159
* Re-exported from @umijs/bundler-utils
160
*/
161
const httpProxyMiddleware: any;
162
163
// All utility functions from @umijs/utils are also available
164
// Including file system utilities, logger, validation, etc.
165
```
166
167
**Usage Examples:**
168
169
```typescript
170
import {
171
createServerRoutes,
172
express,
173
httpProxyMiddleware,
174
logger
175
} from "umi/plugin-utils";
176
177
// Create API routes
178
const routes = createServerRoutes({
179
"/api/users": "./api/users",
180
"/api/auth": "./api/auth",
181
});
182
183
// Use express for custom server setup
184
const app = express();
185
app.use("/api", routes);
186
187
// Add proxy middleware
188
app.use(
189
"/proxy",
190
httpProxyMiddleware({
191
target: "http://localhost:8080",
192
changeOrigin: true,
193
})
194
);
195
196
// Use logger utility
197
logger.info("Plugin initialized successfully");
198
```
199
200
### Client Utilities
201
202
Low-level utilities for client-side plugin functionality.
203
204
```typescript { .api }
205
/**
206
* Assertion utility for runtime validation
207
* @param value - Value to test
208
* @param message - Error message if assertion fails
209
*/
210
function assert(value: any, message: string): void;
211
212
/**
213
* Function composition utility for creating complex operations
214
* @param opts - Composition options with functions and arguments
215
* @returns Composed function
216
*/
217
function compose(opts: ComposeOpts): Function;
218
219
/**
220
* Promise detection utility
221
* @param obj - Object to test for promise-like behavior
222
* @returns True if object has then method
223
*/
224
function isPromiseLike(obj: any): boolean;
225
226
interface ComposeOpts {
227
fns: Function[]; // Functions to compose
228
args?: any; // Arguments to pass through
229
}
230
```
231
232
**Usage Examples:**
233
234
```typescript
235
import { assert, compose, isPromiseLike } from "umi/client";
236
237
// Runtime validation
238
assert(config.routes, "Routes configuration is required");
239
240
// Function composition
241
const pipeline = compose({
242
fns: [validateData, transformData, saveData],
243
args: { strict: true },
244
});
245
246
// Promise detection
247
if (isPromiseLike(result)) {
248
const data = await result;
249
} else {
250
const data = result;
251
}
252
```
253
254
## Plugin Application Patterns
255
256
### Modify Pattern
257
258
Used for transforming values through a chain of plugins:
259
260
```typescript
261
// Synchronous modification
262
const result = pluginManager.applyPlugins({
263
key: "modifyConfig",
264
type: ApplyPluginsType.modify,
265
initialValue: baseConfig,
266
});
267
268
// Asynchronous modification
269
const result = await pluginManager.applyPlugins({
270
key: "modifyConfig",
271
type: ApplyPluginsType.modify,
272
initialValue: baseConfig,
273
async: true,
274
});
275
```
276
277
### Event Pattern
278
279
Used for triggering side effects without return values:
280
281
```typescript
282
// Event execution (all hooks called)
283
await pluginManager.applyPlugins({
284
key: "onBuildComplete",
285
type: ApplyPluginsType.event,
286
args: { buildStats },
287
});
288
```
289
290
### Compose Pattern
291
292
Used for function composition and middleware patterns:
293
294
```typescript
295
// Function composition
296
const composedFn = pluginManager.applyPlugins({
297
key: "middleware",
298
type: ApplyPluginsType.compose,
299
initialValue: baseFn,
300
});
301
302
// Execute composed function
303
const result = composedFn();
304
```
305
306
## Type Definitions
307
308
```typescript { .api }
309
// Plugin application types
310
enum ApplyPluginsType {
311
compose = "compose",
312
modify = "modify",
313
event = "event"
314
}
315
316
// Plugin definition interface
317
interface IPlugin {
318
path?: string;
319
apply: Record<string, any>;
320
}
321
322
// Plugin manager configuration
323
interface PluginManagerOpts {
324
validKeys: string[];
325
}
326
327
// Plugin application options
328
interface ApplyPluginsOpts {
329
key: string;
330
type: ApplyPluginsType;
331
initialValue?: any;
332
args?: object;
333
async?: boolean;
334
}
335
336
// Plugin manager creation options
337
interface CreatePluginManagerOpts {
338
validKeys: string[];
339
plugins: IPlugin[];
340
}
341
342
// Function composition options
343
interface ComposeOpts {
344
fns: Function[];
345
args?: any;
346
}
347
```