Not built with jQuery

Not built with jQuery

The first time I used jQuery on a website was June 2007; I used it for an image carousel that faded between sponsor logos. During the rest of 2007 and 2008 I used jQuery, MooTools and Prototype.js until settling on jQuery for everything in 2009. And I’ve been using jQuery on every site since. Until now.

I just finished working on a small site that doesn’t use jQuery or any JavaScript library at all. I’ve been wanting to do this for a while, inspired by Remy Sharp’s article “I know jQuery, now what?” and through a desire to cut out those 34-80 extra kb of downloads on mobile connections.

It turned out to be quite a fun exercise.

The site was a one page parallax scrolling marketing page that isn’t heavy on JavaScript; but it was a good way to get my feet wet. I assumed I’d have to think more about the JavaScript I was writing to do the things that jQuery made so easy for me and I had a concern that I’d be put off doing something just because the convenience had gone. And in practice, this just wasn’t the case.

Initially I wrote the JS with jQuery as I would normally because it’s become natural and it’s fast. And I used a couple of plugins; my favorite jQuery plugin, jquery.ba-throttle-debounce and a plugin to type text, typed.js.

First step was to write out those plugins with native JavaScript. Any FE devs who have worked with me know that I don’t like jQuery plugins. Often they don’t quite do what you want them to do or you end up being limited by the plugin functionality. I prefer to write my own and then I know what they do and can add new features as needed. I tend to only use plugins that do one simple thing that is boring to write myself or plugins that do something thats incredibly complex or time consuming to write and test myself, for example: Matteo Spinelli’s iScroll plugin.

I was using jquery.ba-throttle-debounce to fire a custom resize event when the browser had stopped being resized. Something like:


$(window).on("resize",$.debounce(250,function(){
  $.event.trigger({
    type: "browser_resized"
  });
}));

Which, without that plugin and without jQuery, you can rewrite as:


var resize_timer;
window.addEventListener('resize', function(event){
  clearTimeout(resize_timer);
  resize_timer = setTimeout(function(){
    if (window.CustomEvent) {
      var event = new CustomEvent("resized", {detail: {}});
    } else {
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent("resized", true, true, {});
    }
    document.dispatchEvent(event);
  },250);
});

OK so a few more lines than before, but nothing major. Essentially each resize event clears the timeout and so stops the function in the timeout from running. When the browser is no longer being resized, the function is allowed to run 250 milliseconds later. The function then sets up and event and dispatches it. All stuff I read on You Might Not Need jQuery and all done in the same time it would have taken me to look those things up on the jQuery API docs.

As for writing out typed.js; all I needed was basic typing, no backspacing, no multiple sentences and I wanted my effect to be faster than what the plugin allowed. So I wrote a quick helper:


a17.Helpers.typewrite = function(el,text) {

  var text_array_length = text.split("").length,
      current_char = 0;

  function typechar() {
    current_char++;
    el.textContent = text.substring(0,current_char);
    if (current_char < text_array_length) {
      setTimeout(function(){
        typechar();
      },(randomNum(30,70)));
    }
  }

  function randomNum(min,max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  typechar();

};

Into it you pass a DOM node, found using querySelectorAll in my case, and a sentence to type out. Every 30-70 milliseconds it adds a new character to the element by updating the textContent. The range of 30-70 was to give a more natural feeling to when the characters appear rather than a uniform speed, as no one types at a uniform speed (an idea stolenborrowed from the source code of typed.js).

After the plugins I took to looking at the rest of my JavaScript, which was concerned with triggering functions and adding classes when the browser was at certain scroll positions. Again You Might Not Need jQuery to the rescue. Some quick updates to a bunch of $(".foo").addClass("bar"); to be el.classList.add("bar"); and write some quick helpers to replace jQuery’s offset() function and make sure I didn’t use any each instead of for loops.

And the file size savings?

Uncompressed JavaScript, with jQuery and plugins: 201kb
Compressed JavaScript, with jQuery and plugins: 118kb
Compressed and gzipped JavaScript, with jQuery and plugins: 40kb

And then after re-writing to remove jQuery:
Uncompressed JavaScript: 48kb
Compressed JavaScript: 23kb
Compressed and gzipped JavaScript: 7kb

Some massive drops in filesize. Also, gzip is clearly brilliant and magical in the way it works. These reduction in sizes could very well be the difference between a mobile user on a cellular connection using the site or getting bored waiting for it to load and leaving it. It may even be small enough to include inline in the page at the bottom and not have that extra HTTP request.

One problem with the way I did this was my brain was always thinking: “how do I do this jQuery thing without jQuery”. Over the last 8 years the jQuery API has become pretty ingrained in my mind; but I’m hoping its a habit I can break and instead start to memorise proper JavaScript functions as I have jQuery ones. My next JavaScript fiddles without jQuery will be to re-write the slider JavaScript that I’ve used on countless AREA 17 projects over the years, which I originally ported from a MooTools version written for AOL’s Asylum blog in 2007.

I’m quite looking forward to it.