Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

worker-loader picks up webpack5 from parent folder, not webpack4 from peer #295

Closed
Knagis opened this issue Oct 15, 2020 · 12 comments · Fixed by #296
Closed

worker-loader picks up webpack5 from parent folder, not webpack4 from peer #295

Knagis opened this issue Oct 15, 2020 · 12 comments · Fixed by #296

Comments

@Knagis
Copy link
Contributor

Knagis commented Oct 15, 2020

  • Operating System: Win10
  • Node Version: 12.13
  • NPM Version:
  • webpack Version: 5.1.1 + 4.44.2
  • worker-loader Version: 3.0.3

Expected Behavior

worker-loader from subfolder loads webpack 4 (the peer dependency and the webpack that is loading the loader itself.

Actual Behavior

worker-loader loads webpack 5 version and crashes.

Module build failed (from /subfolder/node_modules/worker-loader/dist/cjs.js):
TypeError: Cannot read property 'for' of undefined
    at /node_modules/webpack/lib/web/FetchCompileWasmPlugin.js:40:7
    at SyncHook.eval [as call] (eval at create (/subfolder/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:9:1)
    at SyncHook.lazyCompileHook (/subfolder/node_modules/tapable/lib/Hook.js:154:20)
    at Compiler.newCompilation (/subfolder/node_modules/webpack/lib/Compiler.js:630:30)
    at /subfolder/node_modules/webpack/lib/Compiler.js:667:29
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/subfolder/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/subfolder/node_modules/tapable/lib/Hook.js:154:20)
    at Compiler.compile (/subfolder/node_modules/webpack/lib/Compiler.js:662:28)
    at Compiler.runAsChild (/subfolder/node_modules/webpack/lib/Compiler.js:328:8)
    at runAsChild (/subfolder/node_modules/worker-loader/dist/supportWebpack4.js:11:26)
    at Object.pitch (/subfolder/node_modules/worker-loader/dist/index.js:102:34)

Code

// index.js from worker-loader
try{
  FetchCompileWasmPlugin = require('webpack/lib/web/FetchCompileWasmPlugin');
} catch {}
FetchCompileWasmPlugin = FetchCompileWasmPlugin || require('webpack/lib/web/FetchCompileWasmTemplatePlugin');

How Do We Reproduce?

Install two copies of webpack and worker-loader as follows:

  • package.json
    • depends on webpack 5.1.1
    • depends on worker-loader 3.0.3
  • subfolder/package.json
    • depends on storybook
    • depends on webpack 4.44.2
    • depends on worker-loader 3.0.3
@alexander-akait
Copy link
Member

alexander-akait commented Oct 15, 2020

You need to setup your monorepo in right way, disable hoist for webpack@4 for subfolder, sorry, we can't fix it on our side, even we add try/catch, it is not help, because webpack@4 and webpack@5 have incompatibilities

@Knagis
Copy link
Contributor Author

Knagis commented Oct 15, 2020

how about this?

try {
  w5 = require('webpack/lib/web/FetchCompileWasmPlugin')
} catch {}
try {
  w4 = require('webpack/lib/web/FetchCompileWasmTemplatePlugin');
} catch {}

if (w5 && w4) {
  const webpack = require("webpack");
  plugin = webpack.web.FetchCompileWasmPlugin || webpack.web.FetchCompileWasmTemplatePlugin;
} else {
  plugin = w5 || w4 || throw Error("could not load webpack peer dependency");
}

or...

const useWebpack4 = require("webpack/package.json").version.startsWith("4.");
if (useWebpack4) {
  plugin = require('webpack/lib/web/FetchCompileWasmTemplatePlugin')
} else {
  plugin = require('webpack/lib/web/FetchCompileWasmPlugin')
}

@alexander-akait
Copy link
Member

Still not solve, because require in your case always will return 5 and load old version of plugins

@alexander-akait
Copy link
Member

But I think we can solve it for webpack@5.1, but it will be breaking change

@alexander-akait
Copy link
Member

webpack@5.1 return compiler.webpack (self export), so we can use it, but in this case you will have two loaders with different versions, expected?

@Knagis
Copy link
Contributor Author

Knagis commented Oct 15, 2020

Still not solve, because require in your case always will return 5 and load old version of plugins

require("webpack") would load the closest webpack, which is the peer dependency.. the key is to require something of webpack that exists in both v4 and v5 so that node doesn't try to skip the peer dependency due to missing file.

require("webpack/package.json").version would also load the peer dependency - so nested loader would load webpack 4 while the root loader would load webpack 5.


using compiler.webpack would be best, yes. that would enable me to not hack around with the multiple plugins completely.

@Knagis
Copy link
Contributor Author

Knagis commented Oct 15, 2020

btw, I suspect this issue also might be triggered if one installs webpack 5 globally but has a package that depends on webpack 4 - the loader would pick up webpack 5 from global node_modules.

@alexander-akait
Copy link
Member

Yes, so ideal solution do not hoist webpack in this case, just nnote - hoisting babel/ts/other packages will lead to the same problem

@alexander-akait
Copy link
Member

alexander-akait commented Oct 15, 2020

We starting to rewrite our code on using compiler.webpack, but I think we can avoid it here, why? Because this package will be deprecated in near future, webpack@5 supports web workers out of box, only inline is not implemented

@alexander-akait
Copy link
Member

webpack/webpack#6472

@alexander-akait
Copy link
Member

I will update docs here for migration after inline implementation

@Knagis
Copy link
Contributor Author

Knagis commented Oct 15, 2020

how about the approach in #296 ? It should not create any change for any normal typical usecase and fix this hacky hoisted case

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

Successfully merging a pull request may close this issue.

2 participants