Building a plugin system for a nodejs based MVC platform

I would like to be able to build functionality for my application in a plugin style system for a couple reasons:

  1. New projects can choose which plugins are necessary and not have code for functionality that's not needed
  2. Other developers can build plugins for the system without needing too much knowledge of the core workings.

I'm not really sure how to go about implementing this. I would like to have a plugins folder to host these separately but I guess my questions are:

  1. How do plugins interact with the core system?
  2. How does the folder structure work? Would each hold the standard MVC structure: controllers, services, models, views, etc?

I guess if anyone has a tutorial or some documentation relating to this technique that would be helpful. I've done a bit of searching but it's all a little too closely related to the actual code they're working with instead of the concept and I hadn't found anything specifically related to nodejs.

I suggest an approach similar to what I've done on the uptime project (https://github.com/fzaninotto/uptime/blob/master/app.js#L46):

  • trigger application events in critical parts of your application
  • add a 'plugins' section in the applicaition configuration
  • each plugin name must be a package name. The plugin packages should return either a callback, or an object with an init() function.
  • either way, inject to the plugins the objects they will need to run (configuration, connections, etc) when calling init(), or executing the callback.
  • plugin modules register listeners to the application events and modify it

Benefits:

  • lightweight
  • rely on npm for dependencies
  • don't reivent the wheel

Create a plugin prototype for the base functionality, and let the user define its plugin in a module. In the module the user would inherit an object from the prototype, extend its functionality, and then export a constructor which returns the plugin object.

The main system loads all plugins by require("pluginname") and for each calls the constructor.