# Haskell WASM REPL Template A template project to create [REPLs](https://en.wikipedia.org/wiki/REPL) with [Haskell](https://haskell.org) that run in the browser using [WASM](https://en.wikipedia.org/wiki/WebAssembly). ## Running The project is orchestrated using [Nix]. After you enter the Nix shell by running `nix-shell`, you can the following commands: - `clean`: Cleans the Cabal build directory. - `compile`: Build the project using Cabal. - `run`: Builds and run the project using Cabal. - `build`: Builds the project using Nix. Builds dynamically linked executables. - `build-static`: Builds the project using Nix. Builds statically linked executables. Requires either to be run on Linux, or to have a Nix [Linux builder](https://nixcademy.com/posts/macos-linux-builder/) configured. - `build-docker`: Runs the previous step and creates a [Docker](https://en.wikipedia.org/wiki/Docker_(software)) image with the statically linked executables using Nix. Requires Docker to be set up on the build machine. The image will also contain the contents of the `data` directory. - `build-wasm`: Runs the previous step and converts the Docker image into a WASM binary `out.wasm`, and copies it into the `web` directory. - `serve`: Serves the contents of the `web` directory over HTTP locally. The `build-static`, `build-docker`, and `build-wasm` commands take a long time to finish when run for the first time, maybe even hours. The built artifacts are cached so subsequent builds finish in minutes. ## Deploying You can copy the contents of the `web` directory to your server and serve them as a static website. For the browser to load the WASM file, the server needs to send the following headers: ```http Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` It is recommended to configure your server to serve pre-compressed assets, and to pre-compress the `out.wasm` file using Brotli or Gzip. This reduces the browser load time of the website by more than half. It is also recommended to configure cache-control headers for the assets in your server so that browsers cache them. If you change the `out.wasm` file frequently, it is recommended to figure out a cache-busting policy for it. ## Developing This project uses the following tools/components: - [Nix] is used to build statically linked executables and Docker images. - [Niv](https://github.com/nmattia/niv) is used to pin Nix dependencies. - [container2wasm](https://github.com/ktock/container2wasm) is used to convert Docker images to WASM binaries. The [WASI example](https://github.com/ktock/container2wasm/tree/main/examples/wasi-browser/htdocs) from container2wasm forms the basis of the `web` directory. - [Xterm.js](https://github.com/xtermjs/xterm.js/) is used to create the web terminal in browsers. - [Xterm-pty](https://github.com/mame/xterm-pty/) is used to run the WASM binary on Xterm. - [Xterm-fit-addon](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-fit) is used to make the web terminal fullscreen. ## Using For unknown reasons, the WASM REPL does not work on Safari. Please use it in Firefox or Chrome. [Nix]: https://nixos.org