├── example.js ├── cached-webpgr.min.js ├── index.html ├── README.md └── cached-webpgr.js /example.js: -------------------------------------------------------------------------------- 1 | var t2 = new Date(); 2 | console.log('## load complete: ' + (t2 - t1) + 'ms'); 3 | console.log('## jQuery: '+$); -------------------------------------------------------------------------------- /cached-webpgr.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * cached-webpgr.js - simple localStorage based caching of JavaScript files 3 | * https://github.com/webpgr/cached-webpgr.js 4 | * Author: Webpgr http://webpgr.com by Falko Krause 5 | * License: MIT 6 | */ 7 | function _cacheScript(c,a,b){var d=new XMLHttpRequest();d.onreadystatechange=function(){if(d.readyState==4){if(d.status==200){localStorage.setItem(c,JSON.stringify({content:d.responseText,version:a}))}else{console.warn("error loading "+b)}}};d.open("GET",b,true);d.send()}function _loadScript(c,b,a,e){var d=document.createElement("script");if(d.readyState){d.onreadystatechange=function(){if(d.readyState=="loaded"||d.readyState=="complete"){d.onreadystatechange=null;_cacheScript(b,a,c);if(e){e()}}}}else{d.onload=function(){_cacheScript(b,a,c);if(e){e()}}}d.setAttribute("src",c);document.getElementsByTagName("head")[0].appendChild(d)}function _injectScript(g,e,d,b,i){var h=JSON.parse(g);if(h.version!=b){localStorage.removeItem(d);_loadScript(e,d,b,i);return}var f=document.createElement("script");f.type="text/javascript";var a=document.createTextNode(h.content);f.appendChild(a);document.getElementsByTagName("head")[0].appendChild(f);if(i){i()}}function requireScript(d,a,b,f){var e=localStorage.getItem(d);if(e==null){_loadScript(b,d,a,f)}else{_injectScript(e,b,d,a,f)}}; 8 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 26 | 27 | 28 |

localStorage Script Caching Demo

29 |

This code demonstrates how to use the localStorage to cache and JavaScrip files.
30 | Cached files will be loaded much faster than scripts from any server (even local ones).
31 | My test showed: 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
Loading jQuery from CDN268ms
Loading jQuery from localStorage47ms
44 |
45 | 46 | This demo will only work on a server, file:// is not supported. 47 | 48 |

