Skip to content

Instantly share code, notes, and snippets.

@developit
Last active December 21, 2019 21:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save developit/95aee9ea1d46719b68948aa77f56d993 to your computer and use it in GitHub Desktop.
Save developit/95aee9ea1d46719b68948aa77f56d993 to your computer and use it in GitHub Desktop.

Module Worker polyfill for Chrome 61+

Chrome 61+ supports dynamic import() within Classic Workers. We can use this to polyfill Module Workers to a reasonable degree of accuracy.

The only trick is that we need to queue up any messages received while we wait for the module tree to load in the Worker, since Module Workers load the entire dependency graph before flushing messages queued during Worker instantiation.

This polyfill comes in two versions:

module-workers-polyfill-inline.js is a single-file polyfill, but creates Workers with an Opaque Origin. If you're only loading dependencies from absolute URLs and not relying on storage like IndexedDB, this option is fine.

module-workers-polyfill.js is a polyfill that depends on an external JS file to do its work. This allows it to be instantiated on the same origin as your page, avoiding the limitations present in the inline version.

// put this script in your web root (/module-worker-shim.js)
var $_=[];addEventListener("message",$_._=function(e){$_.push(e)});import(location.href.replace(/^.*#/,'')).then(function(){removeEventListener("message",$_._);$_.map(dispatchEvent);$_=0})
(function(W) {
Worker = function(url, opts) {
opts = Object.assign({}, opts || {});
if (opts.type != 'module') return new W(url, opts);
delete opts.type;
return new W('data:,var $_=[];addEventListener("message",$_._=function(e){$_.push(e)});import('+JSON.stringify(new URL(url, location.href).href)+').then(function(){removeEventListener("message",$_._);$_.map(dispatchEvent);$_=0})',opts);
}
}(Worker));
// remember to also copy module-worker-shim.js to your public directory
(function(W) {
Worker = function(url, opts) {
opts = Object.assign({}, opts || {});
if (opts.type == 'module') url = '/module-worker-shim.js#'+new URL(url, location.href).href);
delete opts.type;
return new W(url,opts);
}
}(Worker));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment