Basket.js: achieve lightning fast performance for website

Swarnendu De June 12, 2015

basket

Recently I was developing a web application for a client. All was going well in development till it moved  to production, where I had to face a new problem that lead to many a sleepless night.

The end-users for our application were mostly from India. You might be aware of the fact that over 85% of the Indian population is plagued by slow internet issues. Because of this people were unable to load the app and this turned into a major issue.

When I searched the internet on the topic, I found that Google and Bing are using localStorage extensively for storing the SCRIPTS for subsequent pageviews. Being curious as a  developer, I tried to find whether Google and Bing are using something unique to achieve the performance benchmark? This is where I was introduced to the basket.js project by Addy Osmani.

Basket.js is a small javascript library which provides caching of scripts in localStorage.

How is it going to improve the performance?

Every time your browser loads a specific page, it loads all the script files linked to it. Let’s say a visitor opens/ refreshes your website 20 times a day and has to wait for the scripts to load every time, before he can actually perform a desired action.

“So what can we do to improve the performance?”

Now think of the possibility to save the scripts locally when the user visits the page for the first time. This will enable the page to check for local availability of the scripts, when the user re-visits the website and if the scripts are not found they will simply be loaded from the server.

Basket.js checks if the script(s) have previously been saved locally in browser’s localStorage. If so then they will simply be loaded and injected into the current document. If not, they will be loaded via XHR, but cached so that no additional script loads are required in the future.

Why not IndexedDB or Browser Cache but localStorage?

You must be wondering why Basket.js is using localStorage instead of the browser cache or IndexedDB as both the latter are well popular, right? Let me present some test statistics in front of you:

  • Google and Bing have replicated many tests to show us that there are performance benefits to caching assets in localStorage (especially on mobile) when compared to simply reading and writing from the standard browser cache. Read the article here. We found this comparison graph after testing on some mobile deviceschart (1)
  • Jens Arps has shown that currently IndexedDB is significantly slower than localStorage for reading and writing assets according to this statistic.
  • Other developers who are working to achieve a significant performance benchmark for web and mobile browser also agreed that localStorage works just fine for caching data compared to browser cache

How to integrate Basket.js with your existing project?

It’s very easy to integrate  Basket.js with your existing project. Just follow these steps:

Step 1: Include the basket.js library script in your <head> tag :

<script type="text/javascript" src="lib/basket.full.min-0.0.3.js"></script>

Step 2: Require your app files using BasketJs’s  require  api:

//require jquery
basket.require({
           url: "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js",
           key: 'jquery'
       })

 

Step 3: Use the promise provided by Basket.js api to order dependencies:

basket
       .require({
           url: "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js",
           key: 'jquery'
       })
       .then(function() {
           //success! jquery is loaded you can load dependent scripts now
           basket.require({
              url:"https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js",
              key: 'jquery-ui'
           })
       }, function() {
           //error! jquery is not loaded
       })

The  require  api returns a ‘promise’ which you can use to manage the dependency among scripts. Here jquery-ui is dependent on jquery so we put that inside success callback of the promise. You can pass two parameters as promise callback: first one is success and second one error callback.

Step 3:  Set the  expire  or the  unique  property to determine whether to load cached or fresh version of the scripts:

You can set the expiry for your scripts by setting the  expire  property by number of hours, after which the cached file will be considered as invalid item.

//require jquery
basket.require({
           url: "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js",
           key: 'jquery',
           expire: 1 //number of hours after which it is expired
       })

You can also set the  unique  property which will be used to determine the invalid state of the cached scripts. If the unique value is different than previous then it will load a fresh version else loads the cached version.

//require jquery
basket.require({
           url: "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js",
           key: 'jquery',
           unique: 'v1.0' //your app version which is used to determine the validity.
       })

You can use your application’s version text as unique so that when a new version arrives it automatically loads the new scripts.

Thanks to Addy Osmani for this project which helped me to achieve the desired performance benchmark. check out his project page.

[button id=”exmple_git” class=”btn-primary” link=”https://github.com/rajubera/basketjs-example” linking=”default” size=”medium” type=”” title=”Download the demo project from here” bg_color=”#2077bb”]Download demo project[/button]

Thanks for reading. Hope this article helps you to improve the performance for your website or web application. Do comment below to let me know your feedback.