[Update 2021-06: Chrome and Edge have supported ES6 Modules in Dedicated Workers since Nov 2019. The equivalent Webkit bug is https://bugs.webkit.org/show_bug.cgi?id=164860 which seems fixed since April 2021. Yay! The equivalent Mozilla bug is https://bugzilla.mozilla.org/show_bug.cgi?id=1247687 which work seems to have now started. Yay! Follow along on Can I use!]
I've been playing around a bit with React, since that's where all the hot and shiny is lately. I really like it, but I can see some of the hot and shiny warts - I'll blog about that later after I've been fully brainwashed had more time to play with it.
For the purposes of this exercise, one thing I'm trying to do is go the no-build-step route, where it's all pure HTML and JavaScript. This means no JSX, no npm, no Babel. It's really not too bad at all (unfortunately almost all examples I've seen online use JSX - and understandably).
It's also given me a good stretch at using ES6 modules natively, one hot and shiny wart I've noticed there too.
Web Workers are a way to write JavaScript that executes off the "main thread" of your web app. You pass messages to it, you listen for messages coming back from it. They were introduced a long time ago (seven years!), long before ES6 became a reality, and certainly long before it became possible to use ES6 modules natively.
const worker = new Worker('sketchy.js');
worker.onmessage = function(msg) {
// do something with messages sent back by worker
};
worker.postMessage({...}); // send something to the worker
Workers operate in a different JavaScript context, a WorkerGlobalScope, not the global Window context that normal JavaScript files do. As a result, they seem like a decent way for me to execute user code (that is, code entered by the user into an editor on the page) and avoid common security problems with this, since they do not have access to the DOM, the browser window, cookies, etc. Someone let me know if I'm wrong about this!
Anyway, that's why I want to use Workers. But all the other times I've used Workers, I've hit up against the fact that they are not modules and can't import other modules. This isn't great if you're trying to change over all your project to ES6 modules. Code should be sharable between your main web app, your Web Workers, your Service Workers, etc.
Well turns out I was just using it wrong - kinda.
When you create a Worker, you can also specify options, and one of those options lets you specify that the Worker is a Module:
const worker = new Worker('sketchy.js', {type:'module'});
This is great, except for one thing... Chrome doesn't seem to support this yet. Bug 680046. But good news - work seems to have gotten started on that this month! One can hope that we'll soon be in a world where we can be all modules, all the time.
So, just a helpful correction, a web worker alone is not safe. I’ve created a small project to do secure evals in my own projects: https://github.com/Prendus/secure-eval
I’ve been looking into this issue for about 3 years now, and I’m pretty satisfied that if you use an iframe with the sandbox attribute set to allow-scripts, and then use a web worker from within there, you’re pretty safe.
The problem with just using a web worker is that the web worker still has access to local storage and other resources on your domain, though it does not have access to the DOM. Using an iframe puts the web worker on a different domain, while restricting its access to the DOM. Beware of infinite loops as well, in my library I set a time limit of ten seconds for the web worker to finish its execution. Anyway, if you want to talk about this issue more let me know. I couldn’t find any contact information for you, I’m @lastmjs on Twitter and GitHub
Do we know which browsers *do* support es6 module workers?