A script and resource loader for caching & loading files with localStorage

Related tags

Storage basket.js
Overview

basket.js logo

Basket.js is a script and resource loader for caching and loading scripts using localStorage

##Introduction for the Non-Developer

Modern web applications will typically make use of more than one JavaScript or CSS framework. As the number of scripts add up, so does the number of HTTP requests. This leads to increased page load times and reduced performance. Basket.js is a project dedicated to aleviating this problem.

Basket.js loads your site's scripts into a page and saves them in localStorage so they can be reused after the session until they are expired. It also checks to see if the scripts are already in localStorage, and if not, loads them. This prevents unneccessary reloading of scripts and can improve load time and website performance.

Build Status

Resources

Examples

Articles

Contribute

Style Guide

This project follows the Idiomatic guide to writing JavaScript - a concise extension to the jQuery Core Style guidelines, with the exception of multiple var statements. Please ensure any pull requests follow these closely.

Unit Tests

We are also attempting to get as much unit test coverage as possible. For this reason, please add unit tests for any new or changed functionality and remember to lint and test your code using grunt.

Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!

Building

To build the project, you will first need to install the necessary dependencies (such as RSVP) using npm and Bower.

Run:

$ npm install & bower install

in the project root to get everything you need. Next, to actually build the project you will need Grunt.

Run:

$ grunt release

to generate a new release, otherwise just running grunt test will run the unit tests.

Team

Addy Osmani avatar Sindre Sorhus avatar Andrée Hansson avatar Mat Scales avatar
Addy Osmani Sindre Sorhus Andrée Hansson Mat Scales

License

MIT © Basket.js team

