90% Good parts of jQuery - at only 13% of the size
github.com
github.com
While porting 6 jQuery plugins over, I encountered various differences in the APIs and it was a bit of a headache to sort through them (especially the very subtle differences), but it was worth it.I'm writing a blog post currently on my porting experience, as I imagine others might take on the task and encounter similar issues.
For people comparing Zepto to this offering, keep in mind that Zepto also offers mobile-specific events, so if your reason for porting is mobile latency, Zepto's a good bet.
Wouldn't it be more cost effective (rather than convert/port a whole site to a new js lib) to rewrite your page init JavaScript so it does not require a js lib at all (0ms)? Jquery would be async loaded by the time the user executes actions/buttons; if it had not loaded yet you wait, or show a loading icon, etc.
This porting/optimization adds no value to your users 6 months from now who are running a quad core nexus-razr-droid's browser that loads jquery in 300ms.
I use jQuery because it makes Javascript usage sane. Without it I would hate my job.
Unless you want to be compatible with WP7's IE9/IE10 or mobile Opera browsers of course, since Zepto is webkit only (for a phonegap app it probably does not matter).
Edit: Sorry, I misread that you're talking about parsing time. LabJS helps only with the loading time. Does it really take so long to parse? That's not negligible.
It was at risk of ending up like PHP (in more ways than one). the core team recognizes that the API needs a trim. I also no longer use jQuery and haven't in a while because of the bloat.
but I think the way they are approaching it is wrong. They want to trim the API by 10% for the next -1.8- (edit: 1.7) release. This would break semantic versioning[2].
I think they should fork the code now with a new 'jQuery 2' branch and not break any backwards compatibility in the 1.x branch. The 2.x branch should be a complete re-org with browser support as modules (for eg. if you want to support IE 6.0 you enable a module, etc.)
For now, the jQuery light branch should be optional in 1.x. There are analogies in this approach with what PHP did between 4 and 5, and what Python did between 2 and 3. jQuery shouldn't be stripping out API functions in point releases, but it definitely, definitely needs a trim (and I would rather this work is done on the mainline jQuery project rather than in forks. I think a lot of devs at the moment have forks of Zepto/jQuery they run (i do)).
this project may be the perfect starting point for a jQuery2 branch. i'd definitely be interested in working on that project, and bringing in features from all the various forks and cleaning it up.
[1] http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/
Edit: the deprecated API functions are planned for v1.7, not v1.8 - which means soon. I think it will cause a mess for people who auto-upgrade.
$("#foo").live("click", function(){ });
is equivalent to $(document).delegate( "#foo", "click", function() { });Actually, use the new `#on` as replacement: it can handle the job of `#bind` and `#delegate` (and `#live` of course), so I'd fully expect it to be the only one remaining in the fullness of time.
Warning: the first two arguments are reversed compared to `#delegate`:
$(document).delegate("#foo", "click", function() { });
becomes $(document).on("click", "#foo", function() { });Unfortunately, the "limitations" sections reads fairly cryptically. I'm probably just a little slow today. Can anyone explain what's actually not included? For example are "Valid Examples" examples of what's allowed or not allowed?
I'll dive in to see how much code is required to come along with it. Also note the list to what's in core is not permanent, and can be changed by popular demand :)
I still think a large part of jQuery is bloat that is rarely used.
This is a real deal-breaker for me. One of the absolute best things about jQuery is how it normalizes events, so you don't have to care that, e.g., the source element is event.target in some browsers and event.srcElement in others.
I'm curious where the other breakages are, I've normalized the events where I see that it's needed, e.g. like in the custom `$.key()` function.
I think the better approach is to opt-in to receive the cross-browser normalized event in this way, i.e. via another plugin. There are a lot of cases where it doesn't matter and you don't even use the passed in jQuery event and such the overhead is otherwise not welcome.
http://blog.jquery.com/2011/11/08/building-a-slimmer-jquery/
For example: I discovered that my tiny localStorage library was taking 300ms to load, and that was because I was doing feature detection at parse-time and that feature detection attempted to actually set an item in localStorage. I postponed that, and got the load time down to 20ms.
See: https://code.google.com/speed/page-speed/docs/mobile.html#De...
BTW, their Page Speed thing is now available online: https://developers.google.com/pagespeed/
1) You can't always count on users having cached it from the CDN.
2) If it's included on my own server I can be sure they're getting exactly what I intend and there will be less HTTP requests when I include it with the rest of my JS which will only add ~4kb.
3) I'm a bit of a minimalist when it comes to code - for the web at least.
No, but you can always count the MAJORITY of users will have it cached from the CDN.
http://httparchive.org/trends.php#perGlibs
...and that's across all versions of all libraries.
Quite how that correlates with how many of your first-time visitors will already have the library cached – because they happen to have recently visited another site that uses the same version of the same library – depends on how much your visitor demographic intersects with those sites that use the CDN. You then need to offset that against the DNS lookup time requires for the rest of your visitors to work out whether loading the file from Google's CDN makes sense.
If you're talking about repeat visitors, it doesn't matter where the file was served from, so long as you apply the correct cache-controlling headers.
Besides, even when they don't have it, Google's CDN is better than a hit on your servers, both for your IO load, parallelism, delivery speed, etc.
Components don't seem to stay in cache for very long these days because browser caches are max only 50MB (phones are much smaller) and with a bit of surfing it's easy to get to a position where components get ejected.
Also there is no guarantee that retrieving it from Google's CDN is faster than retrieving it from your servers e.g. there's DNS resolution, TCP connections to be setup etc., some of which will already be done for the main site.
http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min...
...and it was used by just 2.7% (945) of the 35,204 pages in the dataset. Note that it's not just version fragmentation - you have to take protocol into account too as browsers cache HTTP and HTTPS separately.
The next most popular was:
http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min...
...used by 1.3% (460) of pages, followed by:
http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min...
...used by 0.8% (285) of pages.
At this point there really isn't much of a debate; unless you have evidence to the contrary (e.g. all our visitors come from Facebook, and Facebook use the same version of jQuery as we do) using Google's CDN to load jQuery isn't likely to benefit the majority of your first-time visitors.
http://statichtml.com/2011/google-ajax-libraries-caching.htm...
That is the point I was trying to make.
That way you could use Google's jQuery file without being vulnerable to them messing with the file contents.
[1] http://www.imperialviolet.org/2011/05/04/pinning.html
[2] http://src.chromium.org/viewvc/chrome/trunk/src/net/base/tra...
Of course I'm assuming you're using common best practices with cache-control/expires headers.
I hope this library gains some traction, as I'd love to see a JQuery clone that could be modified to pass in targets as named parameters instead of the over-reliance of 'this'.
Every tech seems to have an annoying something. PHP it's the order of arguments in stdlib functions, in Rails it's indirect code ruining your day, in JQuery it's 'what does this refer to again in this context?', and 'var that = this', ugh!
I think two features that have almost ruined the language is the Function.apply and the new keyword.
Function.apply is to JS as Metaprogramming and indirection is to Ruby. Features don't have a priority of use, and programmers reach for the most interesting one (and go to town misusing them).
If there was no new and no Function.apply, JS would be more coherent and remain exactly as useful. It means that when an event is triggered or whatnot, rather than changing the meaning of 'this', it passes the target in as a named variable to the anon-function. Which is way better!
If you constantly have to look up 'what is this set to in this callback' you're so completely doing it wrong!
As far as events go, having `this` set to the element receiving the event is, IMO, entirely logical, and has been a common pattern way before jQuery came into existence. You can always access the target as `event.target` if you'd prefer.
If you have to look up "what is this set to in this callback" constantly, then you just need to learn the API/language.
Says who? Antiquated API design by the W3C (which by the way had no reference implementation) shouldn't be the defining factor in how a language works. 'this' and 'new' were brought over to JS so people who were familiar with Java would 'get it'. JS was designed around different ideas before it was mutilated for the sake of superficial familiarity.
> If you have to look up "what is this set to in this callback" constantly, then you just need to learn the API/language.
I assert that good API design requires you to not have to look up things like this. Things that could be unambiguous. Usage of 'this' introduces ambiguity. Not to mention that in an asynchronous programming environment, if you're doing anything non-trivial and you're not copy-pasting $.ajax() code snippets, you want to have named references to things so that closures written inside the scope have access to whatever interesting thing you're working with.
var that = this is a huge indicator that API design is wrong, that this is an abomination and that people generally aren't thinking critically about the code they're writing.
The standards body for JavaScript is Ecma International -- hence JavaScript being officially known and standardized as "ECMAScript".
Additionally, JavaScript began at Netscape in 1995 two years before it was a published standard.
See Wikipedia:
The alternative closure-based OO style also works fine most of the time but it has some limitations, such as not being able to define protected properties that can be accessed in a subclass.
Of course, "this" breaking inside inner helper functions and event handlers (and having to use "var that" or Function.prototype.bind) is annoying as hell but is more of a syntax issue (fixed by things like CoffeeScript and the proposed #() lambda syntax for ES6)
jQuery 1.7.0 gzipped is 33K.
I'm performance obsessed since if our biz serves an additional 2K on our widgets it's an extra 1.86TB of transfer/month.
However for most on-site content, 33K is the size of a large image. Most delay loading a web page is caused by latency. Latency in the three way handshake to establish TCP connections and latency for each additional HTTP request even with keepalive enabled. Payload is not as big an issue because it needs fast throughput, not fast round-trip times which are impossible to achieve if you're far away from the server.
Smaller and faster are always good and always worth striving for (in coding). So I don't want to take away from this, especially since it means more eyes on jQuery. I think it's great work. But keep in mind that the speed increase is not going to be enormous and the cost is running a non-standard jQuery that lacks .css(), .ajax() and $(function()).
$(function()) isn't included because it's generally bad practice over having javascript run immediately at the bottom before the </body> tag.
If you're site doesn't use $.ajax() why include it? many sites don't use ajax.
$.css() isn't included by default because it's implementation is huge. I prefer to addClass/removeClass (which only causes 1 reflow) or set element styles directly.
Really? I'm not a Javascript expert but I play one on TV and I always thought $(function()) was the standard way of bootstrapping everything safely.
Is the new standard really just Javascript blocks at the bottom? Would love to read more on the pros and cons, got any links?
>>The short story is that we don't want to wait for DOMContentReady (or worse the load event) since it leads to bad user experience. The UI is not responsive until all the DOM has been loaded from the network. So the preferred way is to use inline scripts as soon as possible.
>>By intentionally leaving out DOMContentReady wrappers we have been able to prevent Google Apps to use on this anti pattern. -- https://groups.google.com/forum/#!topic/closure-library-disc...
Also see:
http://encosia.com/dont-let-jquerys-document-ready-slow-you-...
http://stackoverflow.com/questions/6026645/document-readyfun...
I was looking through Mozilla Developer network. There is no documented DOMContentReady event. There is a DOMContentLoaded [1] event which is target at the document object. There is also a load [2] event fired at the window object. This is fired when the document is completely loaded.
jQuery.ready will use DOMContentLoaded and load as a backup. [3]
It is common for jQuery developers to shove their whole code base into the ready callback, which I imagine would slow a page down.
[1] https://developer.mozilla.org/en/Gecko-Specific_DOM_Events
[2] https://developer.mozilla.org/en/DOM/window.onload
[3] https://github.com/jquery/jquery/blob/master/src/core.js
require(['jQuery.ajax', 'jQuery.events'], function() {
// code using ajax and events here
});
Much easier than to manage script tags.(hint: CommonJS / AMD)
i would also like to see jQuery versions for different browsers (kinda like Zepto for Webkit but with 100% of the APIs) - so I could compile using closure against different libraries and serve just the right stuff to different user agents.
it shouldn't be hard to add user-agent specific comments to jQuery so the library could be used to produce user-agent specific versions. i think the relative popularity of zepto shows that there's a need for that.
90% good parts of jQuery? I don't think so. The omissions, like .css, abstracted events, etc make this unfit for the majority of jQuery using projects out there.
So it's more like "90% of what the author wants, YMMV" that "90% period".