Skip to content

feat: node worker support out of the box#21160

Open
prathameshnetake wants to merge 7 commits into
vitejs:mainfrom
prathameshnetake:feat/node-worker
Open

feat: node worker support out of the box#21160
prathameshnetake wants to merge 7 commits into
vitejs:mainfrom
prathameshnetake:feat/node-worker

Conversation

@prathameshnetake
Copy link
Copy Markdown

Support building of NodeJS worker out of the box. This PR also support dev mode
Successor of an old PR #3932

Comment thread packages/vite/src/node/plugins/worker.ts
prathameshnetake and others added 2 commits November 26, 2025 16:52
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
@aviallon
Copy link
Copy Markdown

I'd pay for this to be merged. Seriously.

@prathameshnetake
Copy link
Copy Markdown
Author

@antfu @hi-ogawa please review

@GeoffreyBooth
Copy link
Copy Markdown

I’m eager to see this PR (or another that adds worker support) land. It feels like a glaring gap in Vite that it doesn’t support multithreaded Node apps.

In case it helps anyone else, in my SvelteKit app I use the following custom plugin to enable worker support; edit as needed for your own worker files and paths:

import { copyFile, mkdir, cp } from 'node:fs/promises'
import { resolve } from 'node:path'
import { env } from 'node:process'


/**
 * Vite plugin to copy worker files to the build directory after adapter-node finishes.
 * This ensures worker threads are available when running in preview or production mode.
 *
 * vite-plugin-node-worker outputs to .svelte-kit/output/server/, but adapter-node
 * doesn't automatically copy worker files to build/server/. This plugin handles that.
 * We also need to copy the chunks directory since the worker imports from it.
 */
export function copyWorkerToBuildPlugin() {
	return {
		name: 'copy-worker-to-build',
		/**
		 * Run after the adapter has finished writing files
		 */
		async closeBundle() {
			const outputDir = resolve(import.meta.dirname, '../../.svelte-kit/output/server')
			const sourceWorker = resolve(outputDir, 'my-worker.worker.mjs')
			const sourceChunks = resolve(outputDir, 'chunks')
			const targetDir = resolve(import.meta.dirname, '../../build/server')
			const targetWorker = resolve(targetDir, 'my-worker.worker.mjs')
			const targetChunks = resolve(targetDir, 'chunks')

			try {
				// Ensure target directory exists
				await mkdir(targetDir, { recursive: true })

				// Copy the worker file
				await copyFile(sourceWorker, targetWorker)

				// Copy the chunks directory (worker dependencies)
				// Use force: false to not overwrite existing chunks from adapter-node
				await cp(sourceChunks, targetChunks, { recursive: true, force: false })
			} catch (error) {
				// Only error if we're in a build context where the worker file should exist
				if ((error instanceof Error && 'code' in error && error.code !== 'ENOENT') || env.BUILDING) {
					console.error('Failed to copy worker file:', error)
				}
			}
		},
	}
}

@aviallon
Copy link
Copy Markdown

@antfu Is there something that should be done before it is mergeable?

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

Successfully merging this pull request may close these issues.

3 participants