UNPKG

6.76 kBMarkdownView Raw
1<h1 align="center">
2 <img alt="threads.js" src="./docs/assets/logo-label.png" width="75%" />
3</h1>
4<p align="center">
5 <a href="https://travis-ci.org/andywer/threads.js" target="_blank"><img alt="Build status" src="https://img.shields.io/travis/andywer/threads.js/v1.svg?style=flat-square"></a>
6 <a href="https://www.npmjs.com/package/threads" target="_blank"><img alt="npm (tag)" src="https://img.shields.io/npm/v/threads.svg?style=flat-square"></a>
7</p>
8
9<br />
10
11Offload CPU-intensive tasks to worker threads in node.js, web browsers and electron using one uniform API.
12
13Uses web workers in the browser, `worker_threads` in node 12+ and [`tiny-worker`](https://github.com/avoidwork/tiny-worker) in node 8 to 11.
14
15### Features
16
17* First-class support for **async functions** & **observables**
18* Write code once, run it **on all platforms**
19* Manage bulk task executions with **thread pools**
20* Use **require()** and **import**/**export** in workers
21* Works great with **webpack**
22
23### Version 0.x
24
25You can find the old version 0.12 of threads.js on the [`v0` branch](https://github.com/andywer/threads.js/tree/v0). All the content on this page refers to version 1.0 which is a rewrite of the library with a whole new API.
26
27## Installation
28
29```
30npm install threads tiny-worker
31```
32
33*You only need to install the `tiny-worker` package to support node.js < 12. It's an optional dependency and used as a fallback if `worker_threads` are not available.*
34
35## Platform support
36
37<details>
38<summary>Run on node.js</summary>
39
40<p></p>
41
42Running code using threads.js in node works out of the box.
43
44Note that we wrap the native `Worker`, so `new Worker("./foo/bar")` will resolve the path relative to the module that calls it, not relative to the current working directory.
45
46That aligns it with the behavior when bundling the code with webpack or parcel.
47
48</details>
49
50<details>
51<summary>Webpack build setup</summary>
52
53#### Webpack config
54
55Use with the [`threads-plugin`](https://github.com/andywer/threads-plugin). It will transparently detect all `new Worker("./unbundled-path")` expressions, bundles the worker code and replaces the `new Worker(...)` path with the worker bundle path, so you don't need to explicitly use the `worker-loader` or define extra entry points.
56
57```sh
58 npm install -D threads-plugin
59```
60
61Then add it to your `webpack.config.js`:
62
63```diff
64+ const ThreadsPlugin = require('threads-plugin');
65
66 module.exports = {
67 // ...
68 plugins: [
69+ new ThreadsPlugin()
70 ]
71 // ...
72 }
73```
74
75#### Node.js bundles
76
77If you are using webpack to create a bundle that will be run in node (webpack config `target: "node"`), you also need to specify that the `tiny-worker` package used for node < 12 should not be bundled:
78
79```diff
80 module.exports = {
81 // ...
82+ externals: {
83+ "tiny-worker": "tiny-worker"
84+ }
85 // ...
86}
87```
88
89Make sure that `tiny-worker` is listed in your `package.json` `dependencies` in that case.
90
91#### When using TypeScript
92
93Make sure the TypeScript compiler keeps the `import` / `export` statements intact, so webpack resolves them. Otherwise the `threads-plugin` won't be able to do its job.
94
95```diff
96 module.exports = {
97 // ...
98 module: {
99 rules: [
100 {
101 test: /\.ts$/,
102 loader: "ts-loader",
103+ options: {
104+ compilerOptions: {
105+ module: "esnext"
106+ }
107+ }
108 }
109 ]
110 },
111 // ...
112 }
113```
114
115</details>
116
117<details>
118<summary>Parcel bundler setup</summary>
119
120<p></p>
121
122You need to import `threads/register` once at the beginning of your application code (in the master code, not in the workers):
123
124```diff
125 import { spawn } from "threads"
126+ import "threads/register"
127
128 // ...
129
130 const work = await spawn(new Worker("./worker"))
131```
132
133This registers the library's `Worker` implementation for your platform as the global `Worker`. This is necessary, since you cannot `import { Worker } from "threads"` or Parcel won't recognize `new Worker()` as a web worker anymore.
134
135Be aware that this might affect any code that tries to instantiate a normal web worker `Worker` and now instead instantiates a threads.js `Worker`. The threads.js `Worker` is just a web worker with some sugar on top, but that sugar might have unexpected side effects on third-party libraries.
136
137Everything else should work out of the box.
138
139</details>
140
141## Getting Started
142
143### Basics
144
145```js
146// master.js
147import { spawn, Thread, Worker } from "threads"
148
149const auth = await spawn(new Worker("./workers/auth"))
150const hashed = await auth.hashPassword("Super secret password", "1234")
151
152console.log("Hashed password:", hashed)
153
154await Thread.terminate(auth)
155```
156
157```js
158// workers/auth.js
159import sha256 from "js-sha256"
160import { expose } from "threads/worker"
161
162expose({
163 hashPassword(password, salt) {
164 return sha256(password + salt)
165 }
166})
167```
168
169### spawn()
170
171The `hashPassword()` function of the `auth` object in the master code proxies the call to the `hashPassword()` function in the worker:
172
173If the worker's function returns a promise or an observable then you can just use the return value as such in the master code. If the function returns a primitive value, expect the master function to return a promise resolving to that value.
174
175### expose()
176
177Use `expose()` to make a function or an object containing methods callable from the master thread.
178
179In case of exposing an object, `spawn()` will asynchronously return an object exposing all the object's functions. If you `expose()` a function, `spawn` will also return a callable function, not an object.
180
181## Usage
182
183<p>
184 Find the full documentation on the <a href="https://threads.js.org/" rel="nofollow">website</a>:
185</p>
186
187- [**Quick start**](https://threads.js.org/getting-started)
188- [**Basic usage**](https://threads.js.org/usage)
189- [**Using observables**](https://threads.js.org/usage-observables)
190- [**Thread pools**](https://threads.js.org/usage-pool)
191- [**Advanced**](https://threads.js.org/usage-advanced)
192
193## Webpack
194
195Threads.js works with webpack. Usually all you need to do is adding the
196[`threads-plugin`](https://github.com/andywer/threads-plugin).
197
198See [Build with webpack](https://threads.js.org/getting-started#build-with-webpack)
199on the website for details.
200
201<!--
202## API
203
204TODO
205-->
206
207## Debug
208
209We are using the [`debug`](https://github.com/visionmedia/debug) package to provide opt-in debug logging. All the package's debug messages have a scope starting with `threads:`, with different sub-scopes:
210
211- `threads:master:messages`
212- `threads:master:spawn`
213- `threads:master:thread-utils`
214- `threads:pool:${poolName || poolID}`
215
216Set it to `DEBUG=threads:*` to enable all the library's debug logging. To run its tests with full debug logging, for instance:
217
218```
219DEBUG=threads:* npm test
220```
221
222## License
223
224MIT