Dart & Flutter Packages by dev-cetera.com & contributors.
A modern utility to load and use wasm-bindgen modules in Flutter web apps, with support for the WasmGC (--wasm) compiler.
See this Live Example. It runs some Rust functions and was compiled with the --wasm
flag. Here is the Source Code.
- WasmGC Compatible: Built from the ground up for
flutter build web --wasm
. - Minimal Boilerplate: A single line in your
index.html
and one function call in Dart is all you need to get started. - Type-Safe: Encourages using dart: js_interop's static types for robust function calls.
- No Manual JS: A generic, reusable loader script handles the complexities of WASM instantiation.
- Multi-Language Support: Works with any language that compiles to WASM and uses wasm-bindgen (e.g., Rust, C/C++ with Emscripten).
Follow these steps to get your WASM module running in your Flutter app.
First, build your code to a WASM module. Here is a Rust example that matches the Dart API below.
Cargo.toml
Make sure you have wasm-bindgen
as a dependency and the cdylib
crate-type.
[package]
name = "my_module"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
src/lib.rs
Annotate any function you want to call from Dart with #[wasm_bindgen]
.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub fn is_answer_forty_two(x: i32) -> bool {
x == 42
}
Run wasm-pack
to compile the code. This will create a pkg directory.
wasm-pack build --target web
Copy the generated pkg directory into your Flutter project's web/assets/
folder.
Your final file structure should look like this:
flutter_project/
└── web/
├── assets/
│ └── my_module/
│ ├── my_module.js
│ └── my_module_bg.wasm
├── index.html
└── loader.js <------ OPTIONAL
Or in Flutter, define the assets path in your pubspec.yaml
:
flutter:
assets:
- my_module/
You must include the loader.js
script to handle the WASM initialization.
Add the following <script>
tag to your web/index.html
file:
<head>
<!-- ... -->
<script src="https://cdn.jsdelivr.net/gh/dev-cetera/df_wasm_interop@v0.1.2/web/loader.js"></script>
</head>
-
Create a new file in your Flutter project at
web/loader.js
and paste the contents of the loader script into it. You can find the official loader script here: loader.js on GitHub -
Add the following
<script>
tag to yourweb/index.html
file:
<head>
<!-- ... -->
<script src="loader.js"></script>
</head>
This file translates your WASM functions into a clean Dart API.
// ignore_for_file: non_constant_identifier_names
import 'dart:js_interop';
@JS()
@staticInterop
class MyModule {} // leave it blank
extension MyModuleExtension on MyWasmApi {
external int add(int a, int b);
@protected // hide "is_answer_forty_two" from the developer
external bool is_answer_forty_two(int x); // make sure the function signatures match exactly!
bool isAnswerFortyTwo(int x) => is_answer_forty_two(x); // rename is_answer_forty_two
}
MyWasmApi createMyWasmApi() {
final module = await WasmModule.initialize(jsPath: 'assets/my_module/my_module.js');
return module.instance as MyWasmApi;
}
void main() async {
final api = await createMyWasmApi();
print(api.add(1, 2));
print(api.isAnswerFortyTwo(42));
runApp(MyApp());
}
☝️ Please refer to the API reference for more information.
This is an open-source project, and we warmly welcome contributions from everyone, regardless of experience level. Whether you're a seasoned developer or just starting out, contributing to this project is a fantastic way to learn, share your knowledge, and make a meaningful impact on the community.
- Buy me a coffee: If you'd like to support the project financially, consider buying me a coffee. Your support helps cover the costs of development and keeps the project growing.
- Find us on Discord: Feel free to ask questions and engage with the community here: https://discord.gg/gEQ8y2nfyX.
- Share your ideas: Every perspective matters, and your ideas can spark innovation.
- Help others: Engage with other users by offering advice, solutions, or troubleshooting assistance.
- Report bugs: Help us identify and fix issues to make the project more robust.
- Suggest improvements or new features: Your ideas can help shape the future of the project.
- Help clarify documentation: Good documentation is key to accessibility. You can make it easier for others to get started by improving or expanding our documentation.
- Write articles: Share your knowledge by writing tutorials, guides, or blog posts about your experiences with the project. It's a great way to contribute and help others learn.
No matter how you choose to contribute, your involvement is greatly appreciated and valued!
If you're enjoying this package and find it valuable, consider showing your appreciation with a small donation. Every bit helps in supporting future development. You can donate here: https://www.buymeacoffee.com/dev_cetera
This project is released under the MIT License. See LICENSE for more information.