Skip to content

Instantly share code, notes, and snippets.

@developit
Last active July 25, 2023 12:54
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save developit/220246bc99044af74a6680ce13284f59 to your computer and use it in GitHub Desktop.
Save developit/220246bc99044af74a6680ce13284f59 to your computer and use it in GitHub Desktop.

Module Workers Polyfill npm version

This is a 1.1kb polyfill for Module Workers.

It adds support for new Worker('..',{type:'module'}) to all modern browsers (those that support fetch).

Usage

Copy module-workers-polyfill.js to your web directory, then load it using an import or a script tag. It just needs to be loaded before instantiating your Worker.

<script src="/module-workers-polyfill.js"></script>
<script>
  const worker = new Worker('/worker.mjs', { type: 'module' });
</script>

Example

// load the polyfill:
import '/module-workers-polyfill.js';

// now we can use import-from-worker, which relies on Module Workers:
import importFromWorker from 'https://unpkg.com/import-from-worker@1.0.1/dist/import-from-worker.js';

function getAcornAST(code) {
  const { parse } = await importFromWorker('https://unpkg.com/acorn@7.1.0/dist/acorn.mjs');
  return await parse(code, { sourceType: 'module' });
}
(function(W) {
if (W && W._$P === true) return;
// if Worker is present and doesn't support Module Workers, install polyfill:
if (W) {
var s;
var OPTS = Object.defineProperty({}, 'type', {
get: function() {
s = true;
}
});
try {
var url = URL.createObjectURL(new Blob([''],{type:'text/javascript'}));
new W(url, OPTS).terminate();
URL.revokeObjectURL(url);
} catch (e) {}
if (!s) {
try {
new W("data:text/javascript,", OPTS).terminate();
} catch (e) {}
}
if (s) return;
(self.Worker = function Worker(url, opts) {
if (opts && opts.type == "module") {
opts = { name: url + '\n' + (opts.name || '') };
url = typeof document == "undefined" ? location.href : (document.currentScript && document.currentScript.src) || new Error().stack.match(/[(@]((file|https?):\/\/[^)]+?):\d+(:\d+)?(?:\)|$)/m)[1];
}
return new W(url, opts);
})._$P = true;
}
function p() {
// esm-polyfill
var r = {}, n = {}, x;
function e(r, e) {
for (
e = e.replace(/^(\.\.\/|\.\/)/, r.replace(/[^/]+$/g, "") + "$1");
e !== (e = e.replace(/[^/]+\/\.\.\//g, ""));
);
return e.replace(/\.\//g, "");
}
function t(s, u) {
var o, a = s;
u && (s = e(u, s));
return r[s] || (r[s] = fetch(s).then(function(u) {
if ((a = u.url) !== s) {
if (null != r[a]) return r[a];
r[a] = r[s];
}
return u.text().then(function(r) {
if (!u.ok) throw r;
var m = { exports: {} };
o = n[a] || (n[a] = m.exports);
var i = function(r) { return t(r, a); }, c = [];
return (
(r = (function(r, e) {
e = e || [];
var n, t = [], j = 0;
function u(r, e) {
for (var s, u = /(?:^|,)\s*([\w$]+)(?:\s+as\s+([\w$]+))?\s*/g, o = []; s = u.exec(r); )
e ? t.push((s[2] || s[1]) + ":" + s[1]) : o.push((s[2] || s[1]) + "=" + n + "." + s[1]);
return o;
}
return (
r = r
.replace(
/(^\s*|[;}\s\n]\s*)import\s*(?:(?:([\w$]+)(?:\s*\,\s*\{([^}]+)\})?|(?:\*\s*as\s+([\w$]+))|\{([^}]*)\})\s*from)?\s*(['"])(.+?)\6/g,
function(r, t, o, a, b, i, c, p) {
return (
e.push(p),
(t += "var " + (n = "$im$" + ++j) + "=$require(" + c + p + c + ")"),
o && (t += ";var " + o + " = 'default' in " + n + " ? " + n + ".default : " + n),
b && (t += ";var " + b + " = " + n),
(a = a || i) && (t += ";var " + u(a, !1)),
t
);
}
)
.replace(
/((?:^|[;}\s\n])\s*)export\s*(?:\s+(default)\s+|((?:async\s+)?function\s*\*?|class|const\s|let\s|var\s)\s*([a-zA-Z0-9$_{[]+))/g,
function(r, e, n, u, o) {
if (n) {
var a = "$im$" + ++j;
return t.push("default:" + a), e + "var " + a + "=";
}
return t.push(o + ":" + o), e + u + " " + o;
}
)
.replace(
/((?:^|[;}\s\n])\s*)export\s*\{([^}]+)\}\s*;?/g,
function(r, e, n) {
return u(n, !0), e;
}
)
.replace(
/((?:^|[^a-zA-Z0-9$_@`'".])\s*)(import\s*\([\s\S]+?\))/g,
"$1$$$2"
)
).replace(
/((?:^|[^a-zA-Z0-9$_@`'".])\s*)import\.meta\.url/g,
"$1" + JSON.stringify(s)
) + "\n$module.exports={" + t.join(",") + "}";
})(r, c)),
Promise.all(
c.map(function(r) {
var s = e(a, r);
return s in n ? n[s] : t(s);
})
).then(function(e) {
r += '\n//# sourceURL=' + s;
try {
var f = new Function("$import", "$require", "$module", "$exports", r);
} catch (e) {
var line = e.line - 1;
var column = e.column;
var lines = r.split('\n');
var stack = (lines[line-2] || '') + '\n' + lines[line-1] + '\n' + (column==null?'':new Array(column).join('-')+'^\n') + (lines[line] || '');
var err = new Error(e.message + '\n\n' + stack, s, line);
err.sourceURL = err.fileName = s;
err.line = line;
err.column = column;
throw err;
}
var n = f(i, function(r) { return e[c.indexOf(r)]; }, m, m.exports);
return (
null != n && (m.exports = n),
Object.assign(o, m.exports),
m.exports
);
})
);
});
}));
}
// import while queuing messages
var q = [], m = q.push.bind(q);
addEventListener("message", m);
function d() {
removeEventListener("message", m);
q.map(dispatchEvent);
}
var u = self.name.match(/^[^\n]+/)[0];
self.name = self.name.replace(/^[^\n]*\n/g, '');
t(u).then(d).catch(function(e) {
setTimeout(function() {
throw e;
});
});
}
if (typeof document == "undefined") p();
})(self.Worker);
!function(e){if(!e||!0!==e._$P){if(e){var n,r=Object.defineProperty({},"type",{get:function(){n=!0}});try{var t=URL.createObjectURL(new Blob([""],{type:"text/javascript"}));new e(t,r).terminate(),URL.revokeObjectURL(t)}catch(e){}if(!n)try{new e("data:text/javascript,",r).terminate()}catch(e){}if(n)return;(self.Worker=function(n,r){return r&&"module"==r.type&&(r={name:n+"\n"+(r.name||"")},n="undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||(new Error).stack.match(/[(@]((file|https?):\/\/[^)]+?):\d+(:\d+)?(?:\)|$)/m)[1]),new e(n,r)})._$P=!0}"undefined"==typeof document&&function(){var e={},n={};function r(e,n){for(n=n.replace(/^(\.\.\/|\.\/)/,e.replace(/[^/]+$/g,"")+"$1");n!==(n=n.replace(/[^/]+\/\.\.\//g,"")););return n.replace(/\.\//g,"")}var t=[],s=t.push.bind(t);addEventListener("message",s);var a=self.name.match(/^[^\n]+/)[0];self.name=self.name.replace(/^[^\n]*\n/g,""),function t(s,a){var u,o=s;return a&&(s=r(a,s)),e[s]||(e[s]=fetch(s).then((function(a){if((o=a.url)!==s){if(null!=e[o])return e[o];e[o]=e[s]}return a.text().then((function(e){if(!a.ok)throw e;var c={exports:{}};u=n[o]||(n[o]=c.exports);var i=function(e){return t(e,o)},f=[];return e=function(e,n){n=n||[];var r,t=[],a=0;function u(e,n){for(var s,a=/(?:^|,)\s*([\w$]+)(?:\s+as\s+([\w$]+))?\s*/g,u=[];s=a.exec(e);)n?t.push((s[2]||s[1])+":"+s[1]):u.push((s[2]||s[1])+"="+r+"."+s[1]);return u}return(e=e.replace(/(^\s*|[;}\s\n]\s*)import\s*(?:(?:([\w$]+)(?:\s*\,\s*\{([^}]+)\})?|(?:\*\s*as\s+([\w$]+))|\{([^}]*)\})\s*from)?\s*(['"])(.+?)\6/g,(function(e,t,s,o,c,i,f,p){return n.push(p),t+="var "+(r="$im$"+ ++a)+"=$require("+f+p+f+")",s&&(t+=";var "+s+" = 'default' in "+r+" ? "+r+".default : "+r),c&&(t+=";var "+c+" = "+r),(o=o||i)&&(t+=";var "+u(o,!1)),t})).replace(/((?:^|[;}\s\n])\s*)export\s*(?:\s+(default)\s+|((?:async\s+)?function\s*\*?|class|const\s|let\s|var\s)\s*([a-zA-Z0-9$_{[]+))/g,(function(e,n,r,s,u){if(r){var o="$im$"+ ++a;return t.push("default:"+o),n+"var "+o+"="}return t.push(u+":"+u),n+s+" "+u})).replace(/((?:^|[;}\s\n])\s*)export\s*\{([^}]+)\}\s*;?/g,(function(e,n,r){return u(r,!0),n})).replace(/((?:^|[^a-zA-Z0-9$_@`'".])\s*)(import\s*\([\s\S]+?\))/g,"$1$$$2")).replace(/((?:^|[^a-zA-Z0-9$_@`'".])\s*)import\.meta\.url/g,"$1"+JSON.stringify(s))+"\n$module.exports={"+t.join(",")+"}"}(e,f),Promise.all(f.map((function(e){var s=r(o,e);return s in n?n[s]:t(s)}))).then((function(n){e+="\n//# sourceURL="+s;try{var r=new Function("$import","$require","$module","$exports",e)}catch(n){var t=n.line-1,a=n.column,o=e.split("\n"),p=(o[t-2]||"")+"\n"+o[t-1]+"\n"+(null==a?"":new Array(a).join("-")+"^\n")+(o[t]||""),l=new Error(n.message+"\n\n"+p,s,t);throw l.sourceURL=l.fileName=s,l.line=t,l.column=a,l}var m=r(i,(function(e){return n[f.indexOf(e)]}),c,c.exports);return null!=m&&(c.exports=m),Object.assign(u,c.exports),c.exports}))}))})))}(a).then((function(){removeEventListener("message",s),t.map(dispatchEvent)})).catch((function(e){setTimeout((function(){throw e}))}))}()}}(self.Worker);
{
"name": "module-workers-polyfill",
"main": "module-workers-polyfill.min.js",
"version": "0.3.2",
"license": "Apache-2.0",
"homepage": "https://gist.github.com/developit/220246bc99044af74a6680ce13284f59",
"scripts": {
"prepare": "npx terser module-workers-polyfill.js -cmo module-workers-polyfill.min.js",
"prepack": "mv '*Module Workers Polyfill.md' README.md",
"postpack": "mv README.md '*Module Workers Polyfill.md'"
}
}
@Armster15
Copy link

This was literally a life saver, thank you so much!

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