You might not need jQuery (2014)(youmightnotneedjquery.com) |
You might not need jQuery (2014)(youmightnotneedjquery.com) |
In every single example, the jQuery version is basically one or two lines of code, versus 10-15 lines for the alternative. (and the jQ version seems significantly easier on the eyes as well.)
Also, jQuery supports promises and has for quite a while.
This page hasn't aged well. I've come full circle and am now using jQuery again.
For reference:
// JSON
const data = await (await fetch('/my-url')).json();
// Post
await fetch('/my-url', { method: 'POST', body: data });
// Request
try {
const resp = await fetch('/my-url');
// ...
} catch (e) {
// ...
}
// Fade In
el.animate({ opacity: 1 }, 400);
// Fade Out
el.animate({ opacity: 0 }, 400);
// Hide
el.hidden = true;
// Show
el.hidden = false;
// After
target.after(el);
// Append
target.append(el);
// Before
target.before(el);
// Each
for (const el of document.querySelectorAll(selector)) {
// ...
}
// Empty
el.replaceChildren(); // or el.textContent = '', depending on which you find clearer
// Filter
[...document.querySelectorAll(selector)].filter(filterFn);
// Get Height
el.clientHeight;
// Get Width
el.clientWidth;
// Matches
el.matches('.my-class');
// Remove
el.remove();
// Delegate
document.addEventListener(eventName, e => {
const match = e.target.closest(elementSelector);
if (match) {
handler.call(match, e);
}
});
// Trigger Custom
el.dispatchEvent(new CustomEvent('my-event', { detail: { some: 'data' } }));
// Trigger Native
el.dispatchEvent(new Event('change'));
// Extend
Object.assign({}, objA, objB);
// Parse HTML
(new DOMParser()).parseFromString(htmlString);
// Type
obj[Symbol.toStringTag]; const resp = await fetch('/my-url')
if (!resp.ok) throw new Error(await resp.text())
const data = await resp.json()
From MDN (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API):> The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.
I also don't care much for the fetch() API; I dislike promises and what does it send when you try to POST a JS object ({foo: 'val'})? [object Object]. Yeah, useful...
And even in 2021-jQuery, it still works around some browser bugs and inconsistencies, even in modern browsers. Much less than it used to, but not zero either.
It's hard to overstate the impact of jQuery. It more than doubled my productivity due to removal of much of the duplicated work AND the general streamlining of DOM manipulation. As someone who was also neck deep in XML and XSD, the element selection syntax also felt reasonably familiar and comfortable.
> Loading the entirety of jQuery just to access some of the remaining features just means you're loading JavaScript that you aren't going to use
Isn't this the penalty for every single library we use. At most we can use about 20% and the rest is just out taking space.
Browsers got to this point because jquery pushed for it.
JS people be like: "86K jQuery dependency is wasteful!"
Also JS people: "why do you care that an SPA loads 2M of JavaScript? Are you stuck on a 56k modem or something?"
Yes, absolutely. That's a total no-brainer.
> Hidden complexity you don't control is the most expensive kind I think.
There's oodles of hidden complexity you don't control in any modern CPU, but most developers (rightly!) don't care. Complexity you have to fix bugs in is the expensive type, but IME you're far more likely to hit bugs in your custom implementation of whatever it was than in jQuery.
That's called encapsulation. :)
Seriously, encapsulating complexity is the foundation of most programming paradigms.
I don't actually use jQuery any more but obviously if you are using it, you are saving the 10-15 lines every time you use one of these methods, not 10-15 lines in your whole application. I have a hard time believing that the savings of code lines will not be close to the weight of the dependency in any medium sized company codebase.
Jquery is a thin wrapper over javascript, whereas React has a comparable size but is a significantly higher level abstraction.
There's projects like https://umbrellajs.com/ which are very similar to jquery's APIs for DOM manipulation and it's only 2.5kb gzipped.
IMO it's a nice balance between having a convenient API without bringing in the world.
If I could write 2-5x less code and it's easy to remember I would make that trade off every time.
That said, optimization techniques have gotten good enough that you might be able to just let a build tool do that for you. If you really still want to use jQuery.
"If you're developing a library on the other hand, please take a moment to consider if you actually need jQuery as a dependency"
Counterpoint, if you're developing a library, then (based on this page itself), each line that would depend on jQuery would otherwise balloon to 15 times as large, so maybe the highly optimized jQ dependency would be worthwhile if the extra functionality would actually be useful (or perhaps "slim" jQuery). The savings would increase for each additional library that had a shared dependency on jQuery.
But, anyway, developer time is valuable, and the 80kb or so for jQuery will probably be blown away as soon as you stick a single image on the page.
"Every single example?" Are we reading the same page? I was fairly surprised to find that 75% of the alternatives are literally one-liners. There are a handful that swell up to 10-15 lines of code, but I would say it's a very small portion, far from "every single example."
This page is just outdated. IE10 is a now deprecated browser whose last release was 4 years ago according to Wikipedia.
(BTW, the baggage of supporting old versions of IE was removed when jQuery 2 was launched in 2013. There's now also a "slim" jQuery that removes a few features for a smaller file size.)
Even the old jQuery seems easier to read than the modern ES6 equivalent (IMO).
jQuery:
$(".classname").addClass("darktheme")
ES6: document.querySelector(".classname").classList.add("darktheme")"jQuery and its cousins are great, and by all means use them if it makes it easier to develop your application.
If you're developing a library on the other hand, please take a moment to consider if you actually need jQuery as a dependency."
If you're shipping a big application and need to use a large number of these utilities, by all means use jQuery. But if you're shipping a small library and only need one or two of these functions, you might want to forgo the dependency. Using jQuery in your library forces it as a dependency onto everyone who uses your library, potentially making them deal with version conflicts if your version of jQuery doesn't align with their version of jQuery (or the version that another dependency wants).
But isn't the point here that you can wrap the 10-15 lines into your own function which you can then call with just a single line of code?
So you "might not need JQuery" because you can program it yourself following the examples given, and can choose which parts of it you need and want to package with your app.
You could do that for any software, not sure what you gain from doing it though.
On the web, user experience should really be a higher priority than developer experience.
> On the web, user experience should really be a higher priority than developer experience.
Those aren't disconnected. The more time I spend on technical implementation details, the less time I have to think about UX and/or implement things that improve UX.
But, either way, it really depends. If you are writing a large application and jQuery saves thousands of lines of boilerplate, then it's totally worth it. For a tiny library (which is what this page is targeted at), then it's probably overkill and you should learn how to do it manually with pure JS. Both can be true at the same time.
The only reason to reach for jQuery, IMO, is familiarity. If you don't want a framework, then just write vanilla js.
It's heavily inspired by "You might not need jquery" as the intro shows! Lots of the methods are just like in these examples, only with looping/multiple nodes. Example:
$(el).addClass(className); vs el.classList.add(className);
Do not work the same. jQuery (and Umbrella JS) deal with multiple elements and with multiple class names in multiple formats (as a string, as arguments, etc). That's why I find myself still using Umbrella JS from time to time in smaller non-React projects! Just makes everything a lot easier, for 3kb.
They're listing APIs that you used to need jQuery for that are now natively supported by the browser. This is for people still doing the jQuery style of development.
Oh wait...
If we're really clever we can probably get it up to several megabytes, require three languages and have it run from an embedded C compiler written in Webassembly.
Of course, it will only work in Chrome but really who wants to waste time testing in browsers nobody even uses amirite?
We're not in kansas anymore.
https://en.m.wikipedia.org/wiki/Program_optimization#When_to...
If your code can execute 10x faster without jQuery then the optimization is not premature. If a developer takes twice as long to write any code the problem isn’t optimizations at all.
One could argue that it is premature if the code doesn't _need_ to run 10x faster.
If you optimize process of delivering feature to the end user then using JQuery is optimization and not premature. It does not have to be optimization of runtime/load time.
Cash is largely a drop-in replacement for jQuery Slim at a significantly smaller size (~6kb vs ~24kb min+gzip).
The methods listed in youmightnotneedjquery.com are a little simplistic/buggy at times and not tested, if you just need a single method from jQuery it would probably be a better idea to simply copy/paste it from Cash.
Last weekend I was trying to find new car dealerships in my region that carried a particular model of car that I'm interested in. They had a dealer search page that could return all dealerships within 250 miles, and they had an inventory search page that had hardcoded the 3 nearest dealership IDs into the URL. But they had no GUI to search all the cars for all the dealers in my region.
I poked around at the elements on the dealership search page, cobbled together a jQuery one-liner to dump all the dealership IDs in my region, and pasted those into the URL to finally see every individual car in my region of the model I wanted. The page took quite a while to load, so probably have have some DoS vulnerabilities to deal with, but at least I was happy.
Vanilla javascript would have been so much more cumbersome!
And AFAIK not matched by any simple wrapper for the newer APIs (it's fashionable to go to heavier ones like axios).
I still grab jQuery into projects for the sheer convenience.
I have actually gone back to making heavier use of jQuery again these days.
The biggest flaw of jQuery is concealing some levels of complexity that are absolutely vital to grasp.
The primary reason for that distinction is that you are willing to spend a tiny bit of effort on micro-improvements to quality of product or aren’t, just like parenting. Yes, the effort is ridiculously tiny because it pays for itself with only a trivial amount of practice.
jQuery speeds up development, but in most situations it's straightforward to replace.
On the other hand, I never remove React (and especially Reagent) from an existing site - too much effort, too much to break.
Hacks with :checked are well known, but you can do a ton of stuff with :focus-within, :invalid, :target, :hover, <details>/<summary>/[open], grids/flexbox/visibility, and the adjacent-sibling selector. <dialog> is almost there, although it still needs a JS activation hook.
It feels really good to have a complete application UI that works with JS disabled, and I can still progressively enhance it with JS for necessary perversions of HTML like ARIA etc.
WebComponents can do just a fraction of what React/Vue do, and it's just the least interesting parts. The encapsulation is great, of course, but it was already possible to have "reusable components" back in the jQuery days and before.
All the WebComponents usage I've seen professionally lately were wrapping React/Vue or using some other lightweight framework that does something similar.
Not saying WCs are bad tech: just saying I think there are some great ideas in Vue/React that still don't have a native API. Would LOVE to see a new version of WebComponents adopting some of those ideas (only the good ones though haha)!
As well as the form issue, what made webcomponents untenable for me was that you can't use slots without opting the whole component into CSS encapsulation.
Great if you want to distribute components without fear of the consumer's CSS messing with your styles, absolutely useless if you want to extract common patterns in your own app because now you have to duplicate the relevant CSS in every component.
That said, I was once a single page app skeptic but I now think React and Vue are great alternatives to HTML/templates that compile to HTML if you have a reasonably complex front end. Pre-React and Vue, in the Angular.js/Ember.js/Backbone era, SPAs were not in a stage of maturity that made it simple or optimal to use them as a primary front end. Today I'd say for a complex FE go ahead with React or Vue, if you have a very simple FE, definitely consider HTML/template-to-HTML as a serious option.
(and no, I don't mean WebAssembly - bring back static websites!)
Sorry to pick on your post over the million and one other ones that pop every time jQuery gets mentioned in HN (same for the "look at my my blog website that just uses HTML/CSS" posts), but why is it silly? There's no halcyon period where it was simpler and easier, and the tools are in general much better than they were.
Because of bloated frameworks and slow convenience libraries the front end is a very low barrier of participation. The problem there is then that peoples’ entire careers and life worth are stacked around these fragile glass houses and the only thing they want is to avoid being exposed as a fraud.
Is writing a killer product without all the bullshit that impossible? No, clearly not, but that completely misses the point.
- Got rid of redux because it's shit
- Got rid of Material UI because it's bulky and its API changes are painful, replaced it with tailwind
- Got rid of React Router because it's bulky and its API changes are also painful, replaced it with a simple hook
As someone who worked on large jQuery apps before React, I think most people would jump back into React or Vue in the first chance after seeing a non-trivial jQuery app. Not to mention there was a lot of "bloat" in those apps, too: Backbone, Bootstrap, Moment.js...
jQuery was amazing for small things, for landing pages, for some Bootstrap components here and there, and for sprinkling the page with progressive-enhanced features. And it still is probably the best choice.
But it was not a great fit for moderate-to-large apps. And it was a terrible fit for moderate-to-large apps that only consumed data from an API.
Not saying React and Redux are good, but I think at least the parts of React, Angular and Vue that replaced jQuery were definitely a step in the right direction.
I'm also not saying that "big apps" are the way to go. If I could I would go back to server-side rendered HTML and modern CSS, but it has become hard to find developers that are into it.
I strongly recommend reading through the newly rewritten official tutorials in the Redux docs, which have been specifically designed to show our recommended practices:
- "Redux Essentials" tutorial [0]: teaches "how to use Redux, the right way", by building a real-world app using Redux Toolkit - "Redux Fundamentals" tutorial [1]: teaches "how Redux works, from the bottom up", by showing how to write Redux code by hand and why standard usage patterns exist, and how Redux Toolkit simplifies those patterns
The older patterns shown in almost all other tutorials on the internet are still valid, but not how we recommend writing Redux code today.
You should also check out the Redux "Style Guide" docs page [2], which explains our recommended patterns and best practices, and why they exist. Following those will result in better and more maintainable Redux apps.
[0] https://redux.js.org/tutorials/essentials/part-1-overview-co...
[1] https://redux.js.org/tutorials/fundamentals/part-1-overview
Look at svelte if you haven’t.
It doesn't have a compilation phase but it allows us to use Preact, and it's only 5k.
Of course if you need much of the functionality of JQuery then it is a perfect fit for you.
Note there is a cost to JQuery associated with learning and understanding what exactly each function of its API does. If you have paid that cost already by using JQuery and thus learning it, and you need it, then it makes sense to keep on using it.
What I meant was inlining the jQuery calls to their equivalent JS snippets, removing the need for including a 80K library if you are not overly dependent on jQuery. It was also a tongue-in-cheek comment.
On low-end devices it's a bit too much (I'm talking about edge-case users with phones as cheap as $50). It was also quite a chore keeping up with their API changes every couple months.
I forced myself to cut down on components and just style my UI with CSS. It's more consistent, more predictable, and less strain on the end-user's device. It's a trade-off across looking good, better end-user performance, good user experience, good developer experience, and having more time for the product and users instead of maintaining and updating dependencies.
jQuery rarely has security issues anyway; and the issues that do exist are usually low-impact. It certainly won't have any more than any code I'll write myself.
It's not even a build-chain only feature at this point. Some of the reasons the ES2015 module format was built the way that it was were exactly so that browsers can do their own tree-shaking of runtime code. Even if you don't save on the performance impact of the extra 30 KB from being downloaded, in modern enough browsers you would potentially still see a performance impact on browser memory usage and JIT compilation time.
Even if your bundle size has bloated to a MB already, a 30 KB savings is still roughly a 3.3% savings. It's still noticeable. Whether that is "significant" is an argument of personal taste and how many "9s of performance" you try to deliver. Even single digit percentage savings can be huge "significant" wins for many projects.
* trial
* error
* reading the HTML, DOM, and CSS standards documents very thoroughly end-to-end
* stackoverflow
* repeat
However, for your standard CRUD type app, honestly round trips of 100-200 ms for backend requests are really common/standard. On the FE, loading and evaluating big JS bundles, rendering, etc., can be way slower. For CRUD apps I’ve worked on, perf issues on the FE have been more common than on the BE. Especially with the common React/Redux stack, it’s very easy to make perforce mistakes and end up with a lot of unnecessary component updates when things aren’t really changing.
Is a request that technically succeeds (the response has come back), but has a status code where the server has indicated something didn't work always an _exception_ in your client code? I'd argue it isn't, and should just be handled in the normal control flow of your client code via conditionals.
Java users might want to make 404 an exception (FileNotFoundException), C++ users probably wouldn't throw an exception for that
Encapsulation/abstraction should really be a tool of last resort. From experience, it doesn't actually help reduce complexity if overused, but just makes it hidden and more likely to surprise you when you're debugging.
jQuery's not a very good example of this though. It's one of the most widely used, and hence most tested and least buggy pieces of software out there. Nowadays the web APIs are pretty solid, but back in the IE6/7/8 days the jQuery API was a lot less buggy than using the built in APIs directly.
Does jQuery (est. 2006) have more bugs in it than your code?
To me this seems a comment that only stands for one-developer projects.
https://en.wikipedia.org/wiki/Encapsulation_(computer_progra...
I do agree 30k is hardly worth thinking about.
https://arstechnica.com/gadgets/2020/12/firefox-v85-will-imp...
https://developers.google.com/web/updates/2020/10/http-cache...
Dealing with those versions was where jQuery really earned its spot in the JS universe. It was a lot to remember where all the quirks were and the incantations to work around them.
https://api.jquery.com/fadeOut/
Edit: I just realized you said "transforms". Transforms are a separate question from transitions. CSS transforms are concerned with giving an element a different size, rotation, and/or position. Transitions are concerned with changing any given CSS property gradually over time (including potentially transforms). I think you're right that jQuery started using CSS transforms, but it does not appear to use CSS transitions.
The main case where CSS transitions are meaningfully faster appears to actually be transforms themselves, because for those the actual transition, too, can be moved to the GPU, whereas a JavaScript-driven transition still has to be run on the main CPU thread.
* "CSS transforms" are unrelated to animations.
- Umbrella 6 lines (max col 55): https://github.com/franciscop/umbrella/blob/master/src/plugi...
- jQuery 35 lines (max col 83): https://github.com/jquery/jquery/blob/master/src/attributes/...
Yes I reuse methods there to make my life easier like `.eacharg()`, but jQuery as well with `getClass()`. The difference is that UmbrellaJS is using the native `classList.add`, while jQuery is doing string concatenation and cleaning it up heavily. jQuery does not even use `className`, it uses the even older `.setAttribute()`.
Why they cannot just move over? I did try to move them over, the thing is that the edge cases of jQuery were solidified into features as people found them and wrote tests. And jQuery is very big on not breaking behaviour even for small things, so the only way to maintain the current exact behaviour is to have the current exact code, hence you cannot just migrate it over.
You answered your own question :)
And maybe such a single function is currently already provided by the browser APIs.
Or maybe there are packages of individual functions of JQuery? But that would serve little purpose IF the functionality is provided by current browsers.
In any case I think the article serves a good purpose in explaining what are the most useful parts of JQuery and how you could implement them yourself with the more modern browsers if and when you need them.
My preference is to avoid dependencies if I can and prefer depending on my own code which uses standard APIs if possible.
> Yes, absolutely. That's a total no-brainer.
That's what we've been thought but it's not a no brainer at all. Context matters, but you disregard it and only focus on the lines of code, just as the author of the comment you respond to is saying people do.
You're building a marketing page that's not gonna be updated after completed and only gonna be valid for X days? Sure, the code doesn't matter.
You're trying to build a fast and slim UI that's gonna be deployed on routers and possibly loaded on low-power devices? You better care about every single line that gets loaded on the device.
I'm not saying dependencies are always wrong. I'm also not saying it's always right. I'm saying why you need the dependency and the quality of the code it includes is important to consider, and knee-jerk reactions of "of course I'd use it" is hurting the profession more than the library reuse saves us currently.
Unless you've gone out of your way to buy a (more expensive) part with less memory, your router will have enough memory to make 86.1Kb an utter irrelevancy; so will most of what were traditionally considered "low-power devices". Yes there are extreme cases where it matters, but we're talking about a vanishingly rare proportion of use cases.
> I'm not saying dependencies are always wrong. I'm also not saying it's always right. I'm saying why you need the dependency and the quality of the code it includes is important to consider, and knee-jerk reactions of "of course I'd use it" is hurting the profession more than the library reuse saves us currently.
I think this is backwards, and the knee-jerk reaction of "of course it's important and you need to carefully think about it" is what's holding back the industry. The overwhelming majority of the time, the right thing is to use the dependency; the best development practice is to default to using dependencies and reassess if and when it you hit an actual problem.
I'm curious - would you be able to elaborate, please? Thank you.
Run into a couple of examples of such complexity, and the dependency is well worthwhile.
A jQuery that can be tree-shaken would be awesome, as there are parts I use regularly and others I have never used. Ironically the -lite bundle leaves outs parts I use frequently...
I find both `element.nextElementSibling` and `element.next()` to be examples of poor API design. The former one is more verbose than needed while the latter one is so short you can't even tell whether it's a method or a property.
Ah, thanks. I got bitten by this recently and didn't know what to do with this "thing that's not an array but seems like it should be, and doesn't always behave like one"
Accounting for 70% average minification and 40 characters per line on average, that's around 6,500 lines of normal code shipped "for free" by using pReact instead where there's both no wire cost and no extra parse time.
Equivalent code in ES6 would be (maybe there's a terser way but this is what I'd do at first glance):
[...document.querySelectorAll('.className')].forEach(el => el.classList.add('darktheme'));
Not a whole lot extra in terms of actual code, but I'd argue it's not super intuitive (having to cast a NodeList to an array is a pretty big beginner footgun), and as you get into more complex scenarios, the jQuery architectural pattern of operating against collections of nodes really shines. document.querySelectorAll(".className").forEach(el => el.classList.add('newClass')); $(".classname").addClass("darktheme") $('.class').remove()
$('.class').after(...)
vs: var e = document.querySelector('.class')
e.parentNode.removeChild(e)
document.querySelector('.class').insertAdjacentElement('afterend', ...)// Edge 12 document.querySelector('.class').remove();
// Edge 17 document.querySelector('.class').after(...);
Where jQuery shines - but also hides a lot of complexity- is when operating on an array of elements, e.g. if you want to remove all elements with a certain class.
document.querySelector(".class").remove();
document.querySelector(".class").after(...);I do not get the hate over jquery, specially since frameworks like angular used (use?) to include a light version of it (sizzle or similar?) and methods like $httpParamSerializerJQLike, which does not scream of elegance.
I still remember when prototype.js was the default in rails, and jquery was so less overengineered and it just worked. It felt like magic.
Plus, in this case, you will find out by seeing the dark theme is not active :p
Javascript/CSS/HTML forms the common basis of web development. You may assume every reader of your code is familiar with it.
If you use a specific library, you are restricting (easy) readability to those that know the specific library.
This has merit if the library provides sufficiently useful abstractions or shortcuts, but it's only a drawback if the library provides merely an alternative way to write something already possible in the base layer.
I know plenty of developers who would view inclusion of JQuery as some cardinal sin due to reasons like the ones you state, but don't apply the same logic to React, Redux, or other more modern, significantly more complex libraries.
Browsers have since mostly fixed "browser compatibility issues" at the standards level, so that problem technically no longer needs solving.
As applications have grown larger those other things that were out of scope for JQuery have become bigger and bigger problems that developers face. (Of the big two I mentioned React solves one, Redux solves the other.)
Some people see JQuery as a "cardinal sin" for the first issue: browsers have already "solved" this, this is a deadweight because it fixes a problem I no longer have. They would have fewer problems with React/Redux/whatever because they solve new problems.
Some people see JQuery as a "cardinal sin" as much for the latter issue: because JQuery was so unopinionated on code structure, data flow, component structure, it led to a lot of real world code that was "JQuery spaghetti" littered with anti-practices like relying heavily on global or might as well be global variables for state information, with no structure to which code might impact which variables and when. Componentizing a JQuery system was often a lot of hard work that JQuery itself didn't help with (and given it's own common usage as a window.$ global with sometimes surprising bits of hidden state inside it, in some cases directly hurt those efforts). Given libraries like React or Redux were designed to solve some of the problems that JQuery once created, it also seems clear why some developers might be very vocally antagonistic to JQuery but have no problem bloating a project with tools that solved those problems and/or have more structure and opinions on building "good" componentized/compartmentalized structures.
In those cases, I'd argue pReact is superior. It's almost 10x smaller (29kb vs 3.5kb gzipped). It's faster and more structured leading to less maintenance cost and more code reuse. If you use hyperscript, there's also no JSX compilation required.
You are also putting a heavy burden of proof on your readers: it generally sounds implausible that exactly the same people would complain about <100kiB being bloat and >1MiB not for the same use-case, but I am not going to go and fact-check that (with the implausibility of the claim, I would expect you to give direct pointers yourself or will simply distrust your claim).
All I know is that you can build a custom jQuery build with grunt, as described in their README, which is what I do. I mostly use JavaScript as if the last ten years didn't happen, so I'm hardly an expert on any of this :-)
It gets around a half-million downloads per week according to NPM stats while hyperapp gets under 3k per week.
But looking at the repo https://github.com/hyperhype/hyperscript I have a hard time imagining how preact can work together. They seem to overlap in functionality.
https://preactjs.com/guide/v10/tutorial/
or you can use the full hyperscript markup library