├── 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 | | Loading jQuery from CDN |
36 | 268ms |
37 |
38 |
39 | | Loading jQuery from localStorage |
40 | 47ms |
41 |
42 |
43 |
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 |
--------------------------------------------------------------------------------