Enabling Dynamic Plugin Support for your JavaScript Application
Hi fellow reader,
I recently came through a problem while working on a javascript framework on top of jQuery. At one point, having one big javascript file containing all the application objects becomes hard to both naviguate and maintain.
From here you want to ease your developement process by splitting your main class in small, specialized, classes stored in different files and then includes all these files using <script> tags. This is not convenient, you will have HTTP connections overhead even before your page DOM is loaded and displayed.
You could eventually make use of a server side tool like the PHP library Minify to combine, minify and cache your javascript files. Hovewer I’ll talk about a system that dynamically and on-demand loads components using jQuery’s Ajax implementation.
Simple Javascript Class
Let’s start a simple Javascript Class :
var shinyObject = function() {
};
Extending our classe with the saySomething() method :
shinyObject.saySomething = function() {
alert("Something");
}
Ok, in firebug console we can now type shinyObject.saySomething(); and the revelant code will be executed.
Plugin support
Warning, the following code is for concept demonstration pupose only on should not be used in production. Please disregard security concerns, this is not the point.
Onto creating our plugin module loader for our main class. Here is the new method :
shinyObject.loadPlugin = function(options) {
this.plugin_path = "./";
$.ajax(
{
type : "get",
url : shinyObject.plugin_path + options.name + ".js",
dataType : "text",
success : function(code) {
if(typeof shinyObject[options.name] != 'object') {
var plugin = eval(code);
if(typeof plugin == 'object') {
shinyObject[options.name] = plugin;
}
else {
alert("Impossible to load " + options.name + " module. Please check your module code syntax.");
}
}
}
}
)
This snippet is rather easy to understand, the loadPlugin method take a single JSON object as argument, this is convenient because we will want to add more parameters later. The name of an existing file is passed to the ajax() jQuery method and the results of this HTTP request is passed to a callback function.
If shinyObject do not already have an instance of this particular plugin in its register table, then we evaluate the code. If the evaluated source code is a valid javascript object, we are affecting it to a new entry in it’s register table, otherwise, warn the developper of possible mistake in the plugin.
Creating a Plugin
To create a plugin for our appplication let’s create a new file in shinyObject.plugin_path named saySomethingElse.js and put the following snippet inside :
(function () { var a_local_variable = "local variable is local"; return { saySomethingElse = function() { alert("Something Else Matters!") alert("And you can use local variables because : " + a_local_variable); } } })();The important thing here is the self executing function notation :
(function () { /* code */ })();
This notation is making the difference between a simple library and an autoexecuting piece of code that returns an object.
Loading a Plugin
Will are now adding the loadPlugin() call to our the onReady event of the page:
$(document).ready(function() {
shinyObject.loadPlugin({'name': 'saySomethingElse'});
});
Once the DOM ready for action, our shinyObject will automatically load its dependencies. If the code contained in your plugin do not have to deal with the DOM at all, you can safely make this call directly from the <head> part of your html document. Call me obessional programmer if you want, but I personaly find it more convenient to have everything initialized a the same place.
Using our Plugin
Once loaded successfuly, you can access your plugin’s public methods and properties like this :
/* Simple Method call */ shinyObject.saySomethingElse.saySomethingElse(); /* Object.ModuleName.Method(); */As simple as 1, 2, 3.
Conclusion
What we achieved here is rather simple but can be extremely useful in nowadays web applications, even regarding performances. Let’s say we are building a big application with hundred of plugins that may be optional widgets for our users. The solution described at the begining of this article will generate a great overhead in both bandwith and HTTP requests prior page rendering.
Benefits of our dynamic plugins:
- Fast Page rendering
- Decoupled loading using Asyncronous HTTP
- Saves a part of the Bandwidth
- Easier library management for developpers
What about you dear reader ? What are your solutions for huge javascript libraries management and plugin support ? I’m really interested to know about it !










Any thought to an alternative to eval()?
http://blogs.msdn.com/ericlippert/archive/2003/11/01/53329.aspx
P.S. How about implementing this within the confines of jquery.livequery.js? For example, say i want to run my $().alternate() plugin on all tables? Currently I use this…
$(‘table’).livequery(function(){
$(this).alternate();
});
How might i use your concept to only load the alternate plugin when it’s needed here?
@Brian
Hi Brian !
Thanks for the pointer to a great article!
Here is an excerpt from Eval is Evil article, first paragraph:
I think we are in that particularly invaluable usage of eval :)
@Nicolas Crovatti
Thanks for the reply Nicolas! I’ve come across the “eval() is evil” comment on several occasions so I was curious. Obviously i have things to learn ;)
@Brian
The concept exposed here is based on a Javascript Framework that makes some use of core jQuery implementation, it’s not built using jQuery plugins systems.
To apply the very same concept for jQuery plugins system, you might want to create first a plugins that deals with plugins management like exposed here ;)
Thank you for your help!