0
# Plugin Context API
1
2
Complete plugin development API providing access to the service layer's capabilities including comprehensive lifecycle hooks, method registration, build customization, and validation support.
3
4
## Capabilities
5
6
### Plugin Context Interface
7
8
The primary API interface available to all plugins providing access to the kernel's capabilities and state.
9
10
```typescript { .api }
11
/**
12
* Plugin context interface defining the complete API available to plugins
13
*/
14
interface IPluginContext {
15
/** Map of all registered plugins */
16
plugins: Map<string, IPlugin>;
17
/** Map of all registered platforms */
18
platforms: Map<string, IPlatform>;
19
/** Path configuration object */
20
paths: IPaths;
21
/** Runtime options from command execution */
22
runOpts: any;
23
/** Helper utilities from @tarojs/helper package */
24
helper: typeof helper;
25
/** Runner utilities from @tarojs/runner-utils package */
26
runnerUtils: typeof runnerUtils;
27
/** Initial project configuration */
28
initialConfig: IProjectConfig;
29
30
// Registration methods
31
register(hook: IHook): void;
32
registerMethod(arg: string | { name: string; fn?: Func }, fn?: Func): void;
33
registerCommand(command: ICommand): void;
34
registerPlatform(platform: IPlatform): void;
35
36
// Hook execution
37
applyPlugins(args: string | { name: string; initialVal?: any; opts?: any }): Promise<any>;
38
39
// Validation
40
addPluginOptsSchema(fn: (joi: joi.Root) => void): void;
41
}
42
```
43
44
### Hook Registration
45
46
Register hooks to participate in the build process and customize behavior at specific lifecycle points.
47
48
```typescript { .api }
49
/**
50
* Register a hook to be called during the build process
51
* @param hook - Hook configuration object
52
*/
53
register(hook: IHook): void;
54
55
interface IHook {
56
/** Hook name (e.g., 'onBuildStart', 'modifyWebpackChain') */
57
name: string;
58
/** Plugin ID that registered this hook (automatically set) */
59
plugin?: string;
60
/** Hook implementation function */
61
fn: Func;
62
/** Execute this hook before another hook */
63
before?: string;
64
/** Execution stage (lower numbers execute first) */
65
stage?: number;
66
}
67
```
68
69
**Usage Examples:**
70
71
```typescript
72
// Build lifecycle hook
73
ctx.register({
74
name: 'onBuildStart',
75
fn: async (opts) => {
76
console.log('Build starting for platform:', opts.platform);
77
}
78
});
79
80
// Configuration modification hook
81
ctx.register({
82
name: 'modifyWebpackChain',
83
fn: (opts, { chain }) => {
84
chain.plugin('MyPlugin').use(MyWebpackPlugin, [options]);
85
return { chain };
86
}
87
});
88
89
// Hook with execution order control
90
ctx.register({
91
name: 'modifyWebpackChain',
92
stage: 100, // Execute later
93
fn: (opts, { chain }) => {
94
// This runs after hooks with lower stage numbers
95
}
96
});
97
```
98
99
### Build Lifecycle Hooks
100
101
Pre-defined lifecycle hooks available for build process customization.
102
103
```typescript { .api }
104
/**
105
* Hook called when build process starts
106
*/
107
onBuildStart(fn: Func): void;
108
109
/**
110
* Hook called when build process finishes (after each save in watch mode)
111
*/
112
onBuildFinish(fn: Func): void;
113
114
/**
115
* Hook called when build process completes (once after initial build)
116
*/
117
onBuildComplete(fn: Func): void;
118
119
/**
120
* Hook called during compiler.make phase
121
*/
122
onCompilerMake(fn: (args: { compilation: Webpack.Compilation; compiler: Webpack.Compiler; plugin: any }) => void): void;
123
```
124
125
**Usage Examples:**
126
127
```typescript
128
// Build start hook
129
ctx.onBuildStart(async (opts) => {
130
console.log('Starting build...');
131
// Initialize build resources
132
});
133
134
// Build finish hook (called on each rebuild)
135
ctx.onBuildFinish(async (opts) => {
136
console.log('Build finished');
137
// Cleanup or post-processing
138
});
139
140
// Build complete hook (called once)
141
ctx.onBuildComplete(async (opts) => {
142
console.log('Initial build complete, ready for development');
143
// Open browser, start additional services, etc.
144
});
145
```
146
147
### Configuration Modification Hooks
148
149
Hooks for modifying various aspects of the build configuration.
150
151
```typescript { .api }
152
/**
153
* Modify App configuration before compilation
154
*/
155
modifyAppConfig(fn: (args: { appConfig: AppConfig }) => void): void;
156
157
/**
158
* Modify webpack configuration using webpack-chain
159
*/
160
modifyWebpackChain(fn: (args: { chain: Chain; webpack: typeof Webpack; data?: IModifyChainData }) => void): void;
161
162
/**
163
* Modify Vite configuration
164
*/
165
modifyViteConfig(fn: (args: { viteConfig: any; data?: IModifyChainData; viteCompilerContext: any }) => void): void;
166
167
/**
168
* Modify build assets after compilation
169
*/
170
modifyBuildAssets(fn: (args: { assets: any; miniPlugin: any }) => void): void;
171
172
/**
173
* Modify mini-program configuration files
174
*/
175
modifyMiniConfigs(fn: (args: { configMap: IMiniFilesConfig }) => void): void;
176
177
/**
178
* Modify runner options before execution
179
*/
180
modifyRunnerOpts(fn: (args: { opts: any }) => void): void;
181
```
182
183
**Usage Examples:**
184
185
```typescript
186
// Modify webpack configuration
187
ctx.modifyWebpackChain(({ chain, webpack }) => {
188
// Add custom plugin
189
chain.plugin('MyCustomPlugin')
190
.use(MyCustomPlugin, [{ option: 'value' }]);
191
192
// Modify loader
193
chain.module
194
.rule('custom-rule')
195
.test(/\.custom$/)
196
.use('custom-loader')
197
.loader('custom-loader');
198
});
199
200
// Modify app configuration
201
ctx.modifyAppConfig(({ appConfig }) => {
202
appConfig.pages.push('pages/custom/index');
203
appConfig.window.navigationBarTitleText = 'Custom Title';
204
});
205
206
// Modify build assets
207
ctx.modifyBuildAssets(({ assets, miniPlugin }) => {
208
// Add or modify generated files
209
assets['custom-file.json'] = JSON.stringify({ custom: 'data' });
210
});
211
```
212
213
### Command Registration
214
215
Register custom commands that can be executed via the CLI or programmatically.
216
217
```typescript { .api }
218
/**
219
* Register a custom command
220
* @param command - Command configuration object
221
*/
222
registerCommand(command: ICommand): void;
223
224
interface ICommand extends IHook {
225
/** Command alias for CLI */
226
alias?: string;
227
/** CLI options mapping for help display */
228
optionsMap?: Record<string, string>;
229
/** Usage examples for help display */
230
synopsisList?: string[];
231
}
232
```
233
234
**Usage Examples:**
235
236
```typescript
237
// Basic command
238
ctx.registerCommand({
239
name: 'analyze',
240
fn: async (opts) => {
241
console.log('Analyzing project...');
242
// Analysis logic
243
}
244
});
245
246
// Command with CLI options and help
247
ctx.registerCommand({
248
name: 'deploy',
249
alias: 'd',
250
optionsMap: {
251
'--env [env]': 'deployment environment',
252
'--dry-run': 'preview deployment without executing'
253
},
254
synopsisList: [
255
'taro deploy --env production',
256
'taro deploy --dry-run'
257
],
258
fn: async (opts) => {
259
const { env, dryRun } = opts.options;
260
// Deployment logic
261
}
262
});
263
```
264
265
### Platform Registration
266
267
Register custom platforms that can be targeted for builds.
268
269
```typescript { .api }
270
/**
271
* Register a custom platform
272
* @param platform - Platform configuration object
273
*/
274
registerPlatform(platform: IPlatform): void;
275
276
interface IPlatform extends IHook {
277
/** Configuration section name to use for this platform */
278
useConfigName?: string;
279
}
280
```
281
282
**Usage Examples:**
283
284
```typescript
285
// Register custom platform
286
ctx.registerPlatform({
287
name: 'my-platform',
288
useConfigName: 'mini', // Use mini-program config section
289
fn: (opts) => {
290
const platform = new MyCustomPlatform(ctx, opts.config);
291
return platform.start();
292
}
293
});
294
295
// Register platform with custom config
296
ctx.registerPlatform({
297
name: 'electron',
298
useConfigName: 'electron',
299
fn: (opts) => {
300
// Electron platform build logic
301
}
302
});
303
```
304
305
### Method Registration
306
307
Register methods that can be called by other plugins.
308
309
```typescript { .api }
310
/**
311
* Register a method that can be called by other plugins
312
* @param arg - Method name or configuration object
313
* @param fn - Method implementation (if first arg is string)
314
*/
315
registerMethod(arg: string | { name: string; fn?: Func }, fn?: Func): void;
316
```
317
318
**Usage Examples:**
319
320
```typescript
321
// Register utility method
322
ctx.registerMethod('getProjectInfo', () => {
323
return {
324
name: ctx.initialConfig.projectName,
325
framework: ctx.initialConfig.framework
326
};
327
});
328
329
// Register method with object syntax
330
ctx.registerMethod({
331
name: 'customTransform',
332
fn: (data) => {
333
// Custom transformation logic
334
return transformedData;
335
}
336
});
337
338
// Use registered method in another plugin
339
const projectInfo = ctx.getProjectInfo();
340
```
341
342
### Plugin Options Validation
343
344
Add validation schema for plugin options using Joi.
345
346
```typescript { .api }
347
/**
348
* Add validation schema for plugin options
349
* @param fn - Function that receives Joi instance and returns schema
350
*/
351
addPluginOptsSchema(fn: (joi: joi.Root) => void): void;
352
```
353
354
**Usage Examples:**
355
356
```typescript
357
// Add options validation
358
ctx.addPluginOptsSchema((joi) => {
359
return joi.object({
360
outputDir: joi.string().required(),
361
minify: joi.boolean().default(true),
362
target: joi.string().valid('es5', 'es6').default('es5'),
363
plugins: joi.array().items(joi.string())
364
});
365
});
366
367
// Plugin with validated options
368
export default (ctx, opts) => {
369
// opts is now validated and has defaults applied
370
console.log(opts.outputDir); // Required string
371
console.log(opts.minify); // Boolean, defaults to true
372
};
373
```
374
375
### Hook Execution
376
377
Execute registered hooks programmatically within plugins.
378
379
```typescript { .api }
380
/**
381
* Execute registered hooks with optional initial value and options
382
* @param args - Hook name or configuration object
383
* @returns Promise resolving to final transformed value
384
*/
385
applyPlugins(args: string | { name: string; initialVal?: any; opts?: any }): Promise<any>;
386
```
387
388
**Usage Examples:**
389
390
```typescript
391
// Execute simple hook
392
await ctx.applyPlugins('customHook');
393
394
// Execute hook with initial value (modify pattern)
395
const modifiedConfig = await ctx.applyPlugins({
396
name: 'modifyCustomConfig',
397
initialVal: baseConfig,
398
opts: { context: 'build' }
399
});
400
401
// Execute hook and collect results (add pattern)
402
const additionalItems = await ctx.applyPlugins({
403
name: 'addCustomItems',
404
initialVal: [],
405
opts: { filter: 'active' }
406
});
407
```
408
409
## Context Properties
410
411
```typescript { .api }
412
interface IPaths {
413
/** Current command execution directory */
414
appPath: string;
415
/** Project configuration directory */
416
configPath: string;
417
/** Project source code directory */
418
sourcePath: string;
419
/** Build output directory */
420
outputPath: string;
421
/** Node modules directory */
422
nodeModulesPath: string;
423
}
424
425
interface IPlugin {
426
/** Unique plugin identifier */
427
id: string;
428
/** Plugin file path */
429
path: string;
430
/** Plugin configuration options */
431
opts: any;
432
/** Plugin type (Plugin or Preset) */
433
type: PluginType;
434
/** Plugin apply function */
435
apply: Func;
436
}
437
```
438
439
## Plugin Development Best Practices
440
441
### Plugin Structure Template
442
443
```typescript
444
export default (ctx, opts = {}) => {
445
// Add options validation
446
ctx.addPluginOptsSchema((joi) => {
447
return joi.object({
448
// Define your options schema
449
});
450
});
451
452
// Register hooks
453
ctx.onBuildStart(async () => {
454
// Build start logic
455
});
456
457
ctx.modifyWebpackChain(({ chain }) => {
458
// Webpack modifications
459
});
460
461
// Register custom methods
462
ctx.registerMethod('myUtility', () => {
463
// Utility logic
464
});
465
};
466
```
467
468
### Error Handling in Hooks
469
470
```typescript
471
ctx.register({
472
name: 'onBuildStart',
473
fn: async (opts) => {
474
try {
475
// Build logic that might fail
476
await riskyOperation();
477
} catch (error) {
478
ctx.helper.printLog('ERROR', 'Build failed', error.message);
479
throw error; // Re-throw to stop build
480
}
481
}
482
});
483
```