Last active
August 12, 2016 11:36
-
-
Save Munawwar/29e7c9f9c6613a4f041588cb8808d7c6 to your computer and use it in GitHub Desktop.
SystemJS LESS transpiling & caching plugin (uses IndexedDB, which is cleared after each session).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global Promise, console*/ | |
/** | |
* Usage: | |
* Promise.all([ | |
* System.import('./systemjs-less-cacher.js'), | |
* System.import('./less.js') | |
* ]).then(function (values) { | |
* var lessCacher = values[0], | |
* less_browser = values[1], | |
* url = 'localhost/some.less', | |
* lessCode = 'html {height: 100%}'; | |
* lessCacher(url, lessCode, less_browser, function (err, css) { | |
* //use css here | |
* }); | |
* }) | |
*/ | |
module.exports = new Promise(function initialize(resolve) { | |
var dummy = function (url, less, less_browser, callback) { | |
callback(null, null); | |
}; | |
if (!window.indexedDB) { | |
return resolve(dummy); | |
} | |
var db; | |
var Module = { | |
_cache: {}, | |
init: function () { | |
return (new Promise(function (resolve, reject) { | |
//First time init | |
if (!window.sessionStorage.getItem('systemjs-less-cacher')) { | |
// Create an objectStore for this database | |
var objectStore = db.createObjectStore("less", { keyPath: "key" }); | |
objectStore.transaction.oncomplete = function () { | |
window.sessionStorage.setItem('systemjs-less-cacher', 'true'); | |
resolve(Module); | |
}; | |
objectStore.transaction.onerror = function(event) { | |
console.error(event); | |
resolve(dummy); | |
}; | |
} else { | |
var start = Date.now(); | |
var request = db.transaction(["less"], "readwrite").objectStore("less").get('cache'); | |
request.onerror = function(event) { | |
reject(event); | |
}; | |
request.onsuccess = function() { | |
Module._cache = request.result ? request.result.data : {}; | |
console.log(Date.now() - start); | |
resolve(Module); | |
}; | |
} | |
})); | |
}, | |
saveTimer: null, | |
/*Persist cache to db*/ | |
save: function () { | |
var transaction = db.transaction(["less"], "readwrite"); | |
transaction.objectStore("less").delete('cache'); | |
transaction.objectStore("less").add({key: 'cache', data: Module._cache}); | |
}, | |
/** | |
* Cache URL's CSS code and LESS code hash. | |
* @private | |
*/ | |
setItem: function (url, css, lessHash) { | |
if (css !== null) { | |
Module._cache[url] = { | |
css: css, | |
lessHash: lessHash | |
}; | |
} else { | |
delete Module._cache[url]; | |
} | |
clearTimeout(Module.saveTimer); | |
Module.saveTimer = setTimeout(Module.save, 1000); | |
}, | |
/** | |
* Get URL's cached CSS and LESS code hash. | |
* @private | |
*/ | |
getItem: function (url) { | |
if (url in Module._cache) { | |
return Module._cache[url]; | |
} else { | |
return null; | |
} | |
}, | |
/*FNV-1 hash algorithm from https://gist.github.com/vaiorabbit/5657561. It gives very less collisions.*/ | |
hash: function fnv32(str) { | |
var FNV1_32A_INIT = 0x811c9dc5; | |
var hval = FNV1_32A_INIT; | |
for ( var i = 0; i < str.length; ++i ) { | |
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); | |
hval ^= str.charCodeAt(i); | |
} | |
return hval >>> 0; | |
}, | |
/** | |
* @param {String} url URL to less file (with the .less extension) | |
* @param {String} less The less code | |
*/ | |
cache: function (url, less, less_browser, callback) { | |
var lessHash = Module.hash(less) + '', | |
item = Module.getItem(url); | |
if (item && item.lessHash === lessHash) { | |
callback(null, item.css); | |
} else { | |
//render it using less | |
less_browser.render(less, { | |
filename: url, | |
rootpath: url.replace(/[^\/]*$/, '') | |
}, function (err, data) { | |
Module.setItem(url, data.css, lessHash); | |
callback(null, data.css); | |
}); | |
} | |
} | |
}; | |
(function (callback) { | |
//Clear db on new session. | |
if (!window.sessionStorage.getItem('systemjs-less-cacher')) { | |
var request = window.indexedDB.deleteDatabase('systemjs-less-cacher'); | |
request.onsuccess = callback; | |
request.onerror = function (event) { | |
console.error(event.target); | |
resolve(dummy); | |
}; | |
} else { | |
callback(); | |
} | |
}(function () { | |
var request = window.indexedDB.open("systemjs-less-cacher", 1); | |
request.onerror = function (event) { | |
console.error(event.target); | |
resolve(dummy); | |
}; | |
request.onsuccess = function (event) { | |
if (!db) { | |
db = event.target.result; | |
Module.init().then(function (mod) { | |
resolve(Module.cache); | |
}); | |
} | |
}; | |
request.onupgradeneeded = function (event) { | |
db = event.target.result; | |
Module.init().then(function (mod) { | |
resolve(Module.cache); | |
}); | |
}; | |
})); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment