Installation ========================== ## Compilation When done developing, we can compile to Web Assembly or JavaScript for distribution. This is done by acquiring a `GHC` that supports WebAssembly or JavaScript. We recommend acquiring these backends using `GHCUp` or `Nix`. > [!TIP] > For new Haskell users we recommend using [GHCup](https://www.haskell.org/ghcup/) to acquire the [WASM](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/wasm.html) and [JS](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/javascript.html) backends. ##  Web Assembly > [!TIP] > The Haskell `miso` team currently recommends using the WASM backend as the default backend for compilation. Using [GHCup](https://www.haskell.org/ghcup/) you should be able to acquire the `GHC` `WASM` compiler. For instructions on how to add a third-party channel with [GHCup](https://www.haskell.org/ghcup/), please see their official [README.md](https://gitlab.haskell.org/haskell-wasm/ghc-wasm-meta#using-ghcup) > [!TIP] > For [Nix](nixos.org) users it is possible to acquire the WASM backend via a [Nix flake](https://nixos-and-flakes.thiscute.world/) ```bash $ nix shell 'gitlab:haskell-wasm/ghc-wasm-meta?host=gitlab.haskell.org' ``` > [!NOTE] > This will put `wasm32-wasi-cabal` in your `$PATH`, along with `wasm32-wasi-ghc`. Since the WASM backend is relatively new, the ecosystem is not entirely patched to support it. Therefore, we will need to use patched packages from time to time. > [!TIP] > Instead of using a `nix shell`, it's possible to install the GHC WASM Flake into your environment so it will always be present on `$PATH` ```bash $ nix profile install 'gitlab:haskell-wasm/ghc-wasm-meta?host=gitlab.haskell.org' ``` Update your `cabal.project` to the following - `cabal.project` ```yaml packages: . with-compiler: wasm32-wasi-ghc with-hc-pkg: wasm32-wasi-ghc-pkg source-repository-package type: git location: https://github.com/dmjio/miso branch: master if arch(wasm32) -- Required for TemplateHaskell. When using wasm32-wasi-cabal from -- ghc-wasm-meta, this is superseded by the global cabal.config. shared: True ``` Call `wasm32-wasi-cabal build --allow-newer` and a `WASM` payload should be created in `dist-newstyle/` directory. ```bash $ wasm32-wasi-cabal update $ wasm32-wasi-cabal build --allow-newer ``` ```bash Configuration is affected by the following files: - cabal.project Resolving dependencies... Build profile: -w ghc-9.12.2.20250327 -O1 In order, the following will be built (use -v for more details): - app-0.1.0.0 (exe:app) (configuration changed) Configuring executable 'app' for app-0.1.0.0... Preprocessing executable 'app' for app-0.1.0.0... Building executable 'app' for app-0.1.0.0... [1 of 1] Compiling Main ( Main.hs, dist-newstyle/build/wasm32-wasi/ghc-9.12.2.20250327/app-0.1.0.0/x/app/build/app/app-tmp/Main.o ) [2 of 2] Linking dist-newstyle/build/wasm32-wasi/ghc-9.12.2.20250327/app-0.1.0.0/x/app/build/app/app.wasm ``` You have now successfully compiled a Haskell `miso` application to WebAssembly 🔥 *** But, we're not done yet. In order to view this in the browser there are still a few more steps. We need to add some additional files that emulate the [WASI interface](https://github.com/WebAssembly/WASI) in the browser ([A browser WASI shim](https://github.com/bjorn3/browser_wasi_shim)). > [!NOTE] > The GHC WASM backend can execute any Haskell program in a WASI-compliant runtime (e.g. [wasmtime](https://github.com/bytecodealliance/wasmtime)) > See the [official documentation](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/wasm.html) for more information. To start, we recommend creating an `app.wasmexe` folder to store the additional artifacts required. > [!TIP] > We recommend using an up-to-date `node` version (currently tested with `v24.2.0`) to ensure `post-link.mjs` works properly. ```bash # Creates the directory for hosting $ mkdir -v app.wasmexe mkdir: created directory 'app.wasmexe' # This command produces `ghc_wasm_jsffi.js`, which ensures our FFI works properly. $ $(wasm32-wasi-ghc --print-libdir)/post-link.mjs \ --input $(wasm32-wasi-cabal list-bin app --allow-newer) \ --output app.wasmexe/ghc_wasm_jsffi.js # This copies the `app.wasm` payload into `app.wasmexe` $ cp -v $(wasm32-wasi-cabal list-bin app --allow-newer) app.wasmexe Configuration is affected by the following files: - cabal.project '/home/dmjio/Desktop/miso/sample-app/dist-newstyle/build/wasm32-wasi/ghc-9.12.2.20250327/app-0.1.0.0/x/app/build/app/app.wasm' -> 'app.wasmexe' ``` > [!NOTE] > Along with the above `ghc_wasm_jsffi.js` and `app.wasm` artifacts, we also need to include an `index.html` and an `index.js` for loading the WASM payload into the browser. - `index.html` ```html