npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rollup-plugin-worker-threads

v0.3.0

Published

Provides a better developer experience for `worker_threads` by automatically splitting the worker threads' code into separate files when packaging.

Downloads

2

Readme

rollup-plugin-worker-threads

Introduction

Provides a better developer experience for worker_threads by automatically splitting the worker threads' code into separate files when packaging.

  • ts is the first priority supported
  • Instead of using the worker, run the function directly when the test is run

Use

yarn add -D rollup-plugin-worker-threads # Install dependencies

The first way

//rollup.config.js
import { defineConfig } from 'rollup'
import typescript from 'rollup-plugin-typescript2'
import { workerThreadsSuffix } from 'rollup-plugin-worker-threads'

export default defineConfig([
  {
    input: 'src/index.ts',
    output: [
      { dir: 'dist/esm', format: 'esm' },
      { dir: 'dist/cjs', format: 'cjs' },
    ],
    plugins: [typescript(), workerThreadsSuffix()],
  },
])

Specific code

// src/util/wrapWorkerFunc.ts
import { expose, Remote, wrap } from 'comlink'
import path from 'path'
import { isMainThread, parentPort, Worker } from 'worker_threads'
import nodeEndpoint from 'comlink/dist/umd/node-adapter'

/**
 * Wrapping functions to be executed in the worker
 * 1. return the function directly when it checks that the current file is not a js file
 * 2. when it is checked that it is executed in the main thread, use worker to wrap it and execute it
 * 3. use expose to wrap it and execute it when it is checked to be in the worker thread
 * Note: Currently a new worker is created each time, maybe consider supporting reuse of workers
 * @param ep
 */
export function wrapWorkerFunc<T extends (...args: any[]) => any>(
  ep: T,
): Remote<T> {
  if (path.extname(__filename) !== '.js') {
    return ep as Remote<T>
  }
  if (isMainThread) {
    return ((...args: any[]) => {
      const worker = new Worker(__filename)
      const fn = wrap<T>(nodeEndpoint(worker))
      return (fn(...args) as Promise<any>).finally(() => worker.unref())
    }) as Remote<T>
  }
  expose(ep, nodeEndpoint(parentPort!))
  return ep as Remote<T>
}
// src/hello.worker.ts
import { wait } from '@liuli-util/async'
import { wrapWorkerFunc } from './util/wrapWorkerFunc'

async function _hello(name: string) {
  await wait(100)
  return `hello ${name}`
}

export const hello = wrapWorkerFunc(_hello)
// index.ts
export * from './hello.worker'

The second way

//rollup.config.js
import { defineConfig } from 'rollup'
import typescript from 'rollup-plugin-typescript2'
import { workerThreads } from 'rollup-plugin-worker-threads'

export default defineConfig([
  {
    input: 'src/index.ts',
    output: [
      { dir: 'dist/esm', format: 'esm' },
      { dir: 'dist/cjs', format: 'cjs' },
    ],
    plugins: [typescript(), workerThreads()],
  },
])

Specific code

// index.ts
import HelloWorker from './worker?worker'
import type { worker as helloType } from './worker'
import { wrap } from 'comlink'
import nodeEndpoint from 'comlink/dist/umd/node-adapter'

export async function hello(name: string) {
  const worker = new HelloWorker()
  try {
    const helloWorker = wrap<typeof helloType>(nodeEndpoint(worker))
    return await helloWorker(name)
  } finally {
    worker.unref()
  }
}
// worker.ts
import { wait } from '@liuli-util/async'
import { expose } from 'comlink'
import { parentPort } from 'worker_threads'
import nodeEndpoint from 'comlink/dist/umd/node-adapter'

export async function worker(name: string) {
  await wait(1_00)
  return `hello ${name}`
}

expose(worker, nodeEndpoint(parentPort!))

FAQ

Why are there two ways to use it?

This project was originally inspired by vite's Import Script as Worker, but then I realized that nodejs itself provides the ability to write the main thread and worker thread in one But then I realized that nodejs itself provides a convenient way to write code for the main thread and worker thread in one file, so I tried both. At the moment I prefer the first way, and I will probably delete the second way of using it later.

Why not use existing plugins?

Well, I can list some of the plugins I have researched and their issues.

  • rollup-plugin-web-worker-loader
    • Does not handle ts files by default
    • worker does not package dependencies when they are included in the worker
  • rollup-plugin-worker-factory
    • No example of ts in sight
    • The default is to modify the worker
  • @surma/rollup-plugin-off-main-thread
    • Don't see the ts example

No satisfactory plugins have been found so far, so I may have to write a rollup plugin afterwards. As I said, no comparison is no harm, if there is no good support for ts+worker from vite, maybe I can still tolerate this bad development experience.