npm i freelancer --save
An implementation of on-the-fly defined WebWorkers that are created inline using data URIs, rather than separate physical files — for the benefit of all humanity.
example: heroku • ~500 bytes gzipped.
Freelancer
uses the same interface as Worker
except the passed parameters upon instantiation are slightly different.
Normally when invoking new Worker
you pass the location of the file, whereas with new Freelancer
you pass a function that contains the body of the worker.
Freelancer
also allows an optional second parameter to be passed that allows you to send additional options to the worker.
import { Freelancer } from 'freelancer';
const worker = new Freelancer(() => {
self.addEventListener('message', event => {
console.log(event.data);
self.postMessage('Pong!');
});
});
worker.addEventListener('message', event => console.log(event.data));
worker.postMessage('Ping?');
It's worth bearing in mind that the worker is still a separate thread and thus the typical rules of closures no longer apply – any parameters you would like to be received by the worker would need to be sent using postMessage
or by passing parameters upon instantiation.
Upon instantiation of Freelancer
you can use the second parameter to pass options that will be pushed to the worker – passed options will be serialized using JSON.stringify
and thus any data sent needs to be serializable – which essentially means you're unable to pass by reference, and circular references will cause issues.
import { SharedFreelancer } from 'freelancer';
const options = { send: 'Ping?', respond: 'Pong!' };
const worker = new SharedFreelancer(options => {
self.addEventListener('message', event => {
console.log(event.data);
self.postMessage(options.respond);
});
}, options);
worker.addEventListener('message', event => console.log(event.data));
worker.postMessage(options.send);
Although we refer to it as the second parameter you are in fact able to pass an infinite amount of parameters to the worker – the only requirement is that the first parameter is the worker's function.
When defining a worker inline you'll lose the ability to import
because the declaration needs to be at the top-level – instead you should prefer dynamic import
s using async
functions or a simple Promise.then
.
import { Freelancer } from 'freelancer';
import translate from './translator';
const worker = new Freelancer(async () => {
const translate = await import('./translator');
self.addEventListener('message', event => {
self.postMessage(translate(options.respond));
});
});
worker.postMessage(translate(options.send));
In some cases SharedWorker
— or to a lesser extent Worker
— may be undefined
due to a lack of browser support (see issue). When a worker is unsupported you'll receive an error message, and thus it's crucial to determine browser support before using a particular worker.