359 comments

[ 3.2 ms ] story [ 285 ms ] thread
I understand the desire for people to make pages like this (this isn't the first), but the examples are not completely honest with themselves, in my opinion.

One of the biggest benefits jQuery introduces is the concept of treating single selections and multiple selections identically. While using jQuery, I can emit a $(".class").hide() call, which will apply to all elements with the matching class. Simple and elegant.

However, using native JS as the page suggests, I will need to construct a loop within my function, especially if I'm using the DOM supported getElementsByClassName method, returns a pseudo-array of DOM nodes which don't have the style method available on them. You'll notice the examples already assume a selected element and leave much of this heavy lifting out.

Furthermore, jQuery offers the selection simplicities of Sizzle (ie: "#div .container .item). To do the same selection process in vanilla JS, I'll need to nest 2 getElementsByClassName functions in a getElementByID function, and return the concatenated results from each potential .container. That is to say nothing of more complex selectors.

So yes, if you're addressing the absolute simplest form of selection, this works, but otherwise I don't think it's really presenting the situation honestly.

This is actually a great example of the purpose of the site. Since IE8, browsers have supported a native 'sizzle-style' element querying syntax: http://youmightnotneedjquery.com/#finding_elements

IE9 and later also support a native each. You are correct however that you'd have to use Array.prototype.each.call, because the NodeList is not a real array.

It sounds like you're looking for the querySelector and querySelectorAll methods: https://developer.mozilla.org/en-US/docs/Web/API/Document.qu...
querySelector and querySelectorAll could have been pretty great, but they suffer from some serious problems as they ended up spec'd.

The one I hate most is that qSA returns Yet Another JavaScript Collection That Is A Lot Like An Array But Isn't An Array And Therefore Doesn't Have Any Of The Nice Methods(TM). Yes, you're going to have to iterate over the thing using an index in a loop.

There's others:

http://ejohn.org/blog/thoughts-on-queryselectorall/

I'm really not sure how the standards-makers got this so terribly wrong given that the libraries had already started to solve the problem.

    Array.prototype.slice.call(document.querySelectorAll('.myClass'), 0);
Or if you want to abstract that into a utility function:

    function qsa(sel) {
        return Array.prototype.slice.call(document.querySelectorAll(sel), 0);
    }

    qsa('.myClass'); // Returns array of elements
And now you are on the way to rewriting jQuery from scratch.

Add a few more helper functions, separate it all out to its own js file, reuse the js file in other projects, and soon people will complain about the bloated js file you keep using in your projects.

Man, I really do enjoy my chosen line of work. It creates such fun things to debate over.

You're certainly right. Did you see that the page specifically targets people who make javascript libraries? The page is arguing that when possible, libraries shouldn't depend on jquery, and shows how to do that for a few common idioms.

Since a library is written once and used in many different places, it's worth going to a little more effort to make it more flexible.

That sounds more like an argument for picking a canonical version of jQuery that can be cached aggressively, rather than everybody shipping a probably-buggy re-implementation of the 25% of jQuery they need.
(comment deleted)
"You might not need jquery"
> However, using native JS as the page suggests, I will need to construct a loop within my function, especially if I'm using the DOM supported getElementsByClassName method, returns a pseudo-array of DOM nodes which don't have the style method available on them. You'll notice the examples already assume a selected element and leave much of this heavy lifting out.

You don't really need jQuery for that, though. You just need a forEach-like function that works with NodeLists. This is easily implemented in three lines of JavaScript.

> Furthermore, jQuery offers the selection simplicities of Sizzle (ie: "#div .container .item). To do the same selection process in vanilla JS, I'll need to nest 2 getElementsByClassName functions in a getElementByID function, and return the concatenated results from each potential .container. That is to say nothing of more complex selectors.

Not since IE8. These days, you can just do document.querySelectorAll('#div .container .item'). For most common selectors like the one you showed, Sizzle ends up delegating to this method anyway. You only need Sizzle for selectors that cannot be expressed in CSS (e.g. "select a UL with only one child", which would require the CSS4 ! marker).

In practice a better approach would be to build up a micro-library of functions to just implement the small subset of features you do need.

  // Using underscore/lo-dash and ES6.
  _.forEach(document.querySelectorAll('.class'), elem => elem.hidden = true);

  // Building reusable utility functions
  function forEachSelector(sel, cb) { _.forEach(document.querySelectorAll(sel), cb); }
  function hideElement(el) { el.hidden = true; }
  forEachSelector('.class', hideElement);
Of course, there is the danger of ending up with homegrown jQuery that is less well tested and less well thought out. Perhaps there is a place for a small JS library that works with native DOM elements, in the same non-invasive way lo-dash and underscore work with data structures.

The problem with jQuery is that it's an all-or-nothing approach. The way it wraps native DOM nodes means it keeps trying to pull you back to using its inbuilt utility methods.

> The problem with jQuery is that it's an all-or-nothing approach. The way it wraps native DOM nodes means it keeps trying to pull you back to using its inbuilt utility methods.

Not true at all. You can do a custom build and leave out things you don't need. You can even leave out stuff you DO need and replace with your own simpler shim. See the README file.

Sure, it's technically possible. But not common from the projects I've seen.

The APIs seem to be designed with the assumption that all your code will be using jQuery. For example converting a wrapped node to a native DOM node requires an extra call that, in my opinion, is ugly: $('.something').get(0); and could be considered to be an anti-pattern.

I don't think this is a bad thing. jQuery does a good job at providing a DSL that replaces native DOM access. But if you want a library instead of a framework its strongly opinionated style can be off-putting.

> The APIs seem to be designed with the assumption that all your code will be using jQuery.

Again, not true. For example, the `this` in an event handler is the actual DOM element, not a jQuery object. Whether you handle that directly with DOM methods or wrap it with `$(this)` is up to you. Many people prefer the latter but the former is often smaller and prettier.

> For example converting a wrapped node to a native DOM node requires an extra call that, in my opinion, is ugly: $('.something').get(0); and could be considered to be an anti-pattern.

How common is that, really? Your example assumes a single element with that class name. Why not chain a jQuery method behind it and handle the 0 or N cases as well?

Or even better, if you're only selecting one DOM element that doesn't need the jQuery wrapper, then don't use jQuery for that one case. There's nothing that prevents doing that even if jQuery is being used for other elements in the project.

Just because jQuery is loaded doesn't mean you have to use it for everything on the page.

You can count on one hand the number of jQuery features that most developers incorporate into their projects. E.g.:

- Setting or getting css attributes - Querying the DOM - Manipulating and walking through arrays

Each of these features can be replicated with fewer than 10 lines of code.

Chaining and implicit iterators.
Since I've started using an MVC, I use chaining less and less. I tend to just use a variable the few times I need to do a bunch of manipulation to the same element. Beyond that, any chain using .end is nuts to me.
There are many things you don't need to do. I'll take the time saved in development over cutting out an extra framework.
Like it says at the top of that page:

> jQuery and its cousins are great, and by all means use them if it makes it easier to develop your application.

Yeah, I don't have to wear shoes outside, but the alternative is very destroyed and useless feet. Maintaining my boots is far less work than curing my hurt feet.
> in truth, post-IE8, browsers are pretty easy to deal with on their own

I totally agree, but not everyone lives in a post-IE8 world. It's as much as 10% of our traffic on some sites and several big clients use it.

That's why it's called You_Might_NotNeedJQuery. ;)
Would be great if we could all stop recapitulating this, it's not helping
If you are developing a library, then your users _Might_ need to support old browsers and _Might_ need jQuery.
lots of js libs are for things like webgl that already dictate a recent browser.
and I care about wether my site works on Safari or Android 2.3 browsers. Will you fix all the "wont fix" DOM bugs for me?
It's hard to tell if this site is advocating for ditching this type of js library altogether and writing all those replacements inline (ick for some of those) or simply replacing jQuery with a thinner (and narrower) library.

I could be convinced of the latter but not the former.

I think that what it's saying is that you can write yourself a microlibrary that just includes the ten or fifteen lines of adapter code you actually need for the thing you're building, and that you should use native browser constructs whenever possible.
One of the main things we're advocating is to consider not depending on jQuery when building an open-source project.

For Offline, PACE, Odometer, Tether, and many of our other OS projects (http://github.hubspot.com), we chose not to depend on jQuery because it means our libraries can be smaller and more people can use them.

We're happy and proud to use jQuery when building an application. As many other commenters have noticed, it can be extremely useful at reducing code complexity—and let's just say it: it can make it more enjoyable to write front-end code!

What's a good resource to read up on how browsers handle unsupported JS, if I want to write a fall-back?

I've already got fall-back for people who've turned off JS, but I've yet to write anything for unsupported JS.

This might be overkill for you, but take a look at http://modernizr.com/

Sometimes it's just as simple as testing if the function your about to call exists before you call it.

What?

> $('<div>').append($(el).clone()).html()

vs

> el.outerHTML

Why not $(el)[0].outerHTML?

What if $(el).length === 0?
This check is required in both cases. el.outerHTML assumes that el is not NULL (which it could be as a result of getElementById, for example).
You had me convinced until I scrolled down to read the code examples and realized why I actually do need jQuery. If its between adding yet another collection of utility functions to approximate the functionality jQuery would give me vs just adding jQuery. I'd rather go with jQuery.
One way of looking at it is that if you already have underscore to give you _.extend and the like, you can get pretty far with just what the browser gives you.
The first example alone is reason enough to use jQuery - why would I want to use four statements instead one? Why would I want to have to remember to call `send`? Why do I have to remember the last boolean parameter of `open`?
Totally valid, but just to say, jQuery's API is just as arbitrary, you just happen to know it better. If you use the native XHR a couple times, you know what open's parameters are.
It is just as arbitrary, but I feel jQuery's API is also easier to grok at a glance. Using either a couple times may instill the parameters in your memory, but what about coming back to it after six months?
If you are writing a library, eliminating a dependency is worth much more then 4 lines of code.

But yeah, if you are just writing code for your own site then knock yourself out.

Which javascript library are you developing?
I had exactly such a collection of DOM utility functions and was glad to give it up. For example, rooting around in element.className was never very enjoyable. Also, the site does not show handling null cases which adds more code.
You have element.classList on all modern browsers now:

http://caniuse.com/#search=classList

It used to be that the first thing I'd reach for when building a prototype was JQuery off a CDN, but now I find that more and more of what I use JQuery for is built into the browser, and in my last few prototypes I've just stopped including it at all because I don't need it.

Did anyone ever take you up on your hackathon idea? https://news.ycombinator.com/item?id=6645426
Nope, I didn't hear anything further on it. Still seems like an interesting event to me, though finding time might be hard. (FWIW, we do similar things within my employer all the time.)
That's too bad. But as with all things it takes time and organization in addition to some willing victims.

"Similar things" as in hackathons for fun, or hackathons structured to test out different approaches and tech?

Hackathons (really, prototypes) structured to test out different approaches.
Except Android 2.3 and below.

Compatibility issues still exist.

I think the question is, does your library need every function on that page? If so, just use jQuery. But do you just need one thing? Then maybe it's better to just make the one utility function rather than pull in all of jQuery.
In my opinion jquery is a hell. Because jquery is only abstraction for browser features level (events, styles, dom), but it's ugly for writen complete code, for this need some like prototype.js or mootools, because it's have oop-style level for browser.
"You might not need Ruby on Rails. Use C to rewrite tons of shit you need."

Use jQuery please.

Rewriting jQuery methods with vanilla js usually turns out to be a hack job that is buggy and ugly. Just use jQuery.

This is exactly what we're trying to combat. For modern browsers, in many cases, it's just not true. There are a few utility methods that are tricky to replace, but you really shouldn't be including jQuery only for it's utility methods.
jQuery provides a uniform API that is guaranteed to work on supported browsers. The jQuery team does all the work to back that guarantee. If I rely on raw JS, then I'm one glitchy browser implementation away from being broken.

Even worse: suppose you build a product with the approach you recommend, it's very successful, and then your sales team makes a major sale to a stodgy old bank that still uses IE7. Or maybe you just never make the sale because you don't support the browser they use.

OK, let's say we should all turn away money from IE7 users because it's insecure and old. For OP's strategy to work, we have to assume all browsers we care about will be compatible going forward. I think this is a very unsafe assumption to make. While one small incompatibility would only be a minor annoyance, once you have more than a handful of these, a compatibility layer like jQuery again looks very nice.

And none of this even speaks to the fact that the jQuery implementation in the source article is generally at least as short and readable as the alternative, or that most people are more familiar with the jQuery version.

The only reason I can think of for dumping jQuery is maybe speed optimization, and even in that case, well-implemented jQuery should be no slower than the native speed plus the cost of a function call. If it's slow and you want to optimize something, why not optimize/bug-fix jQuery itself and help everyone, not just your one project?

That's a really bad analogy.

People don't use Ruby because C's standard library works differently across different platforms.

This isn't about "rewriting jQuery methods with vanilla js". It's about using the built-in, native, vastly more performant methods that come standard on modern browsers.

The analogy is even worse because Ruby changes way faster than C :)

But anyway, writing code in any 'lower' layer is very educational.

I think your analogy is flawed because it seems like you're essentially taking an extreme on the opposite end from what you are sarcastically mocking.

I wouldn't call myself "old school," "hard core" or anything like it, but I just don't see what's so difficult about--or wrong with--replacing any library with "ad hoc" code that accomplishes a small subset of the library's functionality if the majority of the library's purpose is to provide that small subset. "Small", of course, is relative and context dependent.

Rewriting jQuery methods? If you can do it natively, and succinctly, why would you load a library abstraction to begin with?
Awesome site with clear message. +1
So, uh, what will I gain by ditching jQuery?

I will lose a beautiful API with a simple, terse and familiar syntax. I will have to work with an ugly, inconsistent and loquacious API, which has no guarantee of being cross-browser (or accounting for various browser quirks).

And for what? I doubt 81 KB would make much difference to 99.9% of my visitors.

As for performance -- it makes sense to rewrite bottlenecks in pure highly-optimized JS. But to write vanilla JS from scratch, without even knowing whether you'd need that performance boost is a pure waste of time.

UPD: it has been pointed out that this webpage is directed at developers of JS libraries. In this case, all these points are valid, but the title, then, seems to be either misleading (as in "link-bait" misleading) or a plain truism.

You lose dependency on a monolithic library which creates vertically-stacking dependencies and library conflicts. By ditching it, you gain the ability to construct your app out of loosely-bound components supported by independent developers.
Could you elaborate on how jQuery creates vertically-stacking dependencies and library conflicts by itself?
Obviously, you cannot have dependency conflicts if you only have a single dependency! We need a slightly more complicated example to understand the problem. Let's say I'm making the new customer checkout page for my startup.

I decide to call an e-mail address verification as a service API, their library uses jquery 1.8

I decide to call an address verification as a service API, their library uses jquery 1.11

I decide to call a credit card validation as a service API, their library uses jquery 2.0

You go to the e-mail address verification company and say "Do you have a version that supports a newer version of jquery" and they say "yes, also we redesigned our library's interface so if you upgrade you'll have to change all your code..."

My colleagues and I learnt that lesson the hard way. We are working on a WYSIWYG editor (Aloha-Editor) and the first version did depend on jQuery (and jQuery UI for that matter). That caused a lot of trouble for people integrating the editor in their websites, especially if they were already using jQuery. For our particular case we really didn't need it, as it's just as easy to say .getAttribute() instead of .attr(), and we didn't use selectors much, if at all. Effort is underway to get rid of the dependency from the core library in the next major release.
It's odd, but after reading everything and the examples at the end, I feel we need jQuery more than ever. Kind the opposite of the OP is stating. Great post though.
great content, terrible opinion. I like your take on the article.
You might not need jQuery 1.x.

You might be able to use jQuery 2.x instead, which is smaller, faster, and drops support for IE8 and below.

Couple improvements to some of the modern-browser code examples:

FadeIn:

  element.style.transition = 'opacity 400ms ease-in-out';
  element.style.opacity = 1;
Each & filter (this also applies to people's complaints about browser methods not working on collections):

  [].forEach.call(document.querySelectorAll(selector), function(el) { ... })
The native versions also usually run several times faster than the JQuery versions, which is the main reason to use them. This meme that you can't build performant, jank-free HTML5 mobile apps? It's largely because of JS libraries and developers that don't know which operations are fast and which are slow.

I'll also plug my colleague's autogenerated index of the HTML5 APIs:

http://html5index.org/

I've had pretty terrible performance with complicated CSS animations that I managed to clear up with switching to JavaScript and requestAnimationFrame
Are you animating the transform/opacity properties and only those? That's the general secret to smooth animations on web - they're GPU accelerated, everything else requires a call into the browser's layout engine on every frame.
Transitions didn't end up being supported until IE10, which wouldn't jive with the IE8+ baseline the site proposes.
I wondered to myself, why did he create a custom website just to present this? It seems like a great way to position yourself as a skilled front-end developer and advertise your services to potential clients. I suppose it could also have been done out of some kind of altruism, but I'm guessing the former.

Either way, this is pretty neat, and I'll probably be bookmarking it. We're using ClojureScript now and migrating away from jQuery, so this may prove handy.

Indeed you don't need jQuery. Though, there are standards and there are market/industry standards. jQuery has become a market standard wrapper. If jQuery isn't used, developers will still write a wrapper to ease some of these methods. It is better if that is a common market standard like jQuery than everyone doing it.

The amazing part of jQuery still to this day, beyond the selectors (which can now be replaced yes), is the plugin system. Just like Python, there is a plugin for everything and if you don't like them or there isn't one, developers can easily make one and share it with the world and it just works (tm). It is the most easily pluggable javascript library. It creates a baseplane that developers can be more efficient in. Everybody tries to replace the jQuery selectors, animation etc but they miss that jQuery is a platform and a pluggable one at that. It is responsible for tons of productivity.

Greenspun's Tenth, updated for 2014: "Any sufficiently complicated website contains an ad-hoc, informally-specified bug-ridden slow implementation of half of jQuery"

I understand the visceral opposition, but once you start writing a fallback to support some browser (something to support IE or FF or Safari or Chrome ...) you might as well use the battle-tested solution (and write your own thing if you find performance to be unacceptable and trace the bottleneck to jQuery)

The question at hand is, are fallbacks necessary anymore for the browsers we are targeting today?
And the followup is, when do you remove fallbacks from your code? Every time I think I should remove something I end up thinking, "well, it still works just fine, does it really matter if it stays for a little longer?"
The cost is in latency and complexity for users of your head browsers. How much do you want to reduce the user experience of your users on modern browsers to support users on old ones?

There isn't a one-size-fits-all answer for this, but you should have some idea of what your traffic breakdown by browser is, and ideally what your cost in conversion rate is for each additional ms of latency (this varies by industry). I don't remember offhand what the cost per byte in latency is, but IIRC we measured something like 1ms per 1K bytes at Google (this would work out to a 1 MBps = 10Mbps connection, which seems around right for typical cable/residential fiber households these days).

I'm not sure what you mean about "complexity for users of your head browsers". The idea of the fallback/polyfill is that it doesn't even come into effect for the modern browsers.

As far as latency is concerned, I hear you and that makes sense, but the things I'm talking about are not very big, so the latency gain isn't going to matter much for our purposes.

Yeah, we definitely look at the analytics. But even if it the old browser users are sub 1 percentage point, I see the number and think, "I could take this 5 line polyfill out, but then these 1000 uniques wouldn't work."

And I just don't have the heart...

Polyfills are generally a good idea - they cost basically nothing for users of modern browsers, and they go away.

I thought that the issue in this thread is JQuery, which is a layer on top of the modern browser API (probably because the modern browser API didn't exist when it was created, and is in a large part a native implementation of JQuery functionality), and so incurs the cost of all its legacy compatibility support even if you don't need it.

Android 2.3 is the problem more than IE<9 for many developers at this point.
Oh I see. Yeah you can just include a badge at the bottom right "Best used/viewed on Mac Firefox or Chrome".

For anyone else, just use jQuery.

  git fork jquery
  git branch "fix-performance-issue-at-<feature>"
  git commit ...
  git push
Rarely that easy. Oftentimes a performance issue can be traced back to an implementation that must support a dizzying array of use cases. You may not need all of that, but you certainly cannot just tear it out and push it back up.
You make another great point. Jquery includes tests for its implementations.

When you improve a slow implementation, it should be tested against that existing dizzying array of use cases.

I think you need a git checkout there. ;)
I assume fork aliases to clone, which gives you a checkout.
This be right on a purist level, but on every practical level there is little reason not to use [library of your choice]. If you're loading from the google/jQuery CDN (with suitable fallback, obvs.) you've got a good chance of a cache hit, and even if it misses it's a tiny one-off penalty.

And ultimately, why not? jQuery works, has a wide base of users, etc. Sure your trivial Js might not need jQuery features now, but as you add more dynamic behaviour, at some point you'll wish you had just used it to begin with.

A better message might be: make sure you know what the underlying javascript looks like, because there are a lot of people helpless without jQuery.

PLUG: if you're bored of jQuery, try Dojo. Far more power, in a less intrusive form, IMO.

i do Enterprise work & if we have jQuery in a page IBM dismisses our PMRs when we submit issues. So yeah I regularly include some simple cross-browser-normalizing js functions to use with the vendor-approved libs.

Also, jQuery is not trival to use in conjunction with other js libs (Dojo) as namespacing proponents claim. It's not like you just include both & they don't interfere. You have to follow a specific initialization pattern.

I don't understand this comment - I'm not suggesting you should use jQuery or nothing, or jQuery and Dojo. My point is the reasons given in the post for not using a DOM library of some sort are not valid.
o ok i was taking your comment within the context of the post -- more like "why not allow jQuery as a dependency for an open source lib". sorry for misread
Isn't it a giant security hole to be loading part of your library from another site you don't control?

Zillions of people do it anyway, so it's not like you won't have lots of company.

I trust Google more than most websites small enough not to have their own CDN, it's probably much easier and more likely to compromise them than Google's CDN even if of course Google is a more attractive attack surface. I guess theoretically it is, but practically I doubt it's anywhere near the most practical attack vector.