Comments
  • Perf tests

    Perf tests

    We need some perf tests. It's hard to accurately measure the performance, so we'll need to discuss how to best approach this.

    I've compiled a list with some existing localStorage jsPerf tests we can use as inspiration:

    • localStorage key size diff http://jsperf.com/localstorage-read-write-test/3
    • localStorage vs direct object access http://jsperf.com/localstorage-vs-objects/16
    • localStorage vs IndexedDB http://jsperf.com/indexeddb-vs-localstorage/2
    • localStorage getItem / setItem vs getter / setter http://jsperf.com/localstorage-getitem-setitem-vs-getter-setter

    I've noticed localStorage in Safari 5 is about 240x faster than in Chrome 17. It seems like they're doing something right. Anyone why that is?

    Not surprising, it's exponentially slower to access big data.

    Also, it looks like IndexedDB is way slower than localStorage. Though the jsPerf might be biased. We should create our own to confirm.

    Related

    https://plus.google.com/117281036949330216542/posts/PM51anxWXSA

    enhancement 
    opened by sindresorhus 42
  • Multiple files in .require()

    Multiple files in .require()

    So, me and Sindre discussed the possibility of pulling in several files within one .require(). It would look something like this:

    basket.require({
        "foo-1.2.3.js": {
          key: "foo"
        },
        "bar-3.2.1.js": {
          key: "bar",
          overwrite: true
        }
      })
      .wait(function() {
        // use pulled-in files
      });
    
    enhancement 
    opened by peol 23
  • Support TTL (Time To Live) option

    Support TTL (Time To Live) option

    We talked about adding this, should we? It would be a nice addition perhaps. Syntax:

    basket.add('foo-1.2.3.js', { key: 'foo', ttl: '1months' });
    

    months in the string could be minutes, hours, days, weeks, years as well. Too advanced?

    EDIT:

    Implementation should be hours-only values:

    basket.add('foo-1.2.3.s', {
      ttl: 24 * 7 // 1 week
    });
    
    enhancement 
    opened by peol 18
  • Doesn't handle 404 errors

    Doesn't handle 404 errors

    If file is not found basket.js saves the 404 message in localStorage. Try something like

    basket.require('doesntexist123.js');
    

    I would assume the same problem exists with other errors, like 403 etc, too.

    bug 
    opened by apaatsio 13
  • Code cleanup

    Code cleanup

    Fixed all the mixed tabs/space and code style inconsistencies. Sorry, just had too, otherwise I'll go insane.

    Also added a grunt task for creating a release. You only run this before tagging a release. This way you only generate files in the dist folder on a release, and don't dirty up every commit.

    Just run grunt to lint and test when you develop, and run grunt release to create release versions in the dist folder.

    opened by sindresorhus 13
  • Promises reinvented

    Promises reinvented

    The .wait() method appears to do a very similar job to the .then() method on a Promises/A promise. Perhaps basket should use Promises/A compatible promises rather than a similar-but-different alternative?

    opened by wibblymat 12
  • Support file-versioning (new option: version)

    Support file-versioning (new option: version)

    It would be great if we could force update of a specific key automatically by specifying the version:

    basket.add('foo.min.js', { key: 'foo', version: '1.0' });
    
    // would do nothing since we already stored foo
    basket.add('foo.min.js', { key: 'foo' });
    
    // we updated the version, let's update localStorage as well
    basket.add('foo.min.js', { key: 'foo', version: '1.1' });
    

    Is this overkill? It's somewhat like overwrite, but we'll only do it once the version is updated.

    enhancement 
    opened by peol 10
  • Require queue method

    Require queue method

    I'd like to add a require queue method. ( i.e. A file could be fetched only after previous file ).

    basket.requireQueue({url:'jquery.js'}, {url:'jquery.plugin.js'}).then...
    

    It make sense for most of my use cases. Instead:

    basket
      .require({url:'jquery.js'})
      .then(function(){
        basket
          .require({url:'jquery.plugin.js'}, {url:'jquery.effects.js'})
          .then(function(){
            basket.require({url:'mycode.js'});
        });
      });
    

    Make sense?

    opened by felipemorais 9
  • Rename add()?

    Rename add()?

    I'd suggest load() or require() is more appropriate, since that's what the programmer is trying to achieve. That it's add()ed to the cache is the magic this library is making invisible.

    /nitpick

    opened by mahemoff 9
  • Add fallback URL functionality

    Add fallback URL functionality

    This change allows an array of URLs to be passed for a script, where if the first URL fails the loader will try the next, and so on, similar to the Require.js feature. I noticed that on the Basket.js homepage it says that only same-origin URIs are supported, but the XHR approach will work fine with modern browsers and most CDNs allow an Access-Control-Allow-Origin wildcard, so I think this adds value.

    opened by markrendle 8
  • Handle resources other than JavaScript

    Handle resources other than JavaScript

    Work in progress. Don't merge yet.

    This doesn't quite close #77 because I didn't implement the live parameter that I describe in the doc. It also doesn't fix #76 or #60 because there is no example CSS handler or any documentation.

    I think this is the meat of the implementation though, so please sanity check the work so far.

    opened by wibblymat 8
  • alternatives to basket.js?

    alternatives to basket.js?

    Really grateful to the author for creating the library, but it hasn't been updated for a while, and there are some annoying bugs like these

    https://github.com/addyosmani/basket.js/issues/173 https://github.com/addyosmani/basket.js/issues/174

    So might be interesting to accumulate the alternatives people can use instead. Some of things I considered:

    • https://github.com/nodeca/bag.js#readme
    • relying on HTTP layer and Cache-Control headers https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#max-stale e.g. I ended up doing that in my project if anyone is interested: https://github.com/karlicoss/promnesia/commit/8bfba57dcfa0100f7c2636050ff5becf4e2112f0#diff-df49073ced8032d2d3858709fc0880bfb37cc4b816456302fd252afcc2241d11R295

    related issue: https://github.com/addyosmani/basket.js/issues/89

    opened by karlicoss 0
  • Most scripts not stored in localstorage

    Most scripts not stored in localstorage

    I implemented this loader and for some reason it's not working.

    I loop through all the dozens of scripts I need, pass each one to basket.require, and they all get added to the dom.

    When I check the localstorage for my localhost, I only saw 3 scripts stored. Has anyone had this happen?

    opened by miller-kevin 0
  • browser compatibility, local forage, and size limit

    browser compatibility, local forage, and size limit

    is it OK to assume that if local storage (eg. in Opera mini) is not supported then it'll automatically fallback to network with caching.

    what happens when localstorage's capacity is reached?

    If it has to hit the server for a file, would it allow cached files? See https://api.jquery.com/jquery.getscript/ for example.

    Any plans to make it compatible with libraries like Localforage to support other storage types (if local storage is full etc)?

    opened by peacemakr 0
