flutter_node_worker
is a tool and library for Flutter Web that enables multithreading via Web Workers written in Node.js.
Unlike Flutter on other platforms, Isolate is not supported on Web, making it impossible to perform heavy computations outside the main thread. To avoid blocking the UI during long operations, it is recommended to use Web Workers, and this is what this package provides.
This is especially useful for cryptographic operations, parsing, computing, and any CPU-intensive operations.
-
βοΈ
Node.js
worker logic using anynpm
packages -
βοΈ Automatic project template generation (
init
) -
β‘ Build via
Vite
-
π§ Integration of Web Workers into Flutter with a type-safe API
-
π― Support for multi-command logic and data transfer in both directions
- Cryptographic methods
- Large calculations (parsing, math, crypto)
- JSON β Protobuf / MsgPack conversion
- Working with npm libraries directly from Flutter
- Parsers, transformers and generators
- π Description
- π¦ Features
- π§ Where to use
- Table of contents
- π₯ Get started
- π§© Structure
- π API
- CLI-commands
- π οΈ Dependencies
- πΌοΈ Demo
- π What's Next
- π€ Support
- π€ Contributors
dependencies:
flutter_node_worker: any
or using command
flutter pub add flutter_node_worker
Install dependencies:
flutter pub get
dart run flutter_node_worker init --dir my_worker --name encryptor
Creates a template in the my_worker/
folder with the worker name encryptor
.
Additionally, this will generate a Makefile
and a Bash script fnw
in your project root, allowing you to run commands with shorter syntax.
π See CLI-commands below for details on using dart run
, ./fnw
, or make
.
Inside src/encryptor.js
(for example, a cryptographic method for encrypting data):
import forge from 'node-forge';
self.onmessage = function (e) {
const { command, data } = e.data;
if (command === "encrypt") {
const result = encrypt(data.message, data.password);
self.postMessage(JSON.stringify({ status: "success", command, result: { message: result } }));
}
}
function encrypt(message, password) {
// Encryption logic
}
If the worker will use a third-party library, it can be imported as an ES module, but don't forget to install it using:
dart run flutter_node_worker install <package-name> --dir my_worker
or:
cd my_worker
npm install <package-name>
dart run flutter_node_worker build --dir my_worker --out-dir ../web/workers
or:
cd my_worker
npm run build
Creates a built module worker in web/workers/
with the worker name + module.js (in this example encryptor_module.js
). It can now be used in Dart code. If you do not specify --out-dir
, the worker will be built in my_worker/dist/
. The --out-dir
should be specified relative to the worker's directory, not the project root.
For example, if your worker is in my_worker
, use --out-dir=../web/workers
.
final worker = FlutterNodeWorker(path: "my_worker/dist/encryptor_module.js");
final result = await worker.compute(
command: "encrypt",
data: {"message": "Hello", "password": "secret"},
);
my_worker/
βββ package.json
βββ vite.config.js
βββ src/
β βββ encryptor.js // Your worker logic
βββ dist/
β βββ encryptor_module.js // Compiled worker module
FlutterNodeWorker({required String path})
-
compute({command, data, computeOnce})
Sends a command and data to the worker and returns the result.-
If
computeOnce = true
(default isfalse
), the worker will automatically exit after the command is executed - useful for rare operations like generating cryptographic keys on registration. -
If
computeOnce = false
, the worker remains active, which is suitable for frequent tasks such as encrypting chat messages.
-
-
terminate()
Manually terminates the worker, freeing up resources.
Each command can be run in one of three ways:
Method | Example |
---|---|
dart run |
dart run flutter_node_worker init --dir my_worker --name encryptor |
Bash script | ./fnw init --dir my_worker --name encryptor |
Makefile | make init dir=my_worker name=encryptor |
dart run flutter_node_worker init --dir my_worker --name encryptor
./fnw init --dir my_worker --name encryptor
make init dir=my_worker name=encryptor
dart run flutter_node_worker build --dir my_worker --out-dir ../web/workers
./fnw build --dir my_worker --out-dir ../web/workers
make build-worker dir=my_worker out-dir=../web/workers
The --out-dir
should be specified relative to the worker's directory, not the project root.
For example, if your worker is in my_worker
, use --out-dir=../web/workers
.
dart run flutter_node_worker add --dir my_worker --name decryptor
./fnw add --dir my_worker --name decryptor
make add dir=my_worker name=decryptor
dart run flutter_node_worker install uuid --dir my_worker
./fnw install uuid --dir my_worker
make install dir=my_worker pkgs=uuid
dart run flutter_node_worker uninstall uuid --dir my_worker
./fnw uninstall uuid --dir my_worker
make uninstall dir=my_worker pkgs=uuid
Argument | Abbreviation | Description |
---|---|---|
--dir |
-d |
The directory in which the command is executed (init , build , add , etc.) |
--name |
-n |
Worker name when initializing or adding a new one |
--out-dir |
-o |
Directory where the compiled module will be placed |
The demo application allows you to encrypt and decrypt a message using a password. For clarity, an animation has been added demonstrating that the main thread is not blocked - the UI remains responsive even when performing heavy operations.
By opening DevTools β Sources β Threads, you can see the active threads, including the Web Worker (cipher_module.js
), where the calculation takes place.
-
Cover the project with unit and integration tests
-
Switch from
dart:js
todart:js_interop
for safer and more typed work with JavaScript -
Improve Web Worker error handling
-
Add logging and notifications when the worker crashes
-
Support for custom templates and configurations
Open an issue or pull request. Any help is appreciated!
Thanks to all these amazing people: