Read my book

I wrote books about Webpack and React. Check them out!

Tuesday, July 13, 2010

How to write a plugin system in JavaScript?

In this post I aim to provide some ideas for those that wish to build a plugin system for their JavaScript application. I have adapted this post from my work with my Harmony fork.

My system has been inspired heavily by the plugin mechanism of jQuery. Besides the basic idea there are a few special considerations (configuration, includes) to keep in mind. Let's have a look at the system next:

Plugin System Structure

I have structured my system in the following manner:

  • /conf.js - Configuration of the project. The names of the plugins are stashed here.
  • /init.js - Initialization file of the project. This file loads the plugins and sets their initial state. Note that this file depends on conf.js.
  • /plugins - The plugin directory.
  • /myapp.html - The actual application. This should refer to both conf.js and init.js (in this particular order!).
The idea is that the user may determine plugins to use in conf.js. Alternatively a user interface might be provided to constrain the plugins to use within the app itself. In this case there would have to be some manner to store the configuration on the user side using cookies, localStorage or some other way.

conf.js

A simple conf.js may look like this:


It justs lists the names of plugins to use. Each name maps to some actual file and a member of plugins object.

init.js

Let's have a look at init.js next:



I decided to use a map to store plugin location and callback information. I use includeMany jQuery plugin to load the plugins and after that's done I execute a callback that initializes the plugins should that be needed.

After this file has been executed, plugins may be accessed via globals set up at the beginning of the file (ie. just "panels" in this case).

We are still missing a crucial component, the plugin itself!

Plugins

Here's an actual example of a plugin:



It's important to note how it attaches to a global set at init.js. This makes it possible to refer to the actual plugin easily.

If you need to provide more complicated functionality (ie. multiple methods with shared state), you might want to consider setting up a method that returns a reference to "this" and then operate on that. For instance "init" could just return "this" or there could be a separate constructor for this case.

Conclusion

It didn't take that many steps to come up with a simple plugin system. As it hooks up to the basic functionality of JavaScript it should be relatively easy to use. Hopefully you will find the system useful in your project. :)