Execute web worker from different origin

2019-02-05 20:11发布

问题:

I am developing a library which I want to host on a CDN. The library is going to be used on many different domains across multiple servers. The library itself contains one script (let's call it script.js for now) which loads a web worker (worker.js).

Loading the library itself is quite easy: just add the <script type="text/javascript" src="http://cdn.mydomain.com/script.js"></script> tag to the domain on which I want to use the library (www.myotherdomain.com). However since the library is loading a worker from http://cdn.mydomain.com/worker.js new Worker('http://cdn.mydomain.com/worker.js'), I get a SecurityException. CORS is enabled on cdn.mydomain.com.

For web workers it is not allowed to use a web worker on a remote domain. Using CORS will not help: browsers seem to ignore it and don't even execute the preflight check.

A way around this would be to perform an XMLHttpRequest to get the source of the worker and then create a BLOB url and create a worker using this url. This works for Firefox and Chrome. However, this does not seem to work for Internet Explorer or Opera.

A solution would be to place the worker on www.myotherdomain.com or place a proxy file (which simply loads the worker from the cdn using XHR or importScripts). I do not however like this solution: it requires me to place additional files on the server and since the library is used on multiple servers, updating would be difficult.

My question consists of two parsts:

  1. Is it possible to have a worker on a remote origin for IE 10+?
  2. If 1 is the case, how is it handled best to be working cross-browser?

回答1:

For those who find this question:

YES.

It is absolutely possible: the trick is leveraging an iframe on the remote domain and communicating with it through postMessage. The remote iframe (hosted on cdn.mydomain.com) will be able to load the webworker (located at cdn.mydomain.com/worker.js) since they both have the same origin. The iframe can then act as a proxy between the postMessage calls. The script.js will however be responsible from filtering the messages so only valid worker messages are handled.

The downside is that communication speeds (and data transfer speeds) do take a performance hit.

In short:

  • script.js appends iframe with src="//cdn.mydomain.com/iframe.html"
  • iframe.html on cdn.mydomain.com/iframe.html, executes new Worker("worker.js") and acts as a proxy for message events from window and worker.postMessage (and the other way around).
  • script.js communicates with the worker using iframe.contentWindow.postMessage and the message event from window. (with the proper checks for the correct origin and worker identification for multiple workers)