Replacing jQuery (110kb) With Umbrella JS (8kb)
Also, Umbrella JS doesn't have an AJAX module. Luckily, I just wrote an API client using the
fetch() function, which will act as a stand-in for the
When converting from jQuery to Umbrella JS, the changes can be made incrementally since jQuery uses
$() as its handle and Umbrella JS uses
u() as its handle. The only constraint, really, is that you cannot use one instance inside the other. Meaning, you can't pass an Umbrella JS instance to a jQuery method - bad things will happen.
ASIDE: If you're using an ES Module based build-system, you can always
importyour libraries and rename them at the same time. As such, it doesn't really matter what jQuery and Umbrella JS use as their global references.
With that said, I wanted to put together a simple "Hello World" demo for Umbrella JS so that you can see how close the API is to jQuery. The following code isn't really doing anything meaningful - it's just authoring some Umbrella JS plugins and then calling some DOM (Document Object Model) manipulation methods:
As I mentioned above, Umbrella JS doesn't have all the convenience methods that jQuery has. But, we can easily replicate those methods through the use of Plugins. Just like jQuery, Umbrella JS works by creating - aka,
new()'ing - instances of the Umbrella class constructor. The Umbrella JS API is then defined on the
prototype object, which means that all instances of Umbrella JS can access the
prototype methods on the
this scope. Plugins - in both jQuery and Umbrella JS - then become nothing more than new methods injected into the
thisbindings works? And, how
Now, if we run this code in a modern browser, we get the following output:
As you can see, using the Umbrella JS API, we were able to add DOM elements, change the
style attributes, attach event-listeners, and change the
classList during enter/leave interactions. All while using an API that looks almost exactly like jQuery.
- jQuery only = 110(40)kb
- Both libraries = 118(42)kb
- Umbrella JS only = 10(3)kb
Because Umbrella JS is so small, including it alongside the jQuery library required a negligible increase in bundle size. But then, being able to remove jQuery once my migration was complete lead to a large reduction in bundle size. And, keep in mind that I'm still transpiling down to ES5; once I start using
type="module" on my Script tag, the code should get even smaller.
Since "plain text" content is highly compressible, the gzipped size of the different production bundles is not that huge. However, keep in mind that the uncompressed size is a good representation of how much code the browser has to compile, optimize, and execute once it's downloaded. As such, this migration to Umbrella JS should have a meaningful impact on performance, especially on resource-constrained devices.
To be honest, I did spend a little time trying to rewrite my DOM-manipulation code using native DOM methods. But, after 5-minutes, I realized that this was a silly idea. Yes, "you may not need jQuery"; but, there's a lot of things in life that make life better even if you don't need them. It turns out, high-level, fluent APIs are one of those things. And, at 2.8Kb gzipped, the whole bundle-size argument no longer has a place in the decision-making process. And so, I'm very excited to be keeping all the jQuery-value, but using the tiny Umbrella JS library.
Want to use code from this post? Check out the license.
Oh, two things that I forgot to mention in the blog post:
I could not get event-delegation to work properly in the
.on()method. Not sure if is a bug in the library; or, if I'm just not understand the documentation (they don't have much in the way of event-delegation examples).
I could not get the
u(document.createElement("script")). That seemed to work for reasons I don't understand.
In the blog post, I mentioned using
type="module"to prevent some tranpsilation. One issue that I ran into is that module scripts, apparently, must adhere to the same-origin policy for CORS (Cross-Origin Resource Sharing). And, since my scripts are served up from a different (CDN) domain, the CORS security will block it with the current settings. As such, I'm sticking with
browserslistsetting is really what is preventing the tranpiling of code back to ES5.
I wrote a quick follow-up post that talks about jQuery function parity more in-depth:
Basically, these are the Umbrella JS plugins that I wrote to make my existing jQuery-oriented code easier to adapt to Umbrella JS by filling in some of the feature-gap parity.
I tried to run your demo, but nothing worked on mobile, I won't be using it as most of people needs this working for mobile devices, jQuery is big, but works.
Yo be honest your whole website isn't mobile friendly, I am writing this down needing to move to the sides instead of seeing what I am writing, maybe those tips that you do must be tested before you say that is the best thing ever.
Well, you do have an option to build jQuery and get a smaller package. Althought you did present an interesting alternative...
Yeah, my site definitely needs to be more mobile-friendly. This site is really old - it actually predates the notion of being able to view web content on a mobile device. I've been slowly trying to make it more mobile friend - if you think it's bad now you should have seen it a few years ago. Something like 97% of all my traffic comes from desktop devices, so I've been a bit lazy about prioritizing it.
That said, none of the mobile issues should be related to jQuery or my conversion that Umbrella. All those issues should be CSS-related. But, I am surprised that the demo didn't work. Can I ask what browser you are using? I just tried on iOS Safari and iOS Chrome (which I think both just use the same web engine under the hood) and the demo works (you can tell because the text turns pink).
Oh, I didn't know that. I vaguely remember that you could do that with jQuery UI - where you didn't have to include all the various UI widgetry; but, I didn't know something like that was also available for the core library. Good tip.
I am not one of them...but senion developers can even manipulate library line by line. On the other hand, if looking at average web page today, one 35kb gzip-ed library is only a drop in a see. Since open source dominates the market, all JS and CSS are totaly overbloated. Hhahaha this week I ran into a webpage which loads more than 50 font files, but only 2 or 3 were used🤣
Ha ha, it's definitely a "death by a 1,000 cuts" issue on the web today. Right now, I am just trying to make small, incremental changes to try and improve things. No one change is enough; but, hopefully after many, many changes, things will start to get better 💪
You have a mistake:
It probably should be (3)kb.
Excellent catch! Thank you for that - the post has been updated.
Interertins, but I need jQuery because of its plugins. for example mask, jQueryUI and so on. Clear jQuery is not interesting.
Yeah, it's not exactly a drop-in replacement. So, if you have a lot of plugins, it can be a challenge to upgrade. It's also not easy to mix-and-match Umbrella JS objects with jQuery objects since they have different internal mechanisms.
To be clear, I don't dislike jQuery at all. In fact, I still think jQuery is awesome, which is why I'm not trying to replace anything with "vanilla JS". There's a tremendous amount of value to be gotten out of these simple, fluent APIs.
So, don't feel like there's pressure to change. The only pressure is to provide value for your users. And if you're doing that, then you're doing the right thing 💪
I found this post whilst searching for reasons my umbrellajs event delegation wasn't working. Turns out they have just released an update to fix it as it was a bug in their code.
As for the script tag issue, I also had the same problem. After Googling for a while, I stumbled across this website (not my own) which explained that script tags appended to the DOM get executed by browsers, whereas if they are injected through innerHTML they are not. I don't know the reasoning, but it's a "thing" apparently! https://eager.io/blog/everything-I-know-about-the-script-tag/
Yeah, I was talking to Francisco Presencia on Twitter - it sounds like the event-delegation code was a user-submission (not his code), so he didn't know that that part was broken. But, every time I mention something, he seems to turn around and fix it 🤩💪
Thanks for the script-tag link -- I'll take a look.
jQuery's html() method actually attaches any scripts in the markup you pass it for you, getting around the innerHTML issue.
This is also the case for dabby.js, a lightweight ES6 jQuery clone, which at full build weighs in at 18(6)kb.
Very interesting - it's neat how you broke out all of the individual methods. Kind of like how Lodash refactored all of its architecture to allow for individual
importcalls. Classy approach 👍
Thanks for taking the time to look at it. Appreciated.
https://github.com/fabiospampinato/cash is another good option for this sort of thing too.
If memory serve me, I think Cash was in the running of libraries that I was going to pick when replacing jQuery. Thanks for linking to it - always good to provide options.
I know this is an older post, but I saw Umbrella mentioned from your latest Hotwire post. Decided to look into it. Seemed awesome (smaller size, equivalent functionality, etc.) until I started Google "vs" results. Ending up coming across some other variations like Cash and Zepto.
Found a speed comparison... and each time I'd run one, Umbrella came out the slowest. Granted, no one is doing 4.x million selectors, but thought I'd pass it your way:
(Can run yourself or jump to "latest run", which I did about 10 minutes ago as of this comment.)
When I was looking for a jQuery alternative, I did look at some of the other ones you mentioned. I don't remember all the details; but, I think it came down to a cross between developer ergonomics and how much it would take to make the transition. Umbrella JS felt like the sweet spot from that perspective.
I think part of it, too, was that the Umbrella JS site itself was just nice, and it felt like it would be easier to reference and learn from. At the end of the day, I think I just had to pick something, and this felt like a good option.
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →