Show HN: Minified.js – a fully-featured, 4K alternative to jQuery and MooTools
minifiedjs.com
minifiedjs.com
Look at this video at 6m30s: http://channel9.msdn.com/Events/Build/2012/3-132
Productively optimizing a web page is no different than optimizing any other code. If you want to know why a web site is slow, profile it or run it through a tool like webpagetest.org. Don't just set off to rewrite all your loops to run backwards, or eliminate function calls, or reduce the amount of this or that without any understanding of the result.
People who say "hey, what's an extra 30KB for one library? It's only like 10x larger" will tend to reach a similar conclusion at every decision point. And that's why the internet is full of massive, bloated, slow web pages. Single decisions don't cause bloat. Bloat comes from a slack attitude towards efficiency.
I'm not saying this project is an important breakthrough, but I definitely applaud the effort. I've always been surprised at the large size of jquery. I'd love to see a benchmark for runtime performance, including a comparison of parsing time and a benchmark of common operations.
That sounds dangerously like premature optimization. For example, why spend the time creating optimized image sprites if it turns out they don't contribute significantly to load time? It's better to spend development time doing something else.
> And that's why the internet is full of massive, bloated, slow web pages. Single decisions don't cause bloat. Bloat comes from a slack attitude towards efficiency.
By using the word "bloat" it sounds like you're talking about bytes. Again, byte counts often aren't always the main culprit in slow loading of web pages. Synchronous scripts and/or 302 redirects can be much worse, for example. Don't start with the premise that the bytes are the problem and do a lot of work to reduce them, only to find out it isn't the problem. Profile the page load and see what is really the problem. Then fix that.
I would be willing to bet that among just the top 1,000 sites, a user would be required to have 25 to 30 copies of jQuery cached to cover all the sites.
(No idea about more current versions of iOS or browser-caching on other mobiles OSs.)
What does that video possibly prove? That if you compare completely different sites, you can't use reductionist measures of individual attributes to compare speed? Is there anyone on HN who actually doesn't already know that? This is asking which of a collection of mystery vehicles is the fastest by engine size, and then revealing that one is a dump truck, one a train, and the other a motorcycle, with results that should surprise no one.
The only people who would possibly be interested in this project are people who are attempting to optimize the experience their app provides, presumably in a holistic fashion. It is pretty much part and parcel that such a person is going to minimize elements, CSS, images, and scripts in such a case, and aren't simply going to replace jQuery with something like this and assumes that it will make everything fast.
The reality of something like jQuery, like Ruby on Rails or MongoDB, is if you start with it you'll likely be stuck with it. You can't simply make a full site and run it through the profiler and swap out components without significant rewriting.
I see a lot of discussion here based on the premise that this smaller script will make a big difference in overall page load time. It's why the audience in that video was leaning towards the site with the most JavaScript being the slowest. The first benefit listed on the minified.js page is "Minified is smaller!" so exactly what benefits does "smaller" imply?
> The only people who would possibly be interested in this project are people who are attempting to optimize the experience their app provides, presumably in a holistic fashion.
I agree, and creating your own homebrew framework for a large project in a holistic fashion has its own pitfalls. Especially if you've never done it before.
Even in the US there's something like 10% of people with no cell phone at all, and 50% with "smartphones" which is a very broad spectrum ranging from crap to significant household purchases before considering "data plans" are optional and also range from crap to good.
Even non-phone connection quality can be terrible - I rarely find myself on public or hotel wifi with actually good connections. The difference between 200kb of JavaScript and 10kb can often be measured in seconds.
:)
The web is often death by a thousand cuts. Every decision by itself may seem small, but the end result is an unenjoyable, inefficient, battery-sucking result that leads people to abandon the web.
After a few hours of working without jQuery, it became obvious that the standard DOM & selection APIs are verbose and a little awkward. In about 20 minutes I produced a little wrapper that was compatible with a small - but common - chunk of jQuery's surface, and it made life so much more bearable. It clocked in at about 1kb minified (no GZIP).
Obviously it wasn't battle hardened and didn't deal with cross browser issues, as it was just for hacking with - but it felt like proof that a wrapper of some form, if not jQuery, is pretty much always necessary
Writing a bit of "raw" code can really make you understand why jQuery may do things in a certain way or why they have chosen certain abstractions.
Releasing thing into the public domain is not as easy as writing
"Minified has been released into the Public Domain. You can use, copy, distribute and modify Minified without any copyright restrictions. You may even release it under your name and call it yours, if that's your thing."
As the CC0 page explains [1]:
> a waiver may not be effective in most jurisdictions
> Dedicating works to the public domain is difficult if not impossible for those wanting to contribute their works for public use before applicable copyright or database protection terms expire. Few if any jurisdictions have a process for doing so easily and reliably.
Please use a proper PD waiver tool such as CC0.
If you do it right you don't even have the client send/receive an HTTP 304. For our app we have a lot of modular dependencies but we serve all of them from a unique prefix per build (eg. 'assets-SHA(build)/js/foo.js'). The second page load and beyond has zero requests for the same static asset. Whenever we have a new build of the app the unique prefix gets auto updated to force clients to use the latest versions.
For HTTPS make sure to mark your assets as public or they won't be cached:
Cache-Control:max-age=31557600, public
[1]: http://www.semicomplete.com/blog/geekery/ssl-latency.htmlNow that jQuery 2.x drops IE 8- support, a credible question is whether such libraries (which are more in the 95KB range, minified) are even necessary at all.
Quite outside of the time to download, there is a measurable cost to parse all of that boilerplate code as well. This has more of an impact on mobile, obviously.
Well my answer to the credible question is that jQuery has to normalize and fix bugs for just about all the browsers it supports, it's not just an oldIE problem. Plus, jQuery provides abstractions above the basic DOM operations which are pretty low level. So if you don't want to use jQuery you'd probably want some other library to provide equal or greater abstraction.
> Quite outside of the time to download, there is a measurable cost to parse all of that boilerplate code as well. This has more of an impact on mobile, obviously.
Measurable of course. Significant as a portion of the page load time for most pages? Well that's a different thing. And of course if you want it, jQuery 1.8+ provides the ability to create custom builds if you know you don't need parts of it.
As to the cost, assuming that everyone is pulling it from the same CDN (and there aren't the often considerable times simply to check an etag, which is the case with the overwhelming majority of jQuery hosts), an iPhone 4S takes about 80-100ms to simply parse the jQuery file (and given the plateauing of the integer core on on the An chips since, it is a reasonable assumption that every Apple variant since is similar). On each and every page render. A tenth of a second is a long time (and a lot of battery) for what is often of minimal value.
http://jsperf.com/test-jquery-vs-minified
And to the community at large, feel free to add more tests.
The more experienced I become as a programmer, the more respect I have for minimal programs that work very well. It's often very hard to "work your way up to simplicity," as my father likes to call it. (He's an EE.)
(disclaimer: I'm one of the authors)
(And I do curse Microsoft for making IE 9 Vista+ only browser, which is quite likely explainable by use of some shiny new undocumented API, that wasn't available in XP and before. Microsoft and their browser tightly coupled with OS...)
Firefox, Chrome and Opera are available for Windows XP :)
I seriously doubt the reasons Microsoft gave for not supporting it are valid. Even if the sandbox mode could not be used there is no reason why the browser and rendering engine could not run on XP if the proper system DLLs were present, and these could have easily been included with the install as Microsoft does in many other cases.
Here's a quick sampling from a random group of top sites:
stackoverflow.com (googleapis.com), kickstarter.com (googleapis.com), cnn.com (their own cdn), businessinsider.com (jquery.com), foxnews.com (their own cdn), nbcnews.com (aspnetcdn.com), espn.com (espncdn.com), tumblr.com (secure.assets.tumblr.com), lastfm.com (googleapis.com), lyricsmode.com (googleapis.com), reference.com (sfdict.com, cdn for ask etc), qz.com (googleapis.com), theverge.com (googleapis.com), ehow.com (googleapis.com), wikia.com (googleapis.com), chacha.com (googleapis.com)
No idea if it's all linked up, but it means that using alternative search engines doesn't really matter if you still visit Google-enhanced destinations.
Use of these (to serve static content) reduces your server traffic/load and gives a faster response times to users in different geographical regions.
Doesnt seem like a really big argument against, especially considering the size of the library for the first non-cache hit
I have vague memories of reading a post with a stronger conclusion — that CDN caching was basically a non-issue, it would so rarely work — but to my frustration I can't find that right now.
* an IP,
* a referrer from the first page on your site that included the script (no subsequent pages, because now the client has jQuery cached).
All in all, a pretty poor source of information compared to AdWords, Google Analytics, G+, hundreds of millions of Android users, and running the world's most popular search engine. At most they could crunch some browser stats or jQuery usage stats, but they already get that and more from their own services + crawling the web.
And even if this tiny amount of info were somehow a boon to Google, so what? It doesn't hurt you as a site owner.
tl;dr for lazy HN readers: "using Google's CDN to load jQuery isn't likely to benefit the majority of your first-time visitors." As of 2011, jQuery 1.4.2 was by far the most common version and even that was only loaded via googleapis.com on 2.7% of websites.
Note the difference in version Steve found vs my comment (due to query strings etc., which will of course destroy caching)
It seems like that would cover most things I would use, however surely there is more to jquery (that I may or may not be using..)
I like that they are including IE6-8, that was a bummer when zepto came out aimed at mobile/modern only
Actually one of the ways I used to decide what features to squeeze in was making a list of all jQuery functions and re-implementing the functionality with Minified. To make sure that I don't miss anything important.
There are some things that are more complicated to do, because you need to work with anonymous functions, but honestly most of them were functions that I had never heard of before and would probably have re-implemented even when using jQuery :)
I'm not sure if Minified.js qualifies for that, but if it does you should definitely make a bigger point of that ;)
Also, if you don't support each, I assume you don't support method chaining on enumerables?
As for actual missing features, the jQuery data stuff is really useful, but if the intention is to use minified with something like backbone, I guess it's kinda moot.
EDIT: I forgot to say nice library and I like the source code too.
You can chain list methods, as in $('li').filter(function(v, index) { return index%2;}).set({$backgroundColor: '#000'}).animate({$backgroundColor: '#fff'}) to fade every second list element from black to white. The number of collection functions is limited to a minimum though. The Util module will add a lot more collection features (but at a cost of another 4kb).
Yes, that's true, data() is something I intentionally omitted because I don't think that it's worth its bytes today. For simple lower level effects toggle() offers a very different approach of handling state, and for larger apps you should use a MVC framework, as you suggested.
Like "jquery gives you all of this, do you really use all of it?"
I suppose it's a bad sign when we are using jquery blindly and not really knowing what all that includes..
While 4kB may fit well in certain packet sizes, this does not help with HTTP headers that can easily have 100 bytes or more.
Yes, it is.
1) For poorer countries with spotty internet, or mobile only that is slow.
2) For mobile, where data use matters.
3) Ideally with a library this small, it's mostly doing exactly what you need it to and nothing else. So it should be faster for what you're using it for. It's not trying to be all things to all people, and the trade off for that should be giving up long-tail features in exchange for more speed.
Also, if you want to optimize for file-size, you won't get very good results with a collection of micro-libraries. A compiler like Closure is capable of inlining functions and removing unused code only as long as you have all of it in a single file as private functions. But when every library exports all its features, Closure is not able to optimize them properly anymore.
But yes, your point is valid. Also, jquery is so ubiquitous that I see no reason to steer clear of it. If you use a CDN version of it, it's most probably already in client's cache.
(No, I don't have data on mine, I don't even work in this field.)
http://w3techs.com/blog/entry/jquery_now_runs_on_every_secon...
Of the top 10k sites 58.8% use jQuery. That's good!
But only 26.6% use a cdn. Leaving only 15.6%. That's bad...
But 94.2% use Google's. Which is still 14.7%! That's good!
http://www.stevesouders.com/blog/2013/03/18/http-archive-jqu...
But only 1% use the newest version of jQuery. Leaving only 0.15%. That's bad...
http://www.quora.com/User-Behavior/How-many-websites-does-an...
But users visit on average 89 sites per month. Which gives us 12.5%. That's good!
http://stevesouders.com/cache.php
But default browser cache sizes are small. That's bad...
http://www.webperformancetoday.com/2013/06/05/web-page-growt...
But the average website is about 1MB so with a 50MB cache about 50 sites can be cached. Which leaves about 7.2%. That's... OK?
OK. So I don't actually know if a cdn cache hit is all that likely, but the situation is a bit worse, and a bit better than most people think.
Of course, using a cdn is still better than hosting yourself. If you bundle your jQuery then every time your site updates it needs to be redownloaded. If you serve it seperately on your domain, you won't have the distribution benefit of a cdn.
Should you use Google's cdn instead of a different commercial cdn provider that's faster? In that case I'm not sure.
The basic gist is that there is great fragmentation in the cache eco-system, and so there is no guarantee that the user actually has the version of jQuery cached that you are requesting. Alex Sexton brought up in a talk at jQueryTO that there are also the time for the DNS request itself to consider in any discussion of speed, if you concatenate/minify your code it will eliminate a DNS request.
Resources discussed in that page: http://statichtml.com/2011/google-ajax-libraries-caching.htm... http://www.stevesouders.com/blog/2011/08/17/http-archive-nin... http://www.stevesouders.com/blog/2013/03/18/http-archive-jqu...
The end conclusion was that for H5BP it didn't make sense to remove the CDN reference, but for your own site it might - you should test it and see. It also depends on your audience (will the CDN move the files closer geographically?).
In the end, ~40k (gzipped) is not going to make or break your website's performance.
It's always better to use a CDN because:
1. It has a chance to be already cached (specially if you use Google's CDN).
2. All browsers nowadays do 6 parallel requests per host. So using DNS prefetching with `rel=dns-prefetch` will be faster.
3. If you bundle jQuery with your site's JS files, every time you change a single JS file of your own, your users will be forced to re-download your bundled jQuery. Seems pretty inefficient to me.
1. Is open to debate and we have no real numbers of this - hopefully the resource timing API will all us to shed some light on the issue
2. Not sure how the number of connections is relevant as the connection to the CDN will be a new one.
3. Agree with this, people need to merge files that naturally fit together an have similar patterns of change
And yes, if you want to use third-party libraries that use jQuery, using Minified does not make any sense. Currently it's mostly interesting if you want complete control over your JS environment and want to optimize for size.
URL: http://zeptojs.com/
Trying it out right now! Nice work Tim.
Is there something similar in Minified?
$("#dataTable tbody").on("click", "tr", function(event){ alert($(this).text()); });
In Minified, the easiest way to get exactly the same event handler is this: $("#dataTable tbody").each(function(tbody) { $('tr', tbody).on("click", function(){ alert($(this).text()); }, tbody);
api.jquery.com/on/#direct-and-delegated-events
> Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready. ... In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored.
The obvious benefit of this is that if there are 10,000 tr elements, it is quicker to attach your listeners (there's only a single listener on the tbody) and less memory is consumed (again, only a single listener). A more subtle set of benefits come from manipulation of the DOM. Your listener is able to respond to events on elements that have been inserted after the listener was first registered. Also, when removing tr elements from the DOM you don't have to remember to unbind all your event handlers (a common source of memory leaks, as they can be GC'd)
To elaborate -- jQuery does not set an event-handler for each TR -- it sets one on the parent element (the table), and basically when the table is clicked jQuery gets the event and asks: "are you a TR?", and if so, then the handler is called with the clicked element as the context. So even if your table has 1million rows, only 1 event handler is attached and the DOM is only accessed once.
Of course, accessing the DOM 1 million times within a loop is going to take forever.
The following CoffeeScript event handler would be fired for every table cell with the foobar class that is a child of #myTable:
$('#myTable').on 'click', 'td.foobar', () ->
# Do something
What's great here is I can add/remove rows to the table without binding/unbinding event handlers. We use this a lot in our app (http://www.jackdb.com/). The main app content is a single page with all content dynamically loaded and added/removed on the fly. If we had to add event handlers for each data cell (or even row) there would be 1000s of them.I also guess that almost all sites the cost of parsing and executing the libraries is more significant than the actual runtime. I mean, there are sites that parse 200kb of ungzipped source code only to execute the 2 kb of them that are required to have some pull-down menus or sliders a couple of times.
tml xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:page="http://tjansen.de/minifiedPage" xmlns:i="http://tjansen.de/internal" xmlns="http://www.w3.org/1999/xhtml">
at the top of the page. Apparently the minification went too far. :)Edit: oh, no, this time it was me unintentionally editing the compiled index.html.
btw anybody would like to use this in their Rails project, just drop https://github.com/tmlee/minifiedjs-rails into your app for asset pipeline. just did a quick one for that.
BTW to get down to the final size of 4089, I compress the source code with Closure Compiler in Advanced Mode, and then compress again using UglifyJS to get rid of the last 20 bytes. Closure is not perfect...
Where Closure shines is building an app whole-world, compiling both the client code, and library code together, then it can prune away all unused methods in the library.
Another example are jQuery's the complex selector/stacked set features, like 'andSelf()' or 'next()'. Minified only has simple lists and a couple of callback-using helper methods like 'collect()' and 'filter()'. If you are doing something complex and know jQuery's API well enough, jQuery is more powerful.
I am sorry, I probably would still go with the 30KB solution.
That's always a dangerous assumption to make. I can guarantee you that size has nothing to do with parsing and running times. As others have already pointed out, this library is already less performant than jQuery for their needs.
{$left: '10px', $top: '10px'}
is equivalent to {'$left': '10px', '$top': '10px'}
The library doesn’t have to define global variables for that code to work. So it probably doesn’t define them as global variables.And it's no alternative to jQuery or Mootools since your lib doesnt support a lot of stuffs these libs provide.
It's true that Minified doesn't support many features in the same breadth as the other libraries. Instead the focus is on making the essentials easy (often easier) and offering you powerful functions to do the rest. Basically that's how I keep both API size and file size down.