threads-plugin icon indicating copy to clipboard operation
threads-plugin copied to clipboard

Webpack5

Open linonetwo opened this issue 3 years ago • 13 comments

          parser.hooks.new.for('imported var').tap(NAME, expr => {
            if (expr.callee.name !== 'Worker') return false

Can be changed to this, because 'imported var' is not supported.

        parser.hooks.new.for('Worker').tap(NAME, function (expr) {

But still get TypeError: ParserHelpers.addParsedVariableToModule is not a function, and I searched issue https://github.com/GoogleChromeLabs/worker-plugin/issues/88 seems have a workaround, but ParserHelpers.getModulePath is gone too:

this update is useless

          ParserHelpers.addParsedVariableToModule(parser, id, req);

to

let ModuleDecoratorDependency;
try {
  ModuleDecoratorDependency = require("webpack/lib/dependencies/ModuleDecoratorDependency");
} catch (e) {}

// ...

          if (ModuleDecoratorDependency) {
            const dep = new ModuleDecoratorDependency(
              ParserHelpers.getModulePath(parser.state.module.context, req),
              parser.state.module
            );
            dep.loc = expr.loc;
            parser.state.module.addDependency(dep);
          } else {
            ParserHelpers.addParsedVariableToModule(parser, id, req);
          }

linonetwo avatar May 30 '21 09:05 linonetwo

Currently workaround https://github.com/andywer/threads-plugin/issues/37#issuecomment-790727118

// @ts-expect-error it don't want .ts
// eslint-disable-next-line import/no-webpack-loader-syntax
import workerURL from 'threads-plugin/dist/loader?name=worker!./gitWorker.ts';

is working, so this is not a hurry.

linonetwo avatar May 31 '21 17:05 linonetwo

Well, seems there are lots of changes compare to google's version https://github.com/andywer/threads-plugin/compare/master...GoogleChromeLabs:master?expand=1

It can gives some insight about how to upgrade, but it makes me wonder, can I just use worker-plugin to load threads.js ? If not ,what change is necessary? Currently, work on worker-plugin to make twick maybe easier.

linonetwo avatar Jun 01 '21 15:06 linonetwo

re: https://github.com/andywer/threads-plugin/issues/43#issuecomment-851607253 @linonetwo Thanks for posting this thread. I'm running into Error: Cannot find module 'webpack/lib/ParserHelpers' upon upgrading next to 11.0.0 while using threads.js + threads-plugin.

How are you able to use the workaround? From what I can tell, you still must have threads-plugin installed? It looks like this workaround won't work for me, but want to confirm...

hidesminimally avatar Jun 21 '21 00:06 hidesminimally

Hi @hidesminimally it works on my side https://github.com/tiddly-gittly/TiddlyGit-Desktop/blob/445c9a36c7e98bc7498fcba72b1ca84edcb861eb/src/services/git/index.ts#L17-L31 , maybe you can also checkout my webpack config.

linonetwo avatar Jun 21 '21 04:06 linonetwo

Doing this leaves webpack to copy across the files to dist, though i can't seem to get it working with typescript

const workerUrl = new URL('./my-worker.ts', import.meta.url);
const relativePath = path.relative(__dirname, workerUrl.pathname);

spawn(new Worker(relativePath)),

DustinJSilk avatar Jul 27 '21 07:07 DustinJSilk

My config works with electron forge, but didn't test with normal nodejs

linonetwo avatar Jul 27 '21 11:07 linonetwo

@DustinJSilk I think you have a contradiction in your code snippet: import.meta is only present in ES modules (ES2020+, I think) while __dirname is only available in CommonJS modules.

Maybe it can work in browsers after all, if webpack resolves the __dirname, but keeps the import.meta.url intact, for instance. Will most likely not work in node.js, though, I think.

Btw, what's the error?

andywer avatar Jul 27 '21 20:07 andywer

Oh, I didnt realise that would be the case. It seemed okay in Node with both __dirname and import.meta. I tried with both ES2020 and ESNext.

The reason it doesn't work with typescript is because webpack only copies the entry TS file to the dist folder which means all imports are broken. It might work if all code is in a single file though, I didn't try that.

I setup a separate webpack config in the meantime that compiles any *.worker.ts files into adjacent js, and then using the above snippet to copy it across to the dist folder and it runs now.

Not ideal as its a bit messy but its a start!

EDIT Actually, webpack refuses to copy across .ts files all together. I cant remember exactly how i got it to copy across, but even if we do copy it across it would need all dependencies or it would need to be compiled.

DustinJSilk avatar Jul 27 '21 20:07 DustinJSilk

@andywer Following on from this thread and example repository, it seems to work well for webworker, but it doesn't seem to work for node worker threads in TS.

https://github.com/webpack/webpack/discussions/13655

DustinJSilk avatar Jul 30 '21 07:07 DustinJSilk

Right I've managed to get it to compile with a little hack. Webpack 5 seems to only compile DOM URLs, not Node URLs. So I've added "DOM" to my tsconfig lib, and then casting the WebWorker URL to a Node URL seems to work:

import { Worker } from "worker_threads";
import { URL as NodeURL } from "url";

const worker = new Worker(
  new URL("./workers/foo.worker.ts", import.meta.url) as NodeURL
);

Example repo here: https://github.com/DustinJSilk/web-worker-ts-webpack-test

DustinJSilk avatar Jul 30 '21 08:07 DustinJSilk

That's super interesting! Thanks for sharing, @DustinJSilk 👍

Gotta try that myself…

andywer avatar Aug 01 '21 19:08 andywer

@DustinJSilk you just rescued me from a 3 day odysee of getting workers to run with webpack 5. Thanks so much!

Achder avatar Oct 06 '21 08:10 Achder

This works in create-reacte-app v5 in the browser too:

// @ts-expect-error it don't want .ts
// eslint-disable-next-line import/no-webpack-loader-syntax
import logicWorkerURL from 'threads-plugin/dist/loader?name=worker!../logic-worker/manager.ts';

//...

const logicWorker = await spawn<ILogicWorker>(new Worker(logicWorkerURL as string, { type: 'module' }), { timeout: 1000 * 60 });

While it will still have this error on the cli console:

WARNING in No instantiations of threads.js workers found.
Please check that:
  1. You have configured Babel / TypeScript to not transpile ES modules
  2. You import `Worker` from `threads` where you use it

For more details see: https://github.com/andywer/threads-plugin

But I tried to add a log to the worker, apparently the worker is bundled and loaded.

It is possible to ignore this warning in webpack by using ignoreWarnings. You can add this to the craco.config.js if you are using https://github.com/gsoft-inc/craco to modify webpack config of cra:

    configure: (webpackConfig) => {
      const ignoreWarnings = [{ module: /inversify/, message: /Failed to parse source map/ }, { message: /No instantiations of threads/ }];
      return { ...webpackConfig, ignoreWarnings };
    },

linonetwo avatar Nov 01 '22 13:11 linonetwo