Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions in params are not defined for the first time with thread-loader #33

Closed
tech-meppem opened this issue Nov 30, 2022 · 1 comment

Comments

@tech-meppem
Copy link

tech-meppem commented Nov 30, 2022

When using a function in params, it is not defined for the first time that file is processed, however, on subsequent run (such as the second time using webpack watch), it is defined correctly.
We use the 'thread-loader', and removing that does seem to make this work fine.
However, with it enabled, the first time the file is processed, it produces and error.
I can tell it works on subsequent processing with "watch" because putting a console.log in the function prints to console.

The error is:

includeID is not defined

    at eval (eval at ifComparator (node_modules\webpack-preprocessor-loader\dist\filter.js:134:24), <anonymous>:3:1)

As far as I can tell, this is only the case for functions, and normal values are perfectly fine.

So, for example, we have this:

const Config = {
  units: ["Foo", "Baz"]
}
...
{
  loader: 'webpack-preprocessor-loader',
  options: {
    params: {
      includeID: function(id: string) {
        return Config.units.includes(id);
      }
  }
}

And then the file looks like this:

// #!if includeID("Foo")
import {} from 'units/Foo';
// #!endif

// #!if includeID("Bar")
import {} from 'units/Bar';
// #!endif

// #!if includeID("Baz")
import {} from 'units/Baz';
// #!endif

Some other things which might affect it:
The webpack config is done in TS not JS.
We use 'thread-loader', and removing that works.

@tech-meppem tech-meppem changed the title Functions in params are not defined for the first time Functions in params are not defined for the first time with thread-loader Nov 30, 2022
@afterwind-io
Copy link
Owner

afterwind-io commented Dec 5, 2022

TL;DR
thread-loader is not getting along well with some loader options with non-JSON-serializable values, ie functions.

I spent some time reading the source code from thread-loader, not all of them, only to find things getting more confusing. The options you provide to the webpack-preprocessor-loader is JSON.stringifyed in the spawning session of thread-loader, which means the includeID is lost during the process.

https://github.com/webpack-contrib/thread-loader/blob/2e1dfff9fc7133c741ffdd4f1da5a7693b637ad0/src/WorkerPool.js#L90-L115

So it is clear that the trick you used should not be working at all when combined with thread-loader, hence leading to the error you mentioned at the beginning.

It seems that someone is having same problems but no actions taken since then:
webpack-contrib/thread-loader#75

Sorry for the delay but I am afraid it is an implementation limitation from the thread-loader and nothing more I can do for that. Maybe you should take another route if thread-loader is really important for you:

const Config = {
  units: ["Foo", "Baz"]
}
const dynamicParams = Config.units.reduce((obj, id) => Object.assign(obj, {[id]: true}), {})

// In option...
{
  params: dynamicParams      // If controlling block of codes with `#!if`,
  directives: dynamicParams  // If controlling single line of code with `#!foo`,
}

// In code...

// #!if foo == true
import {} from 'units/Foo';
// #!endif

// #!bar
import {} from 'units/Bar';

OR (not tested, should works)

const Config = {
  units: ["Foo", "Baz"]
}

// In option...
{
  params: { myPreciousIDs: Config.units }
}

// In code...

// #!if (function(ids){ return ids.includes("foo"); })(myPreciousIDs)
import {} from 'units/Foo';
// #!endif

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants