15 ms·
Show HN: Auto-generate vanilla JavaScript alternatives for jQuery methods
- Etheryte 5y agoWhile this is technically interesting, I can't help but ask what the benefit of this is? Instead of using a library that's battle-tested and well documented you'll now have to maintain an ad hoc replacement with unknown unknowns. Cutting down your bundle size is a good goal, but this feels like much too steep of a tradeoff.
- mkoryak 5y agoThere is a trend in web dev right now to stop using jQuery because reasons. These reasons make sense if you use a framework and sometimes need to venture outside of it. The problem is that the reasons are not often understood and then a tool like this comes along and now we can easily replace jQuery with a worse API adapter. Hooray!
- masklinn 5y ago> There is a trend in web dev right now to stop using jQuery because reasons. One reason is that a lot of jquery’s bulk is compatibility concerns or BC in edges, if you decide that you don’t support old jQuery (mis)behaviour, older APIs, older browsers, … you can probably slim it down a fair bit. A bunch of utilities you can also probably do without e.g. your jQuery.map, animations stuff, … jQuery is progressively deprecating more and more things, but it’s a harder sell to actually remove them.
- mkoryak 5y agoLike I said, all the reasons for removing jQuery are valid, but only in the context of the codebase where they are given. You wouldn't want to remove jQuery from an app that is used by IE9. People end up hearing the reasons and don't stop to think, hey does this actually apply to my code? What are the trade offs for that 30k of code? Many just end up rewriting what jQuery did in a non reusable way that contributes to code bloat and bad readability.
- byteface 5y agoI do feel the move against jquery comes from people that surpass it, which seems a shame. They had to use it once. It's like burning the rope for the people behind. Many low level users don't care about 30kb to get the $ shorthand as it's a habit they've had for a decade. It's funny almost to see the hoops people jump through not to use it. Like having a point to prove and not being able to prove it. Hey look, you can replace jquery with these 10 unmemorable esoteric steps.
- cormacrelf 5y agoThe repo says it is for lightGallery, which is trying to offer a framework-agnostic lightbox component. Modern JS setups simply don't play nice with jquery.min.js, and it's a big download and hard to slice up. This helps folks reuse more old work like lightGallery. That's a pretty good reason, almost the best possible reason to build this, I think. How it will likely be used is a different matter -- if you're a company trying to hire young devs and don't like to admit you have any legacy tech in the stack, then this is HOT code right now. Same if you need some bullshit targets to hit before the end of the quarter. Get on it!
- Deukhoofd 5y agoI guess it might be useful as a first step if you want to reduce your dependencies on jQuery. First use this so you can drop the dependency, then slowly replace the functions you're using.
- mynegation 5y agoFrom the first glance it replaces the jquery calls to some $utils implementation of the same methods. I guess final bundle contains only methods in $utils that are actually used in the code base, but it looks like re-implementation of jquery subset. Would not just using jquery with tree-shaking achieve similar effect? (not a JavaScript expert, so sorry if it is a dumb question). Maybe another advantage of this is that new implementations target runtime version that is new enough to avoid most of the feature-checking and shims? Would be great if README addressed those questions.
- fabiospampinato 5y agojQuery is not tree-shakeable because it uses a chainable API. Like you don't import `toggleClass`, you access the `toggleClass` property of a jQuery instance, so it can't be tree-shaken off automatically. Even if somebody made a bundler plugin for doing the heavy work jQuery can only be partially compiled with whole modules excluded, you can't exclude individual methods (e.g. you can't just remove `toggleClass`, you have to remove also `addClass`, `removeClass` etc.). FYI I maintain a jQuery alternative that supports being partially compiled with individual modules turned off, but it requires manually listing them: https://github.com/fabiospampinato/cash https://github.com/fabiospampinato/cash
- timostamm 5y agoTree shaking works well when you have ESM imports / exports. jquery is/was usually loaded into the global scope. There is no standard way for tree shakers to deduct which parts of the library you are using. Yes, browser APIs have matured significantly since jquery was new and such a library doesn't add much value anymore. I agree it would be great if the README gave a bit more background. Whoever is looking to migrate away from jquery will be aware of the background though (and will likely appreciate this tool).
- fabiospampinato 5y agoI maintain an alternative to jQuery called Cash [0], this looks cool! If you are interested in joining forces OP it'd be cool to have this capability in Cash itself. IMO that'd be the best of both world because this feature is cool and useful, and Cash's methods are most probably closer to jQuery's, better tested and there are more of them available (76 vs 44). For example, your `on` method [1]: - Doesn't support event delegation. - Doesn't support event namespaces. - Doesn't support receiving an argument mapping events to callbacks like jQuery also can. - It seems to have subtle bugs, like the way the events string is split makes so that double consecutive spaces in it (which can happen as a result of a typo) will result in listening to the empty string event. Basically: 'foo bar'.split ( ' ' ) => ['foo', '', 'bar'] (there are two spaces between foo and bar). The `on` method we are using in Cash [2] is a lot more convoluted than that. On one hand it requires more bytes, but on the other the chances of it behaving exactly like jQuery's are much higher. In fact we can also run jQuery's test suite with Cash to spot issues. Feel free to ping me if you are interested in joining forces. [0]: https://github.com/fabiospampinato/cash https://github.com/fabiospampinato/cash [1]: https://github.com/sachinchoolur/replace-jquery#on https://github.com/sachinchoolur/replace-jquery#on [2]: https://github.com/fabiospampinato/cash/blob/master/src/events/on.ts https://github.com/fabiospampinato/cash/blob/master/src/even...
- sachinneravath 5y agoSure, Cash is super cool. I wrote this library for my personal use. As I was repeating the same work on multiple projects. While removing jQuery dependency, the hardest part was finding the jQuery methods in the existing project and writing the alternative vanilla js methods without making much changes in the codebase. Yes, I agree with you the events part needs to be improved and well documented. (It actually supports namespacing.) I fixed most of the things in https://github.com/sachinchoolur/tiny-events.js https://github.com/sachinchoolur/tiny-events.js and need to make the changes here as well. My intention was not to build another JavaScript utility library. I just wanted to make my JavaScript libraries jQuery independent.
- labster 5y agoSeems pretty cool. The only Cash design decision I’m doubting is $().append not accepting plain text. I get the reason why, but the alternative is ugly. Maybe add an appendText method, or a utility $.textNode? I’m kind of assuming the underlying philosophy of the project is to make DOM manipulation as easy as in jQuery but smaller by removing seldom needed safeguards and relying on modern browser selectors. I’m okay with the additional footguns but think it should still preserve easy, concise syntax.
- manigandham 5y agoVanilla JS refers to Javascript that uses native browser methods instead of relying on a library. This is just replacing jQuery with another library constructed on the fly, but there are already minimal and modern alternatives with the jQuery API like zepto and cash. 1) https://github.com/fabiospampinato/cash https://github.com/fabiospampinato/cash 2) https://github.com/madrobby/zepto https://github.com/madrobby/zepto
- q-rews 5y agoThis. There’s zero sense in using 1:1 replacements of jQuery nowadays since jQuery already has a slim version. If you want to drop jQuery, you have to rethink the code.
- fabiospampinato 5y agoCash's maintainer here. IMO it could be worth for some use cases to use a replacement for jQuery, for the record Cash is ~75% (~20kb minified and gzipped less) smaller than jQuery Slim, that isn't/shouldn't be a rounding error for many use cases.
- vmception 5y agoThese are good points, people are more so taking issue with the title. I was expecting a tool that just tells me how to do something in Javascript - without any library - that I would be tempted to use just include jQuery for. Instead I'm presented with a library. I expected the comment sections to be talking about how AI/ML crowdsourced code aggregators keep messing up, instead I'm reading about a simple additional convenience library that a contractor wrote for themselves, and described wrong.
- laurent92 5y agoActually, VanillaJS is now a library. It can be downloaded in 0KB, or 25KB gzipped. Not to be confused with “Vanilla JS”. It comes with the famous “Math” library that Google and Strip use, for 0KB additional. http://vanilla-js.com/ http://vanilla-js.com/
- ape4 5y agoI'm going to keep jQuery for a while. Its not so big and even though native js has "caught up" in places jQuery is still more compact.
- jamesfinlayson 5y agoAgreed - in a personal project I've moved a lot of functionality to native but sometimes jQuery is just more neat and understandable.
- q-rews 5y agoPeople are confused about what vanilla JavaScript means. If you’re replacing jQuery for another loose library you’re just fooling yourself and wasting time doing it. This is akin to all those StackOverflow answers suggesting to use `any` for every TypeScript problem they encounter.
- simondotau 5y agoIt’s worth remembering that jQuery is a ~30kb “cost” for the end user. Once upon a time, that was a lot. And it was entirely prudent to question its necessity on the basis of load times and bandwidth consumption. But now we live in a world where many common web pages have over 1000kb of resources on them. And nobody blinks an eyelid.
- manigandham 5y agoUnfortunately this kind of thought process is what leads to pages with megabytes of JS. Every byte matters.
- mkoryak 5y agoThis is especially true because now instead of all your dependencies using jQuery, they are each implementing a small subset of jQuery on their own. The problem you thought you solved was actually made exponentially worse when those dependencies dependencies also rewrote some jQuery using different native methods
- sanitycheck 5y agoBut, we didn't used to have megabytes of JS on pages back when everyone used jquery. I think what leads to pages with megabytes of JS is when people automatically assume that all projects must be a SPA built on one the popular everything-but-the-kitchen-sink frameworks.
- simondotau 5y agoBut it isn’t a one-way street. Using jquery can eliminate the need for other, lengthier blobs of code. In fact that’s exactly what this “vanilla JavaScript alternative” does.
- fabiospampinato 5y agoI'm not sure I buy this argument, one can't just say that ~30kb isn't a lot because 30 is a number perceived as low, would 30kb be justified for a library that allows you to toggle a class on a node? Of course it wouldn't, you need to measure what you are getting for 30kb. I don't buy the second part of the argument either, you can load a 1000kb image on a blog post and that won't have nearly the same effect as loading 1000kb of JS. The JS needs to be parsed and executed and maybe the site doesn't even work without it, the image can probably be rendered progressively, can be decoded in another thread, nothing is really waiting on it to load, and if it doesn't load at all it's not the end of the world anyway. With ~4kb you can have Preact, is jQuery Slim (~26kb) giving you ~6.5x times as much value as Preact really? Maybe it is, probably not. For some context I maintain a ~6kb rewrite of a subset of jQuery (https://github.com/fabiospampinato/cash https://github.com/fabiospampinato/cash), which IMO is much better value proposition for many use cases.
- Lurkars 5y agoI first thought that it replaces jQuery with vanilla, but it replaces jQuery functions with other functions? With this point of view using the term vanilla would mean that there is no difference to jQuery, because in the end jQuery is also written in vanilla? Or do I get something wrong here?
- codingdave 5y agoThis is more like tree-shaking jQuery into just the pieces you need from it, so you aren't loading up the full library when you are only using 20% of it.
- franciscop 5y agoI made a tiny jQuery alternative a while back called Umbrella JS: https://umbrellajs.com/ https://umbrellajs.com/ Seeing methods like addClass in "replace-jquery", I'm not fully satisfied. I could make Umbrella JS tiny (1/2 of the alternative listed elsewhere in the thread, Cash, and 10% the size of jQuery) because of heavy method reusal. For instance, in Umbrella JS addClass is just: u.prototype.addClass = function () { return this.eacharg(arguments, function (el, name) { el.classList.add(name); }); }; In "replace-jquery" you are already depending on `this.`, so why not making a couple of useful utils? Right now it is more verbose, and doesn't accept e.g. an array of classes or classes as arguments: addClass(classNames = '') { this.each((el) => { classNames.split(' ').forEach((className) => { el.classList.add(className); }); }); return this; } Cash JS's addClass (which is hidden behind toggleClass(cls, true)) is nice, it's bigger BUT that's because it's 3 implementations at once (addClass, removeClass, toggleClass). It properly uses a method to getSplitValues, which is very helpful and flexible: fn.toggleClass = function ( this: Cash, cls: string, force?: boolean ) { const classes = getSplitValues ( cls ), isForce = !isUndefined ( force ); return this.each ( ( i, ele ) => { if ( !isElement ( ele ) ) return; each ( classes, ( i, c ) => { if ( isForce ) { force ? ele.classList.add ( c ) : ele.classList.remove ( c ); } else { ele.classList.toggle ( c ); } }); }); }; And I will spare you all jQuery's implementation, which is huge, but it can be seen here: https://github.com/jquery/jquery/blob/main/src/attributes/classes.js#L22-L57 https://github.com/jquery/jquery/blob/main/src/attributes/cl...
- fabiospampinato 5y agoCash's maintainer here. I really don't think anybody can squeeze 50% out of the 6kb min+gzip code that make up Cash, quite a bit of thought went into squeezing as many bytes as possible out of it. (while still preserving a large degree of compatibility with jQuery, support for many methods and support for partial compilation) Your comparison isn't quite fair, our toggleClass function does a lot more than a simple addClass, and writing it this way lowers in fact the total min+gzip size. I'd be pretty impressed if you can shave just 1kb out of those 6kb to be honest.
- yawaworht1978 5y agoIs there anything like this for react, Vue etc? Now that would be a milestone.
- t0astbread 5y agoShouldn't that be handled by tree-shaking?
- warpspin 5y agoWith all the people replacing jQuery manually in their projects, you have to wonder whether the summed up costs of everyone running their own replacements is not larger than jQuery itself, once you use 3 or 4 such libraries :D
- SOLAR_FIELDS 5y agoIt’s been awhile since I’ve worked in the frontend space, but even 5 or 6 years ago if you were using a pretty popular hosted CDN of JQuery with a pretty recent version there was a pretty good chance it was already cached on the end user’s device when they hit your site. There’s always a lot of talk about Jquery’s size but I wonder how many users don’t even notice because they’ve already got it on their system. There’s also of course the added cost of executing the library on the site but I’m guessing V8 and other JS engines have optimized the hell out of that too as to make it pretty negligible in terms of time difference.
- JZumun 5y agoModern browsers partition caches by site nowadays - at least, Chrome started doing it last year[0], and Firefox followed soon after I think [1]. That means there's no longer any caching benefit for multiple websites using jQuery - each site will download and cache it separately. [0] https://developers.google.com/web/updates/2020/10/http-cache-partitioning https://developers.google.com/web/updates/2020/10/http-cache... [1] https://developer.mozilla.org/en-US/docs/Web/Privacy/State_Partitioning https://developer.mozilla.org/en-US/docs/Web/Privacy/State_P...
- SOLAR_FIELDS 5y agoInteresting. Reading Mozilla’s justification it does make a lot of sense, however it is kind of unfortunate to lose something that was pretty beneficial in terms of performance because of some bad actors. It’s not really viable to maintain a whitelist of trusted libraries either, and doing so would create a whole new class of problems. Ideally CDN’s are powerful and ubiquitous enough these days that at least when you have the end user going and asking for JQuery from Cloudflare or whoever the CDN probably has a very fast location right next to them distance wise and that data should get over the wire pretty dang quickly. It’s still another performance hit though since you know at least the first time on the site they have to go and get it and if you are hosting your own stuff it might make more sense to just webpack everything together and hand it off to the CDN instead of having something like JQuery be on its own. Less overhead for opening another network request and all that.
- hardwaresofton 5y agoAn old classic worth referencing if you're wondering whether you need jQuery (or any alternatives like UmbrellaJS[0] or Cash[0]): http://youmightnotneedjquery.com/ http://youmightnotneedjquery.com/ [0]: https://umbrellajs.com/ https://umbrellajs.com/ [1]: https://github.com/fabiospampinato/cash https://github.com/fabiospampinato/cash
- rubyist5eva 5y agoI ditched this kinda manual DOM manipulation nonsense with mithril components+streams years ago and never looked back.