basket.js v0.4.0 Release Notes

Release Date: 2014-01-07 // over 10 years ago
  • The State Of LocalStorage As A Cache

    A while back, we released Basket.js - a promise-based script and resource loader for caching reasonably sized assets in LocalStorage for future loading and execution. LocalStorage caching was a technique leveraged by large sites such as GMail and Bing and continues to be used in some projects today. For example, controlled tests by Wikipedia suggested storage of their JS modules reduced page load times by an average of 156ms. It's really not quite as clear-cut as that, though.

    ๐ŸŽ LocalStorage is known to be synchronous and thus blocks the renderer main thread while the browser loads LocalStorage into memory, affecting initial page load. Although solutions like Basket.js have been leveraged due to deficiencies in the current browser story around offline (and appcache), great care does need to be taken when using them. LocalStorage isn't exactly slow for small-medium sized DBs, but is for large LocalStorage DBs. The take away here is: if you care about jank on initial load, don't use LocalStorage as a very large resource cache - it's primarily useful for smaller content.

    ๐Ÿšš Thankfully, to date there's been plenty of exciting work done on solutions like the Caching API in SeviceWorker which will help ease this pain and hopefully remove the need for libraries that try working around the HTTP cache in the future. There's also work underway to create a Node-based ServiceWorker polyfill, which should be exciting to try out.

    ๐Ÿš€ Release notes

    ๐Ÿ‘€ While we wait for ServiceWorker, the Basket.js team are working on integrating support for asynchronous storage systems like IndexedDB (see async-local-storage for an example of how this may be done) and the FileSystem API. That said, a number of new features have been introduced in 0.3.1 that might be of interest :)

    ๐Ÿ†• New features

    • ๐Ÿ‘€ Basket now supports custom handlers for resources other than JavaScript - e.g CSS, Text. See lower down for an example.
    • โœ… Scripts begin loading immediately when you call thenRequire
    • Now supports a live option for caching the result, but always fetching live. It's for use by web apps that may be offline. In the example of a Twitter client, let's say that in the morning I go fetch your tweets while online. Later on I'm on the tube and go back to get your tweets. I can't get a live version, but I can get it from the cache and show a message letting the user know that the data is not fresh.
    • ๐Ÿ‘Œ Improved project unit tests
    • ๐Ÿ‘Œ Supports RSVP 3.0.1, bumped dependencies for grunt tasks

    Some examples:

    Different types can be handled using custom handlers:

    // Add a custom handler for files of type text/plainbasket.addHandler( 'text/plain', function( obj ) {console.assert(obj.data === text, 'The text/plain handler was used');// Do some stuff..// Remove the custom handlerbasket.removeHandler( 'text/plain' );});// Requiring a text file is now possiblebasket.require({ url: '/example.txt' });
    

    live: false - nothing in the cache so we fetch from the network:

    basket.require({ url: '/example.txt', execute: false, live: false }).then( function() {// ...});
    

    live: true - attempt to fetch from the network first:

    basket.require({ url: '/example.txt', execute: false, live: true }).then( function() {// ...});
    

    Immediately loading and chaining with thenRequire:

    basket.require({ url: 'scriptA.js', key: 'first' }).thenRequire({ url: 'scriptB.js', key: 'second' }).then(function() {// first script loaded// second script loaded// scripts loaded in correct order// basket.order === 'firstsecond'});
    

    ๐Ÿš€ This release would not have been possible without all of the ace work by Mat Scales and Sindre Sorhus so big kudos to them both for their help!