Feature: Custom Hooks
Custom hooks would be useful for plugin creators looking to extend an already existing plugin's functionality. For example, let's say I wanted to create a plugin that adds to (or modifies) the presets in unplugin-auto-import; I could use the "presets" hook to gain access to the presets map and modify it from there. Since webpack already allows plugins to create their own hooks, we can see some already existing use cases, like how the html-webpack-plugin lets other plugins modify the HTML output in various locations.
Proof of Concept
Here's a rough design of what the custom hooks API could look like.
Creating hooks:
import { createUnplugin, SyncHook } from 'unplugin';
import { SyncHook } from 'unplugin/hooks'; // Maybe even separate hook types into another import
export const unplugin = createUnplugin((options) => {
return {
name: 'unplugin-auto-import',
hooks: {
presets: SyncHook, // Define the hook
},
buildStart() {
this.hooks.presets(currentPresets); // Run the hook
},
};
});
export const hooks = unplugin.hooks
Using hooks:
import { createUnplugin } from 'unplugin';
import UnpluginAutoImportHooks from 'unplugin-auto-import/hooks';
export const unplugin = createUnplugin((options) => {
return {
name: 'unplugin-auto-import-presets',
// Use hook from another unplugin
[ UnpluginAutoImportHooks.presets /* this is a symbol to ensure uniqueness */ ](presets) {
presets['my-preset'] = '...';
delete presets.react;
},
};
});
I personally would consider this a bit out-of-scope.
/cc @pi0 do you think this could have a valid use case using bookable?
I think this feature can be easily implemented by creating a hookable instance and register user provided hooks but also seems a nice idea to consider being built-in (can't think of any generic use case). On one hand, simple callback option can be also used for simpler usecases.
One way I think could be more generic is that we implement the Rollups' api props that basically allowing arbitrary objects to pass in, and let plugins define the interface (via bookable or plain values). https://rollupjs.org/guide/en/#inter-plugin-communication
That does seem like a better option, as it more closely follows Rollup's API.
@antfu, I have created a new proposal that includes your suggestions and follows closer to Rollup's API. I also included a method to create new plugin instances (if they do not already exist) (suggested in https://github.com/unjs/unplugin/issues/173).
Closing in favor of https://github.com/unjs/unplugin/issues/174.