Why is jQuery (not) relevant?
I dare to say there isn't a web developer who has never worked with jQuery. It's recently been 10 years since the first version of jQuery has been released, and through the time it has became some sort of de facto standard for web development - a standard, which is slowly fading away. In the last year or so, jQuery has gone from being a feature library to being a trade-off library, and I believe that within the next 2 years, it will either go through some fundamental changes, or become abandoned. This may seem like a bold statement, but there are several pretty good reason for that.
jQuery selector engine
The debate about whether Sizzle (jQuery's selector engine) is still relevant has been going on since 2010, when all major browsers got full support for document.querySelector
, which, except for some jQuery-specific selectors such as :animated and :hidden, does exactly the same thing. There's plenty of articles comparing the two, with the important issues being pre-IE9 support and the lack of jQuery's syntax simplifications, like .class:not(div, p)
. That's where the first major trade-off is: you can use $('.class:not(div, p)')
, or you can write document.querySelector(':not(div):not(p).class')
, making the code less pretty and up to 10 times faster. While IE8 and IE9 support may still be needed for some webpages, making the website faster and lighter will get you way more customers than supporting old browsers with 0.25% market share.
jQuery modules
There are 9 major modules within the jQuery library: ajax, css, dimensions, effects (a.k.a. animations), event, offset, wrap, ready, and deferred. If IE9 compatibility isn't required, one can combine element.style
and Object.assign
to achieve the same level of style manipulations as using jQuery.css
. Furthermore, there's Web animations API to replace jQuery effects, the EventTarget interface to handle events, Promise object to replace deferred, and by putting your scripts at the bottom of the page, you really don't need jQuery.ready
callback. The wrap functionality can be replaced with a simple Array.forEach
, but there aren't many cases where one wold actually need it anyway. In summary, only ajax, dimensions, and offset modules don't have native counterparts (yet), and there's a good reason these things don't have direct counterparts in the native code.
Ajax
There are window.fetch function and the FormData object, which act a lot like the jQuery ajax - the main difference being the handling of HTTP response codes. jQuery being smart and convenient, it invokes the error handler if the response code isn't 200 (success). This means the developer has to either write both error and success handlers to handle API return values, or avoid using proper response codes (which is sadly what most developers decide to do). HTTP protocol exists for a reason, and encouraging people to be lazy and ignore the built-in functionality is clearly not something you'd want to do.
Dimensions and offset
This one is a little tricky - on one hand, having functions to conveniently access element's dimensions, padding, position, etc. is great. It comes especially handy when you're dealing with drag&drop or trying to center a pop-up on the screen. Except there exists a dialog element, which is specifically made to provide a simple pop-up interface, and there's a native drag&drop functionality in pretty much all desktop browsers (even IE6!). What people actually use these two modules for (apart form obtaining element width & height) is to make thick responsive websites, which, in 99% cases, should just use the flexbox. Existing functions already provide access to the important element dimensions, while all sorts of offset should be handled by CSS. Messing with borders, padding, etc. just means you'll have to rewrite the whole thing to make it work with a different HTML element.
jQuery or a polyfill?
Some of the functionalities mentioned above aren't fully supported in all browsers - after all, if they were there'd be no jQuery. However, there are polyfills for all of those functionalities, so the question arises: Should I use a polyfill or jQuery? There's no definitive answer, so you should look at what you actually need, and how your workflow works.
For example, if you only need the ajax module, loading the whole jQuery makes no sense. Even the jQuery's ajax module alone is 20% larger than the window.fetch polyfill, and you'll get the whole selector engine (in total, about 500% larger than the polyfill), even though you ain't going to use it. On the other hand, if you're using several jQuery UI widgets, you probably won't load another script just to use a newer feature.
There's a mayor difference between jQuery and a polyfill - a polyfill checks whether the native implementation supports the required functions, then adds the missing functionalities as needed. It executes once to map the code, and there's no overhead when you call the functions afterwards. On the other hand jQuery adds a layer of abstraction, so every time you call the functions it performs several checks to determine which native function can or can't be executed. If you load the polyfill each time the page reloads, it will probably have some impact on the load time, however if you have a web application which loads once and then runs the same code until the user leaves, making 5 or 10 unnecessary checks every time something happens will probably take more than the loading of a polyfill at the beginning.
I roll up, I roll up, ...
Unless you've been living under a rock for the past couple of years, you're probably using a build system / module bundler / code minifier / transpiler, or another tool which takes your code along with it's requirements, and outputs a single file you then put on the website. The AMD module system used by jQuery isn't very good for that, as it only allows the bundler to keep or remove an entire module. Luckily for you, what most bundlers can do is check the code and determine which polyfills are actually needed to provide a certain level of browser compatibility, and bundle them with the code. This is important for 2 reasons:
- You can write good code, and have it gracefully degrade on older browsers thanks to polyfills - this prevents outdated code from piling up on longer projects
- Dropping support for an outdated browser is as simple as changing a few lines of the build system config, so removing legacy stuff no longer needs to be a project on it's own
Conclusion
Clearly everything jQuery does can be done without jQuery as well. While a couple of years ago that would take plenty of time and work, today HTML5, ES5, and polyfills make it possible to write clean and fast JavaScript code without the need for jQuery or similar libraries.
There's nothing wrong with using jQuery. It makes your code more legible, it lets you write small and streamline code, and as long as you're using it, you don't have to worry about older browsers. It's a trade-off; you can be lazy, write short code, and ignore the differences between browsers - just let other people handle that, as long as they're willing to. There's no need to reinvent the wheel, or learn how to handle the gap between organised & transparent code on the developer end, and small & fast code on the user end.
But don't forget: by using jQuery, you're trading shot-term benefits for a long-term performance. Native functions have access to hardware acceleration, precompiled optimisations, and direct access to DOM tree and other data, so no matter how convenient it is to write jQuery code, it'll always run several times slower than the native equivalent. In the end it all boils down to customer satisfaction, where a few extra minutes of your time or a better IE8 support is nothing compared to customers leaving because slow JavaScript code is making the site lag.