Releases(v0.5.2)
  • v0.5.2(Feb 7, 2015)

  • v0.5.0(Jul 8, 2014)

    This is a minor release where a number of dependencies have been updated. New additions to the Basket.js API include skipCache, which prevents storing scipts in cache. The feature can be useful when you want load scripts in order, but only cache some. Here's an example:

    basket.require(
        { url: 'require.js' },
        { url: 'require.config.js', skipCache: true },
        { url: 'libs.js' }
    );
    

    In the above, multiple scripts will be requested and then cached however require.config.js will not be cached in localStorage.

    Special thanks go to @sindresorhus @itsuryev and @wibblymat for their help with this release.

    For the complete changelog see: https://github.com/addyosmani/basket.js/compare/v0.4.0...v0.5.0

    As per our last release, we continue to look forward to the ServiceWorker Cache API eventually being more useful for some of our use-cases. A very early Cache API polyfill was demonstrated working as part of the Polymer Topeka app at Google I/O and we look forward to exploring async solutions using IndexedDB as a backing store in the future.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jan 7, 2014)

    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/plain
    basket.addHandler( 'text/plain', function( obj ) {
        console.assert(obj.data === text, 'The text/plain handler was used');
        // Do some stuff..
        // Remove the custom handler
        basket.removeHandler( 'text/plain' );
    });
    
    // Requiring a text file is now possible
    basket.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!

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1-pre.1(Jan 5, 2014)

Owner
Addy Osmani
Engineering Manager at Google working on Chrome & Web Platform
Addy Osmani
Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with Schema and data validator.

Client Web Storage Browser storage interface for IndexedDB, WebSQL, LocalStorage, and in memory data with basic Schema and data validation. Installati

Before Semicolon 19 Sep 30, 2022
localStorage and sessionStorage done right for AngularJS.

ngStorage An AngularJS module that makes Web Storage working in the Angular Way. Contains two services: $localStorage and $sessionStorage. Differences

G. Kay Lee 2.3k Nov 26, 2022
:lock: Secure localStorage data with high level of encryption and data compression

secure-ls Secure localStorage data with high level of encryption and data compression. LIVE DEMO Features Secure data with various types of encryption

Varun Malhotra 602 Nov 30, 2022
Expirable data storage based on localStorage and sessionStorage.

Expirable storage About The Project Expirable data storage based on localStorage and sessionStorage. Getting Started To get a local copy up and runnin

Wayfair Tech – Incubator 5 Oct 31, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 4, 2023
Vue.js localStorage plugin with types support

VueLocalStorage LocalStorage plugin inspired by Vue typed props which take a care of typecasting for Vue.js 1 and 2 with SSR support. Install npm inst

Alexander Avakov 669 Nov 29, 2022
💾 Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful API.

localForage localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asyn

localForage 21.5k Jan 1, 2023
Simple window.localStorage, with type safety

mini-local-storage simple window.localStorage, with type safety example // localStorage.ts import { createLocalStorage } from "mini-local-storage";

Kipras Melnikovas 4 Jan 8, 2023
This is an upload script which allows you to upload to web3 storage using JS.

This is an upload script which allows you to upload to web3 storage using JS. first make sure to run npm install on the directory run script using nod

null 1 Dec 24, 2021
local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

react-native-storage This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, pr

Sunny Luo 2.9k Dec 16, 2022
A lightweight vanilla ES6 cookies and local storage JavaScript library

?? CrumbsJS ?? A lightweight, intuitive, vanilla ES6 fueled JS cookie and local storage library. Quick Start Adding a single cookie or a local storage

null 233 Dec 13, 2022
Load and save cookies within your React application

react-cookie Universal cookies for React universal-cookie Universal cookies for JavaScript universal-cookie-express Hook cookies get/set on Express fo

Reactive Stack 2.4k Dec 30, 2022
A enhanced web storage with env support, expire time control, change callback and LRU storage clear strategy.

enhanced-web-storage A enhanced web storage with env support, expire time control, change callback and LRU storage clear strategy. How to Start import

Ziwen Mei 15 Sep 10, 2021
The perfect combination: local business shopping and crypto.

The perfect combination: local business shopping and crypto. Get passive income and support local businesses.

Mauricio Figueiredo 4 Mar 19, 2022
A javascript based module to access and perform operations on Linode object storage via code.

Linode Object Storage JS Module A javascript based module to access and perform operations on Linode object storage via code. Code Guardian Installing

Core.ai 3 Jan 11, 2022
Store your data in the world's fastest and most secure storage, powered by the blockchain technology⚡️

Store your data in the world's fastest and most secure storage, powered by the blockchain technology.

BlockDB 3 Mar 5, 2022
Cache is easy to use data caching Node.js package. It supports Memcached, Redis, and In-Memory caching engines.

Cache Cache NPM implements wrapper over multiple caching engines - Memcached, Redis and In-memory (use with single threaded process in development mod

PLG Works 49 Oct 24, 2022
Satyam Sharma 3 Jul 8, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022