Recently, I tweeted:
Going to start inlining Zepto into all my bookmarklet and widget Javascript. All the benefits of jquery without the big download.
— gerard sychay (@hellogerard) September 29, 2012
which prompted:
@hellogerard share a sample, please.
— Richard Bronosky (@RichardBronosky) October 12, 2012
Unfortunately, the code I was referring to was client code, but how about a blog post?
The Widget Problem
For whatever reason, I have been writing lots of Javascript widgets and bookmarklets. This type of 3rd-party code is usually copied and pasted into a website or initiated via a boorkmark (both work in similar fashion). The tricky party about widgets is that the code must be lean and fast, and must be robust to hostile environments. By hostile environments, I mean that you can’t make any assumptions about a particular website these days. If you’ve ever tried to scrape arbitrary webpages, you know what I’m talking about.
The problem with jQuery is that sometimes it is neither lean nor fast, and you can’t assume that the website hosting your widget has jQuery already, or has a particular version of jQuery. But we need jQuery. We need its selectors, and Ajax helpers, and CSS helpers. The solution is to load our own jQuery.
I Got Mine (jQuery)
Start with the typical function expression module that isolates your code from any other Javascript.
(function(document, undefined) { // ... your isolated code })(document); |
Load jQuery asynchronously, and prepare a callback that runs when jQuery is loaded.
(function(document, undefined) { // Load our own jQuery s = document.createElement('script'); s.src='//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js'; s.onload = function() { // ... }); d.getElementsByTagName('head')[0].appendChild(s); })(document); |
When jQuery loads, it will assign itself to the $ variable, overwriting whatever was using it beforehand, such as the host site’s copy of jQuery. Fortunately, jQuery keeps a copy of the original value, and running jQuery.noConflict() restores the original value of $ and returns the latest value. Run $.noConflict()
to get our own, local copy of jQuery in the $ variable.
(function(document, undefined) { // Load our own jQuery s = document.createElement('script'); s.src='//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js'; s.onload = function() { var $ = jQuery.noConflict(); // ... $ now safe to use }); d.getElementsByTagName('head')[0].appendChild(s); })(document); |
Can We Do Better?
This works well. However, if the thought of a whole network request (even if cached) just to run your widget bothers you, there’s a surprisingly simple alternative: inline jQuery. That is, copy and paste the entire jQuery library into your widget code. This may seem unusual, but despite it’s size, it’s still cheaper than a network request.
(function(document, undefined) { // Load our own jQuery /*! jQuery v@1.8.1 jquery.com | jquery.org/license */ (function(a,b){function G(a){var b=F[a]={};return ... var $ = jQuery.noConflict(); // ... $ now safe to use })(document); |
Can We (Still) Do Better?
If inlining all 91k (as of 1.8.2) of jQuery also bothers you: consider Zepto (23k for 1.0RC1). Zepto is billed as “a minimalist JavaScript library for modern browsers with a largely jQuery-compatible API.”
(function(document, undefined) { // Load our own Zepto /* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */ (function(a){String.prototype.trim===a&&(String.prototype ... var $ = window.Zepto; // ... $ now safe to use })(document); |
Zepto, unlike jQuery, will not assign itself to $ if it is already defined, so no issue there.
Now, don’t make the mistake I did in thinking Zepto is a drop-in replacement as a “lightweight” jQuery because it certainly is not, especially in CSS manipulations. Support for CSS effects in IE is sketchy, and its Ajax helpers are a bit different. However, Zepto gives you all the selectors and DOM manipulators you’re used to, has all the Ajax helpers you need, and offers useful utilities such as $.proxy().
So if you need visual effects in your widget, Zepto will probably not do. But if all you need is the ability to add/remove/select elements, then Zepto works great as a jQuery replacement.
2 Comments to 'So You Want To Use jQuery In Your Javascript Widget?'
April 18, 2013
I think the situation will change quite a bit with the introduction of jQuery 2.0. It drops support for older IE (probably a non-issue for you) and has been designed to be modular. Minimal build appears to be around 10k so that’s not bad at all. Of course you may need to include some optional modules but still that’s a nice step forward.
Given jQuery is used a lot these days using a CDN is likely a very viable option these days thanks to caching. That sort of mitigates the size issue I think.
My experience with Zepto is a bit varied. If you need some more complex stuff, you’ll still end up extending it by setting up plugins ie. I am not entirely happy about the fact that the library isn’t AMD compatible out of the box (the author seems to have something against AMD).
I would bet on jQuery, especially given the recent improvements.
Do you have your widgets and bookmarklets available somewhere? It would be very interesting to have a look. I didn’t notice anything at GitHub although I didn’t look very hard.
March 1, 2022
[…] Beyond the tips to minify/compress/CDN-host your Javascript, which you should do for any Javascript library, have a look at Zepto, which aims to be a slimmer jQuery-alternative designed for the mobile browser. It’s not a drop-in replacement for jQuery, but supports all the important things like selectors, AJAX operations, and utilities. I wrote a brief blog post on the subject: http://blog.straylightrun.net/2012/10/23/so-you-want-to-use-jquery-in-your-javascriptwidget/ […]