andywer / threads-plugin

📦 Makes your threads.js code build with webpack out of the box.
Apache License 2.0
28 stars 6 forks source link

Webpack5 #43

Open linonetwo opened 3 years ago

linonetwo commented 3 years ago
          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 commented 3 years ago

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 commented 3 years ago

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.

hidesminimally commented 3 years ago

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...

linonetwo commented 3 years ago

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.

DustinJSilk commented 3 years ago

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)),
linonetwo commented 3 years ago

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

andywer commented 3 years ago

@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?

DustinJSilk commented 3 years ago

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 commented 3 years ago

@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 commented 3 years ago

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

andywer commented 3 years ago

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

Gotta try that myself…

Achder commented 3 years ago

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

linonetwo commented 2 years ago

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 };
    },
JiaPeng1234 commented 3 weeks ago

I have a similar issue with webpack 5, apparently the fallback

fallback: {
            stream: require.resolve('stream-browserify')
        }

doesn't work so I used

    new NormalModuleReplacementPlugin(/node:stream/, 'stream'),

to manually replace, and it works for me