miso

Getting started

Installation

miso applications compile to WebAssembly (the primary target) with the GHC WASM backend, or to JavaScript with the GHC JS backend. The quickest way to a working toolchain is the miso flake.

1. Build and serve the sampler

With nix installed (flakes enabled), clone the sampler and run it — the flake provides the whole WASM toolchain (wasm32-wasi-cabal, wasm32-wasi-ghc, http-server, ghciwatch):

$ git clone https://github.com/haskell-miso/miso-sampler && cd miso-sampler
$ nix develop .#wasm --command bash -c 'make all && make serve'

Then open http://localhost:8080. make all runs wasm32-wasi-cabal build, copies static/ to public/, generates the JS FFI glue with post-link.mjs and shrinks the .wasm with wasm-opt. make watch starts ghciwatch with the WASM browser GHCi for hot reload. A JavaScript-backend shell (javascript-unknown-ghcjs-ghc) is available as .#ghcjs, and a plain GHC shell as the default.

2. Wire up your own project

A miso executable is an ordinary cabal executable. For WASM builds it is linked as a reactor and exports hs_start:

executable app
  main-is: Main.hs
  build-depends: base, miso
  if arch(wasm32)
    ghc-options:
      -no-hs-main
      -optl-mexec-model=reactor
      "-optl-Wl,--export=hs_start"
    cpp-options: -DWASM

and Main.hs exports its entry point when compiled for WASM:

{-# LANGUAGE CPP #-}
module Main where

import Miso

#ifdef WASM
foreign export javascript "hs_start" main :: IO ()
#endif

main :: IO ()
main = startApp defaultEvents app

The index.js loader instantiates the module with a WASI shim and calls hs_start. Copy it from the sampler's static/ folder to begin.

Cabal flags

FlagPurpose
ssrEnable when rendering Views to HTML on a server: text HTML-encodes and hydrateModel is honoured.
template-haskellExpose Miso.Lens.TH (makeLenses, makeClassy).
nativeEnable the Lynx native backend (Miso.Native).
productionUse the minified JavaScript runtime.