NativeScript / worker-loader

36 stars 20 forks source link

Webworker loader issue #33

Closed NathanaelA closed 5 years ago

NathanaelA commented 5 years ago

I have a plugin with two files; Primary.js and Worker.js

In Primary.js I have:

function handleAwesomeness(doBackground) {
  if (doBackground) {
    if (global.TNS_WEBPACK) {
        const TestWorker = require("nativescript-worker-loader!./Worker.js");
        worker = new TestWorker();
     } else {
        worker = new Worker("./Worker.js");
     }
     return;
  }
  console.log("Handle Awesomeness");
}
module.exports=handleAwesomeness;

in Worker.js I have

let ha = require('Primary');

// This will cause the worker to print "Handle Awesomeness" if it is working.
ha();

In the App; I do:

const ha = require('Primary');

// this will cause the Primary function to run on the foreground thread.
ha(false);

// This will cause the Primary function to run on a background thread.
ha(true);

If I use webpack --bundle; This causes the nativescript-worker-loader to go into a infinite loop and then crash with an Out of memory (like #7).

This is technically a loop; but the nativescript-worker-loader should detect that it is calling itself (i.e. the require('nativescript-worker-loader!...') and either skip doing anything or return '' so that the loop no longer continues.

Webpack itself handles this situation fine (you can test by deleting the nativescript-worker-loader! in the require statement in Primary.js) without the worker-loader; but of course then without the ns-worker-loader plugin, the code isn't packed into a separate file so that it can be loaded by the worker...

vchimev commented 5 years ago

Hey @NathanaelA,

Thanks for the report.

It would be best to avoid the circular reference if possible in your scenario, similar to here. However, the related pull request will avoid the loop of nativesciprt-worker-loader calls to itself.

NathanaelA commented 5 years ago

Unfortunately in my specific scenario the plugin that you normally load (Primary) needs to work properly in non-worker mode; which will be used a lot. So the require('primary'); is a force requirement as we don't want to break any apps. ;-) The ability for it to use itself in worker mode then means that 'primary' has to be loadable in the worker. That is what causes the circular reference.

The only other design I can think of is: Move everything from Primary into secondary. Like so:

Primary.js

function handleAwesomeness(doBackground) {
  if (doBackground) {
    if (global.TNS_WEBPACK) {
        const TestWorker = require("nativescript-worker-loader!./Worker.js");
        worker = new TestWorker();
     } else {
        worker = new Worker("./Worker.js");
     }
     return;
  } else { 
     const secondary = require('Secondary');
     secondary();
}
module.exports=handleAwesomeness;

Secondary.js

function handleAwesomeness() {
   console.log("Handle Awesomemness");
} 
module.exports=handleAwesomeness;

Worker.js

const ha = require('secondary');

// This will cause the worker to print "Handle Awesomeness" if it is working.
ha();

This would eliminate the loop. But would add an additional JS file to the plugin. It is a doable design; and one I considered. But it would require me to make sure that all constants and all statics functions that are needed in Secondary are exposed properly in Primarily. Just adds more work, and increases the maintenance burden, so not a big fan of this idea... So I really like your PR #34 ; thank you!

vchimev commented 5 years ago

Released in 0.9.3.