Custom hooks for the build-plugins ecosystem.
If your plugin is producing something that will be shared with other plugins,
you should create a custom hook to let other plugins use it as soon as it is available.
- Add your new hook to the
CustomHooksinterface in./src/types.ts.:
export type CustomHooks = {
// [...]
myCustomSyncHook?: HookFn<[MyData]>;
// or
myCustomAsyncHook?: AsyncHookFn<[MyData]>;
};- Call your hook through the context when the data is available.
// If it is an asynchronous hook
await context.asyncHook('myCustomAsyncHook', data);
// If it is a synchronous hook
context.hook('myCustomSyncHook', data);Note
When you want to create a custom hook, you should use await context.asyncHook() whenever you can, as it is more permissive and flexible.
But it can only be used from another async hook.
If you're creating a custom hook from a sync hook, you don't have a choice but to use context.hook()
- Document it on your plugin's README.md file under a
## Hookssection, explaining when it triggers and what it is useful for.
## Hooks
### `myCustomSyncHook`
This hook is called when the data is available.
```typescript
{
name: 'my-plugin',
myCustomSyncHook(data: MyData) {
// Do something with the data
}
}
```Note
If the context allows you to, prefer using async hooks over sync hooks. This way, subscribers can use them both synchronously and asynchronously.
If your plugin is dependent on some other plugin's custom hook, you can use it from your plugin's definition:
{
name: 'my-plugin',
myCustomSyncHook(data) {
// Do something with the data
},
async myCustomAsyncHook(data) {
// Do something with the data
}
}Note
- Data sent through the hooks are usually mutable, except for primitives.
- Hooks are typed
voidby default, so you don't have to return anything.
This hook is called when the build report has been generated.
It is useful to get the current build's dependency graph for instance.
Happens during the writeBundle hook.
{
name: 'my-plugin',
buildReport(report: BuildReport) {
// Do something with the data
}
}This hook is called when the bundler report is generated.
It is useful to get the current bundler's configuration for instance.
{
name: 'my-plugin',
bundlerReport(report: BundlerReport) {
// Do something with the data
}
}This hook is called when the build root directory is computed.
{
name: 'my-plugin',
buildRoot(buildRoot: string) {
// Do something with the data
}
}This hook is called when the git repository data is computed.
{
name: 'my-plugin',
async git(git: RepositoryData) {
// Do something with the data
}
}This hook is called when the metrics are aggregated and before they are sent to Datadog.
{
name: 'my-plugin',
async metrics(metrics: Set<MetricToSend>) {
// Do something with the metrics
}
}This hook is called when the timings are aggregated.
{
name: 'my-plugin',
async timings(timings: TimingsReport) {
// Do something with the timings
}
}This hook is called at the very end of the build asynchronously.
It may execute sooner than syncTrueEnd in some contexts:
esbuildwill callasyncTrueEndbeforesyncTrueEnd.- We use
build.onDispose, for the latest hook possible in the build. The issue is, it's synchronous only. So we have to usebuild.onEndfor the asynchronousasyncTrueEnd, but it's called well beforebuild.onDispose.
- We use
{
name: 'my-plugin',
async asyncTrueEnd() {
// Do something asynchronous on closure
await someAsyncOperation();
}
}This hook is called at the very end of the build synchronously.
{
name: 'my-plugin',
syncTrueEnd() {
// Do something synchronous on closure
someSyncOperation();
}
}