49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Synopsis 2 | 3 | This tiny library uses the Web Storage (localStorage) to cache JavaScrip files. Cached files will be loaded much faster than requesting them from a server (even local ones).
4 | My test showed: 5 | 6 | | | Chrome | FireFox | 7 | |---|---|---| 8 | |Loading jQuery from CDN | __268ms__| __200ms__| 9 | |Loading jQuery from localStorage | __47ms__ | __14ms__| 10 | 11 | The library is so simple that you can read and understand all of its code! 12 | 13 | ## Code Example 14 | 15 | ```javascript 16 | requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){ 17 | requireScript('examplejs', '0.0.3', 'example.js'); 18 | }); 19 | ``` 20 | In this example I cache jQuery and a local file that is dependent on jQuery. On the first load it will be loaded from the provided URL and on the second load it will be loaded from the localStorage. Changing the version string will cause the cache to be cleared and re-loaded from the sever. Since the `example.js` is dependen on jQuery I load it in the callback that is triggered after loading jQuery. 21 | 22 | 23 | ## Motivation 24 | 25 | My feeling was that caching in localStorage should be a simple and straight forward. However I could not find a simple library without depencies that fulfilled this so I created this mini project, for documentation and learning. 26 | 27 | When I tried to use [basket.js](http://addyosmani.github.io/basket.js/) it unfortunately had some dependency, otherwise it is probabley more advanced (and larger) than this script. 28 | 29 | ## Installation 30 | 31 | Copy the code from `chached-webpgr.min.js` into your .html file (loading it from a server would make it slower!) and use the code from the [Code Example](#code-example) to load your scripts. Be aware of depencies, and use the callbacks for dependent scripts like in the example. 32 | 33 | This code __will only work on a server__, file:// is not supported. 34 | 35 | Caching of scripts cross domain only works if the CORS header is set on the remote server. 36 | 37 | 38 | ## API Reference 39 | 40 | ```javascript 41 | requireScript(name, version, url, callback) 42 | ``` 43 | provides the external API. The internal API consits of 3 functions. 44 | ```javascript 45 | _loadScript(url, name, version, callback) 46 | _injectScript(content, name, version, callback) 47 | _cacheScript(name, version, url) 48 | ``` 49 | Please read the code to learn how they work (they are very short!). 50 | 51 | ## License 52 | 53 | cached-webpgr.js is released under the [MIT License](http://webpgr.mit-license.org/). 54 | -------------------------------------------------------------------------------- /cached-webpgr.js: -------------------------------------------------------------------------------- 1 | /* 2 | * cached-webpgr.js - simple localStorage based caching of JavaScript files 3 | * https://github.com/webpgr/cached-webpgr.js 4 | * Author: Webpgr http://webpgr.com by Falko Krause 5 | * License: MIT 6 | * 7 | * usage example: 8 | * ``` 9 | * requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){ 10 | * requireScript('examplejs', '0.0.3', 'example.js'); 11 | * }); 12 | * ``` 13 | */ 14 | 15 | 16 | /** 17 | * ##_cacheScript 18 | * This function requires IE7+, Firefox, Chrome, Opera, Safari. 19 | * It will make an ajax call to retrive the desired script from the provided url and store it 20 | * in the localStorage under the provided name. The stored script will be wrapped like in this example: 21 | * `{content: '// scrip content $(document).ready(...)', version: '1.02.03'}` 22 | * @param {string} name localStorage identifier; shoud be the same as on the server-side 23 | * @param {string} url `path/to/script.js`; shoud be on the same server (or with remove with CORS header access-control-allow-origin:*) 24 | */ 25 | function _cacheScript(name, version, url) { 26 | var xmlhttp = new XMLHttpRequest(); // code for IE7+, Firefox, Chrome, Opera, Safari 27 | xmlhttp.onreadystatechange = function() { 28 | if (xmlhttp.readyState == 4) { 29 | if (xmlhttp.status == 200) { 30 | localStorage.setItem(name, JSON.stringify({ 31 | content: xmlhttp.responseText, 32 | version: version 33 | })); 34 | } else { 35 | console.warn('error loading '+url); 36 | } 37 | } 38 | } 39 | xmlhttp.open("GET", url, true); 40 | xmlhttp.send(); 41 | } 42 | /** 43 | * ##_loadScript 44 | * For loading external scripts (local or cross domain with CORS) 45 | * @param {string} url (see `requireScript`) 46 | * @param {string} name (see `requireScript`) 47 | * @param {string} version (see `requireScript`) 48 | * @param {Function} callback (see `requireScript`) 49 | */ 50 | function _loadScript(url, name, version, callback) { 51 | var s = document.createElement('script'); 52 | 53 | if (s.readyState) { //IE 54 | s.onreadystatechange = function() { 55 | if (s.readyState == "loaded" || s.readyState == "complete") { 56 | s.onreadystatechange = null; 57 | _cacheScript(name, version, url); 58 | if (callback) callback(); 59 | } 60 | }; 61 | } else { //Others 62 | s.onload = function() { 63 | _cacheScript(name, version, url); 64 | if (callback) callback(); 65 | }; 66 | } 67 | 68 | s.setAttribute("src", url); 69 | document.getElementsByTagName("head")[0].appendChild(s) 70 | } 71 | 72 | /** 73 | * ##_injectScript 74 | * Injects a script loaded from localStorage into the DOM. 75 | * If the script version is differnt than the requested one, the localStorage key is cleared and a new version will be loaded next time. 76 | * @param {object} content wrapped serialized code `{content: '// scrip content $(document).ready(...)', version: '1.02.03'}` 77 | * @param {string} name (see `requireScript`) 78 | * @param {string} version (see `requireScript`) 79 | * @param {Function} callback (see `requireScript`) 80 | */ 81 | function _injectScript(content, url, name, version, callback) { 82 | var c = JSON.parse(content); 83 | // cached version is not the request version, clear the cache, this will trigger a reload next time 84 | if (c.version != version) { 85 | localStorage.removeItem(name); 86 | _loadScript(url, name, version, callback); 87 | return; 88 | } 89 | var s = document.createElement('script'); 90 | s.type = "text/javascript"; 91 | var scriptContent = document.createTextNode(c.content); 92 | s.appendChild(scriptContent); 93 | document.getElementsByTagName("head")[0].appendChild(s); 94 | if (callback) callback(); 95 | } 96 | 97 | /** 98 | * ##requireScript 99 | * If the requested script is not available in the localStorage it will be loaded from the provided url (see `_loadScript`). 100 | * If the script is present in the localStorage it will be injected (see `_injectScript`) into the DOM. 101 | * @param {string} name identifier of the script in the local cache 102 | * @param {string} version version string that is used to check if the script needs to be updated 103 | * @param {string} url `path/to/script.js` that should be caced; can be local (or cross domain with CORS header allowing cross domain access) 104 | * @param {Function} callback function that is extecuted once the script is loaded 105 | */ 106 | function requireScript(name, version, url, callback) { 107 | var c = localStorage.getItem(name); 108 | if (c == null) { 109 | _loadScript(url, name, version, callback); 110 | } else { 111 | _injectScript(c, url, name, version, callback); 112 | } 113 | } 114 | --------------------------------------------------------------------------------