vite icon indicating copy to clipboard operation
vite copied to clipboard

feat: support node workers out of the box

Open prathameshnetake opened this issue 4 years ago • 21 comments

Description

  • Support Node workers out of the box. The current version throws an error "Worker is not defined".
  • Chunk path relative to the module that calling it

Additional context

This need basepath to be unset in config if target is node


What is the purpose of this pull request?

  • [ ] Bug fix
  • [X] New Feature
  • [x] Documentation update
  • [ ] Other

prathameshnetake avatar Jun 24 '21 06:06 prathameshnetake

Can you explain a bit about the use case of this feature?

antfu avatar Jun 25 '21 14:06 antfu

Hi @antfu

Assume following code

// worker.js

import { parentPort } from "worker_thread"

parentPort.on("message", () => {
  // some heavy work in thread
  ...
  parentPort.postMessage("result")
}

// main.js

import MyWorker from "./worker.js?worker"

const worker = new MyWorker()
worker .postMessage("some data");
worker .on("message", result => {
 // get result here
 console.log(result)
}

The current "Vite" version assumes Worker class on window

Problems with Node

  • Generated bundle file just cannot find a declaration for the "Worker" class and hence generate an error "Worker is not defined".
  • Current version emits worker chunk by name config.base + name + postfix -> "/worker.js" ( assuming default base "/"). In generated bundle worker path will be "new Worker('/worker.js')". In the case with node, it will be resolved from the root path of the OS e.g "C:" in windows.

Solutions

  • We can check if the build target is a node and add an import statement for "Worker" from "worker_thread" assuming the user will add external built-in dependencies.
  • Resolve worker path relative from module who calls it using __dirname

This will let us use worker for node js without hassle. Also, we can use typescript to define and use workers in Node.js import MyWorker from "./worker.ts?worker"

prathameshnetake avatar Jun 28 '21 18:06 prathameshnetake

Would like to know the scenario why would you want to bundle your node app using Vite? Electron or some SSR?

antfu avatar Jun 28 '21 20:06 antfu

@antfu I am using this for the electron app in typescript having some heavy ML work on worker threads.

prathameshnetake avatar Jun 29 '21 06:06 prathameshnetake

I think the scenario makes sense. @prathameshnetake Can you add some tests for this PR? Thanks

antfu avatar Aug 09 '21 05:08 antfu

@antfu Sure. I will make the test asap. Thanks

prathameshnetake avatar Aug 09 '21 19:08 prathameshnetake

@antfu Added tests. Please have a look. Thanks

prathameshnetake avatar Aug 16 '21 10:08 prathameshnetake

Would be great you could help documenting this feature as well

antfu avatar Aug 19 '21 12:08 antfu

@antfu Sure I will documentation for this

prathameshnetake avatar Aug 19 '21 16:08 prathameshnetake

Added a guide for node worker threads. Please review and provide feed back if any @Shinigami92 @antfu

prathameshnetake avatar Sep 01 '21 19:09 prathameshnetake

@antfu Please review changes.

prathameshnetake avatar Sep 22 '21 18:09 prathameshnetake

Is this PR dead?

Caleb-Irwin avatar Jan 03 '23 20:01 Caleb-Irwin

I will check if the intent of this PR is already in there

prathamesh-toptal avatar Jan 07 '23 06:01 prathamesh-toptal

Has anyone developed a good workaround for this? Trying to create a library that works both on browser and Node—but this remains a persistent challenge.

garrettmflynn avatar May 05 '23 02:05 garrettmflynn

Any updates for this PR?

feenn avatar May 08 '23 06:05 feenn

I'm not sure if this PR is still being considered, but I've come across a relevant use-case where the lack of support for worker_threads in Vite and Vitest is becoming a bottleneck. I'm using Vitest to test a Node package. Vitest defaults to 'node' as the environment (testTransformMode set to ssr: true). I'm facing issues when trying to work with worker_threads.

https://vitest.dev/config/#environment https://vitest.dev/config/#testtransformmode

My code, which is successfully built using SWC, fails during the testing phase in Vitest. The error message reads "Cannot find module," although the path specified is correct. Here's a simplified snippet:

import { Worker } from 'node:worker_threads'

// workerScript.ts exists in the correct location
const worker = new Worker(new URL('./workerScript.js', import.meta.url))

The lack of support for worker_threads means that Vite projects cannot use worker_threads in their SSR apps. As a side effect, it also means that Vitest users cannot test code that uses worker_threads.

As a temporary measure, I've managed to circumvent the issue by pre-compiling my code and then running the tests against the output in the dist folder, instead of directly using the src folder. While this does allow my tests to run, it undermines one of the main advantages of using Vitest, which is to streamline and simplify the testing process without requiring a separate build step.

heygrady avatar Aug 30 '23 19:08 heygrady

I want to use Vite library mode to bundle a node target package with worker pool, so it means Vite still not support for now? 😂

yunsii avatar Dec 16 '23 03:12 yunsii

Maybe try using the plugin directly? Just like electron-vite does

https://github.com/alex8088/electron-vite/blob/master/src/plugins/worker.ts

rxliuli avatar Jan 07 '24 06:01 rxliuli

I think it's because Vite is primarily focused on frontend development. However, I wish Vite could support node:worker_threads, as I use Vite not only for frontend development but also for backend development with Node.js, vite-node, Fastify and vite-plugin-fastify. If it had this support, it would make working with Bree much more convenient. I could use TypeScript without having to rely on vite-plugin-static-copy to copy JavaScript files to the dist folder.


import { Worker } from 'node:worker_threads'

// workerScript.ts exists in the correct location
const worker = new Worker(new URL('./workerScript.js', import.meta.url))

This can be used during Vite development, but it cannot be executed properly with the build command and requires vite-plugin-static-copy to handle it. By the way, during development, Workers can also use TypeScript, but the build command cannot handle it. So, I have to write JavaScript and then copy it to the dist folder.

Shyam-Chen avatar Jul 09 '24 08:07 Shyam-Chen

I think it's because Vite is primarily focused on frontend development. However, I wish Vite could support node:worker_threads, as I use Vite not only for frontend development but also for backend development with Node.js, vite-node, Fastify and vite-plugin-fastify. If it had this support, it would make working with Bree much more convenient. I could use TypeScript without having to rely on vite-plugin-static-copy to copy JavaScript files to the dist folder.

import { Worker } from 'node:worker_threads'

// workerScript.ts exists in the correct location
const worker = new Worker(new URL('./workerScript.js', import.meta.url))

This can be used during Vite development, but it cannot be executed properly with the build command and requires vite-plugin-static-copy to handle it. By the way, during development, Workers can also use TypeScript, but the build command cannot handle it. So, I have to write JavaScript and then copy it to the dist folder.

@Shyam-Chen Did you ever find a better solution to these issues? I'm just now stumbling across these as well. I'm trying to utilize vite-node for Node.js server development using TypeScript.

jarrodpayne avatar Aug 08 '24 13:08 jarrodpayne

@Shyam-Chen Did you ever find a better solution to these issues? I'm just now stumbling across these as well. I'm trying to utilize vite-node for Node.js server development using TypeScript.

@paynecodes My current solution is to use vite-plugin-static-copy to copy the JavaScript Worker file that I have written.

Shyam-Chen avatar Aug 10 '24 07:08 Shyam-Chen