amd-loader icon indicating copy to clipboard operation
amd-loader copied to clipboard

Support for Web Worker Environments

Open neelabhg opened this issue 9 years ago • 1 comments

RequireJS can be run inside a Web Worker. I'm using the CJS plugin to use CommonJS modules inside a web worker, but I'm getting the "Environment unsupported" error message from amd-loader.

Web Workers do support XMLHttpRequest, so enabling amd-loader to run inside workers should be a matter of extending this if condition to check for availability of Web Worker APIs in addition to checking the availability of the window object.

Because this is probably a trivial change and there are many ways to implement this, I'm not opening a pull-request. To save time, here are the changes that seem to work reliably (in file amd-loader.js near line 80):

+  // from require.js source
+  var isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document);
+  var isWebWorker = !isBrowser && typeof importScripts !== 'undefined';
+
-  if (typeof window != 'undefined') {
+  if (isBrowser || isWebWorker) {
     var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
     var getXhr = function(path) {
       // check if same domain
       var sameDomain = true,
         domainCheck = /^(\w+:)?\/\/([^\/]+)/.exec(path);
-      if (typeof window != 'undefined' && domainCheck) {
+      if (domainCheck) {
-        sameDomain = domainCheck[2] === window.location.host;
+        sameDomain = domainCheck[2] === location.host;
         if (domainCheck[1])
-          sameDomain &= domainCheck[1] === window.location.protocol;
+          sameDomain &= domainCheck[1] === location.protocol;
       }

Note that window is not defined in a web worker, and so the global object in a web worker can be accessed using self but not window. self can also be used to access the global object in the main browser "thread". However, because self is commonly declared as a variable by many users, I don't think it can be used reliably. Getting access to the global object reliably is not very trivial or elegant, so short of using several typeof checks, I think it is best to use location.host and location.protocol directly instead of window.location.host and window.location.protocol respectively. A more robust solution would be great.

Another solution, as shown in a Stack Overflow answer, could be to ask users of this library to define the window object to be the global scope before executing amd-loader inside a web worker:

// configure paths and then import requirejs
importScripts('path/to/requirejs/require.js');

var window = self; // returns a reference to the WorkerGlobalScope

// code using amd-loader or plugins based on it
require(['cjs!some-module'], function (someModule) {
    // ...
});

neelabhg avatar Mar 16 '16 12:03 neelabhg

Web worker support would be higly appreciated. Any chance of merging a similar change to the one proposed by @neelabhg?

kristian avatar Mar 10 '19 23:03 kristian