Skip to content

Instantly share code, notes, and snippets.

@mseeley
Created March 3, 2014 09:29
Show Gist options
  • Star 45 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save mseeley/9321422 to your computer and use it in GitHub Desktop.
Save mseeley/9321422 to your computer and use it in GitHub Desktop.
WebWorker Image preloader proof of concept (Tested in Mobile Safari 6.0/IOS 6.1.3 and Chrome 33)
<!DOCTYPE html>
<html>
<head>
<title>WebWorker image preloading</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
</head>
<body>
<div id="output"></div>
<script id="imgloader" type="javascript/worker">
// Not race proof or robust. Proof of concept.
self.onmessage = function (e) {
var urls = e.data,
done = urls.length,
onload = function () {
if (--done === 0) {
self.postMessage('Done!');
self.close();
}
};
urls.forEach(function (url) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = xhr.onerror = onload;
xhr.open('GET', url, true);
xhr.send();
});
};
</script>
<script>
// Server must expose CORS headers for XHR preload.
var imgs = [
'http://i.imgur.com/JmvCQXd.jpg',
'http://i.imgur.com/L4ipvCE.jpg',
'http://i.imgur.com/fKDIYIP.jpg',
'http://i.imgur.com/4ad4bo5.jpg',
'http://i.imgur.com/VukIBgD.jpg'
],
URL = window.URL || window.webkitURL,
url = URL.createObjectURL(
new Blob(
[document.getElementById('imgloader').textContent],
{ type: "text/javascript" }
)
),
worker = new Worker(url);
worker.onmessage = function (e) {
var frag = document.createDocumentFragment(),
count = imgs.length,
onload = function () {
delete this.onload;
frag.appendChild(this);
if (--count === 0) {
console.log('done')
document.getElementById('output').appendChild(frag);
}
};
// These will come immediately from cache.
// Ensure cache is not disabled by dev tools.
imgs.forEach(function (img) {
var el = document.createElement('img');
// Avoid early reflows as images load without sizes. Wait for onload.
el.onload = onload;
el.src = img;
});
URL.revokeObjectURL(url);
};
// Mix in a cache-bust on every run.
imgs = imgs.map(function (img) {
return img + '?ts=' + Date.now();
});
worker.postMessage(imgs);
</script>
</body>
</html>
@reubenscratton
Copy link

Why does this work?? Surely you shouldn't be able to use 'document' within the worker?

@monomalvado
Copy link

See... the document calls are not inside the Worker JS. The only function call in there not specific to Workers is the XMLHttpRequest which is marked as being acceptable for Workers. Kudos for this script.

@optimalisatie
Copy link

I've created a library inspired by this concept.

https://github.com/optimalisatie/webworker-preload

@Dmyan
Copy link

Dmyan commented Jul 31, 2017

I've created a test at fiddle: https://jsfiddle.net/y0kkck55/1/

@Berkmann18
Copy link

Berkmann18 commented Nov 19, 2017

If I understood correctly, this in-worker DOM use is possible thanks to the worker script being passed as a blob or am I missing something?

@Srikanththyagarajan
Copy link

Does this preload supports IE browser

@jamesta696
Copy link

jamesta696 commented Mar 20, 2021

Pretty cool gist, is there a method to preload CSS & JS files? This is only specific to images.
Your feedback is appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment