Tuesday, February 17, 2009

Building fast jQuery plugins

There are 3 million articles out there about making jQuery plugins, but most of them seem to focus on the basics. That is all well and good, but none of those articles will help you if you want to write a fast, responsive plugin that wont peg the CPU.

I will outline some techniques that have worked for me in building good jQuery plugins.

  • Cache your selectors. Not caching can be a real performance killer, once you select an element, cache it, if you plan to use it again. Even ID selectors should be cached. it will always be faster to reuse a cached selector than to ask the DOM for it. When it comes to plugins, you can hide the cached selectors in the main closure, and reuse them in the methods of the plugin.
  • Cache your state. It will always be faster to check if a boolean is true, than to check if a DOM element is visible. Forget about the DOM. Cache everything you will need access to, cache your modifications. DOM access is slow. I will exchange a few bytes of memory for a few ms of execution any day.
  • Use closures. If you dont know how to use closures, you must learn now. You wont be able to write a good plugin if you dont know when and how to use these. You should use the closure to hide all your config data, your cached selectors etc.
  • Dont use $.fn. if it doesnt make sense. Sometimes it makes sense to return something other then the jQuery object from your plugin. You can always pass in the 'this' the old school way as an argument. Sometimes it may be better to return an object that makes some methods from the closure 'public' and exposes some members. This kind of an object can be useful when writing unit tests, or if you want to provide a rich API without bastardizing $.fn.
  • Use functional inheritance. Use this and you will be get private/public members. This is important if you would like to have a clean API. I am talking about the functional inheritance from 'javascript: the good parts' book. See example of what i mean here.
  • Break things up into responsibilties. Let each method inside your plugin handle one thing. Do we need to recalucate something on window resize? Do we need to reload some event handlers after AJAX calls? Dont make one giant 'reload' method when you can have more specific methods that will save time.
  • Time and profile. I wish i had started doing this earlier. Use firebug's timing and profiling to see which portions of your code are slow, and optimize them.
  • Unit test. QUnit is jQuery's testrunner. Use it.
  • Test on a Pentium 3, in IE 6. This is my golden standard. If its fast here, you have nothing to worry about.

4 comments:

  1. nice post, but I do find the point about closures slightly contentious. Closures are awesome, but if it's performance you're after in all browsers, should probably be avoided like the plague (Microsoft advise not to use them in IE, and most profiling demonstrates them as inferior to using a regular object). But they do keep your code tidy

    ReplyDelete
  2. i was not aware of this performance problem, thanks for pointing it out to me. on the other hand, I've written several very fast (in ie 6) plugins using closures, and jQuery uses them, a lot. i haven't seen any problems with them. At least, i think its a good trade off between whatever performance you lose and the clean API that you gain.

    ReplyDelete
  3. Jquery itself is slow. It's selector engine that tries to do too many tricks, forgetting it's in a browser. And animation, oh boy. I'm anxious to see Flash get murdered as HTML 5, etc take foot but Very Versatile Electronic Document VVED is much better. It has out of the box functionality that requires dozens of jquery "plugins" and it even uses sizzle and peppy selector enignes. It's been developed from the ground up to take into account the abnormal stress modern day web sites or apps are imposing on the cpu.

    ReplyDelete
  4. except that vved has no documentation, and support for it is non-existent. Fix those 2 problems, and ill check it out

    ReplyDelete