This is a base for attempting to determine how to use WebAssembly with Angular 9.
First attempt uses the embedded wasm approach where we inlude the built wasm with the Angular app:
-
src/app/assembly/stats_client_wasm_b.wasm
-
src/app/assembly/stats_client_wasm.js
The WebAssembly component used is stored here: https://github.com/anthonyikeda/stats-client
Here are some articles and repos that I’ve been using to try and make this work.
The WebAssembly was packaged with wasm-pack and targetted to web
as the compilation.
The stats_client_wasm.js
and stats_client_wasm_d.wasm
files were then copied to the src/app/assembly
directory.
There is also a nodejs packaged version attached to the package.json but not imported into the project just yet - got to work out how to use it.
Branch: index_import
This branch attempts to keep the webassembly component local to the app and load it in the index.html
file.
<head>
<meta charset="utf-8">
<title>DashboardUi</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script>
const rust = import('./assembly');
rust
.then(m => {
console.log(m);
m.process_message("Hello");
})
.catch(console.error);
</script>
The problem we have here is the fact that we get a HTTP 404 not found because we are trying to import from what looks like a route, not an actual path.
Assumption: Using a HTTP server like NGINX or HTTPD might address this loading issue.
So this attempts to set up NGINX to serve up the static Angular content and the WASM/JS bundle.
An NGINX server conf was created:
server {
listen 80;
server_name dashboard-ui.local;
location /app {
alias /Users/sites/dashboard-ui;
index index.html index.htm;
}
location /assembly {
root /Users/sites;
autoindex on;
}
}
The mime.types
file in the NGINX server also needs to be updated with the application/wasm
mime-type:
...
application/wasm wasm;
application/java-archive jar war ear;
...
The WebAssembly code is packaged with wasm-pack:
$ wasm-pack build --target web
To create a web friendly package at <src>/pkg
the code from this directory is then copied to the hosting directory (/Users/sites/assembly
).
This setup ensures that the application runs as a static Single Page Application at: http://dashboard-ui.local/app
The WebAssembly components should be served up from: http://dashboard-ui.local/assembly
The challenge here has been properly exposing the /assembly
mapping since if you enable autoindex in the dashboard.conf
file for the /assembly
mapping, NGINX serves up an auto-generated HTML file listing all the files in the directory giving a content-type of text/html
. This means loading the WebAssembly components using:
<script type="module">
const rust = import('/assembly');
rust
.then(m => {
m.process_message('Hello');
})
.catch(console.error);
</script>
will fail because the autogenerated index.html file gets returned instead of the import ready the actual files in the mapping. It seems explicit calls to the correct files need to be made. If you disable autoindex then you just get a 403 Forbidden.
If you try and reference the Javascript file directly:
<script type="module">
const rust = import('/assembly/stats-client-wasm.js');
rust
.then(m => {
m.process_message('Hello');
})
.catch(console.error);
</script>
Then you get the error:
TypeError: Cannot read property '__wbindgen_malloc' of undefined at Module.process_message (stats_client_wasm.js:78) at (index):18
So far there is only one report of this issue on the web which seems to be a bug that’s been patched.