• Stars
    star
    2,091
  • Rank 22,090 (Top 0.5 %)
  • Language
    Haskell
  • License
    BSD 3-Clause "New...
  • Created over 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

🍜 A tasty Haskell front-end framework

miso

A tasty Haskell front-end framework

Miso Slack Haskell Cachix GitHub Actions Hackage IRC #haskell-miso LICENSE

Miso is a small, production-ready, "isomorphic" Haskell front-end framework for quickly building highly interactive single-page web applications. It features a virtual-dom, recursive diffing / patching algorithm, attribute and property normalization, event delegation, event batching, SVG, Server-sent events, Websockets, type-safe servant-style routing and an extensible Subscription-based subsystem. Inspired by Elm, Redux and Bobril. Miso is pure by default, but side effects (like XHR) can be introduced into the system via the Effect data type. Miso makes heavy use of the GHCJS FFI and therefore has minimal dependencies. Miso can be considered a shallow embedded domain-specific language for modern web programming.

Table of Contents

Quick start

To get started quickly building applications, we recommend using the nix package manager with miso's binary cache provided by cachix. It is possible to use stack to build GHCJS projects, but support for procuring GHCJS has been removed as of stack 2.0. nix is used to procure a working version of GHCJS. If you're using cabal we assume you have obtained GHCJS by other means. All source code depicted below for the quick start app is available here.

Begin

To build the sample-app with nix, execute the commands below:

# optional use of cache
nix-env -iA cachix -f https://cachix.org/api/v1/install
# optional use of cache
cachix use miso-haskell
git clone https://github.com/dmjio/miso
cd miso/sample-app
nix-build
open ./result/bin/app.jsexe/index.html

The above commands will add miso's binary cache to your nix installation (support for both Linux and OSX). nix-build will fetch the dependencies from miso's cache and build the sample application.

Nix

Nix is a more powerful option for building web applications with miso since it encompasses development workflow, configuration management, and deployment. The source code for haskell-miso.org is an example of this.

If unfamiliar with nix, we recommend @Gabriel439's "Nix and Haskell in production" guide.

To begin, make the following directory layout:

➜  mkdir app && touch app/{Main.hs,app.cabal,default.nix} && tree app
app
|-- Main.hs
|-- app.cabal
`-- default.nix

Add a cabal file

➜  cat app/*.cabal
name:                app
version:             0.1.0.0
synopsis:            First miso app
category:            Web
build-type:          Simple
cabal-version:       >=1.10

executable app
  main-is:             Main.hs
  ghcjs-options:
    -dedupe
  build-depends:       base, miso
  default-language:    Haskell2010

Write a default.nix (this will fetch a recent version of miso). miso will provide you with a working nixpkgs named pkgs. callCabal2nix will automatically produce a nix expression that builds your cabal file.

with (import (builtins.fetchGit {
  url = "https://github.com/dmjio/miso";
  ref = "refs/tags/1.8";
}) {});
pkgs.haskell.packages.ghcjs.callCabal2nix "app" ./. {}

Add the source from Sample Application to app/Main.hs

Build the project

nix-build

Open the result

open ./result/bin/app.jsexe/index.html

For development with nix, it can be nice to have cabal present for building. This command will make it available in your PATH.

nix-env -iA cabal-install -f '<nixpkgs>'

To be put into a shell w/ GHCJS and all the dependencies for this project present, use nix-shell.

nix-shell -A env

To view the dependencies for your project, call ghcjs-pkg list when inside the shell.

nix-shell -A env --run 'ghcjs-pkg list'

To build the project with cabal after entering the nix-shell

nix-shell -A env --run 'cabal configure --ghcjs && cabal build'

For incremental development inside of the nix-shell we recommend using a tool like entr to automatically rebuild on file changes, or roll your own solution with inotify.

ag -l | entr sh -c 'cabal build'

Architecture

For constructing client and server applications, we recommend using one cabal file with two executable sections, where the buildable attribute set is contingent on the compiler. An example of this layout is here. For more info on how to use stack with a client/server setup, see this link. For more information on how to use nix with a client/server setup, see the nix scripts for https://haskell-miso.org.

Examples

TodoMVC

Flatris

2048

Snake

Mario

Miso Plane (Flappy Birds)

Websocket

SSE

XHR

Router

SVG

Canvas 2D

ThreeJS

Simple

File Reader

WebVR

Pixel Card Wars

Haddocks

GHCJS

GHC

Sample application

-- | Haskell language pragma
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

-- | Haskell module declaration
module Main where

-- | Miso framework import
import Miso
import Miso.String

-- | Type synonym for an application model
type Model = Int

-- | Sum type for application events
data Action
  = AddOne
  | SubtractOne
  | NoOp
  | SayHelloWorld
  deriving (Show, Eq)

-- | Entry point for a miso application
main :: IO ()
main = startApp App {..}
  where
    initialAction = SayHelloWorld -- initial action to be executed on application load
    model  = 0                    -- initial model
    update = updateModel          -- update function
    view   = viewModel            -- view function
    events = defaultEvents        -- default delegated events
    subs   = []                   -- empty subscription list
    mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')
    logLevel = Off                -- used during prerendering to see if the VDOM and DOM are in sync (only applies to `miso` function)

-- | Updates model, optionally introduces side effects
updateModel :: Action -> Model -> Effect Action Model
updateModel action m =
  case action of
    AddOne
      -> noEff (m + 1)
    SubtractOne
      -> noEff (m - 1)
    NoOp
      -> noEff m
    SayHelloWorld
      -> m <# do consoleLog "Hello World" >> pure NoOp

-- | Constructs a virtual DOM from a model
viewModel :: Model -> View Action
viewModel x = div_ [] [
   button_ [ onClick AddOne ] [ text "+" ]
 , text (ms x)
 , button_ [ onClick SubtractOne ] [ text "-" ]
 ]

Transition application

An alternative, more powerful interface for constructing miso applications is using the Transition interface. Transition is based on the StateT monad transformer, and can be used to construct components. It also works very nicely with lenses based on MonadState (i.e. (.=), (%=),(+=),(-=)).

-- | Haskell language pragma
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}

-- | Haskell module declaration
module Main where

-- | Miso framework import
import Miso
import Miso.String

-- | Lens import
import Control.Lens

-- | Type synonym for an application model
data Model
  = Model
  { _counter :: Int
  } deriving (Show, Eq)

counter :: Lens' Model Int
counter = lens _counter $ \record field -> record { _counter = field }

-- | Sum type for application events
data Action
  = AddOne
  | SubtractOne
  | NoOp
  | SayHelloWorld
  deriving (Show, Eq)

-- | Entry point for a miso application
main :: IO ()
main = startApp App {..}
  where
    initialAction = SayHelloWorld -- initial action to be executed on application load
    model  = Model 0              -- initial model
    update = fromTransition . updateModel -- update function
    view   = viewModel            -- view function
    events = defaultEvents        -- default delegated events
    subs   = []                   -- empty subscription list
    mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')
    logLevel = Off                -- used during prerendering to see if the VDOM and DOM are in sync (only applies to `miso` function)

-- | Updates model, optionally introduces side effects
updateModel :: Action -> Transition Action Model ()
updateModel action =
  case action of
    AddOne
      -> counter += 1
    SubtractOne
      -> counter -= 1
    NoOp
      -> pure ()
    SayHelloWorld
      -> scheduleIO_ (consoleLog "Hello World")

-- | Constructs a virtual DOM from a model
viewModel :: Model -> View Action
viewModel x = div_ [] [
   button_ [ onClick AddOne ] [ text "+" ]
 , text . ms $ x^.counter
 , button_ [ onClick SubtractOne ] [ text "-" ]
 ]

Live reload with JSaddle

It is possible to build miso applications with ghcid, jsaddle that allow live reloading of your application in reponse to changes in application code. See the README in the sample-app-jsaddle folder for more information.

Docker

Developing miso applications inside a Docker container is supported (allows applications to be built on Windows). See the README in the docker folder for more information.

Building examples

The easiest way to build the examples is with the nix package manager

git clone https://github.com/dmjio/miso && cd miso && nix-build --arg examples true

This will build all examples and documentation into a folder named result

➜  miso git:(master) βœ— tree -d ./result/bin
./result/bin
|-- canvas2d.jsexe
|-- compose-update.jsexe
|-- file-reader.jsexe
|-- mario.jsexe
|   `-- imgs
|-- mathml.jsexe
|-- router.jsexe
|-- simple.jsexe
|-- svg.jsexe
|-- tests.jsexe
|-- threejs.jsexe
|-- todo-mvc.jsexe
|-- websocket.jsexe
`-- xhr.jsexe

To see examples, we recommend hosting them with a webserver

cd result/bin/todo-mvc.jsexe && nix-shell -p python --run 'python -m SimpleHTTPServer'
Serving HTTP on 0.0.0.0 port 8000 ...

Coverage

The core algorithmic component of miso is diff.js. It is responsible for all DOM manipulation that occurs in a miso application and has 100% code coverage. Tests and coverage made possible using jsdom and jest.

To run the tests and build the coverage report:

cd miso/tests
npm i
npm run test
## Or by using `yarn` instead of `npm`:
# yarn
# yarn test

Isomorphic

Isomorphic javascript is a technique for increased SEO, code-sharing and perceived page load times. It works in two parts. First, the server sends a pre-rendered HTML body to the client's browser. Second, after the client javascript application loads, the pointers of the pre-rendered DOM are copied into the virtual DOM, and the application proceeds as normal. All subsequent page navigation is handled locally by the client, avoiding full-page postbacks as necessary.

The miso function is used to perform the pointer-copying behavior client-side.

For more information on how miso handles isomorphic javascript, we recommend this tutorial.

Pinning nixpkgs

By default miso uses a known-to-work, pinned version of nixpkgs.

Binary cache

nix users on a Linux or OSX distro can take advantage of a binary cache for faster builds. To use the binary cache follow the instructions on cachix.

cachix use miso-haskell

Benchmarks

According to benchmarks, miso is among the fastest functional programming web frameworks, second only to Elm.

Maintainers

@dmjio

Commercial Users

Contributing

Feel free to dive in! Open an issue or submit PRs.

See CONTRIBUTING for more info.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

License

BSD3 Β© David Johnson

More Repositories

1

stripe

πŸ’° Stripe API
Haskell
175
star
2

envy

😠 Environmentally friendly environment variables
Haskell
147
star
3

Julio

Julia embedded in Haskell
Nix
53
star
4

google-translate

γŠ™οΈ Google Translate API
Haskell
51
star
5

hackernews

πŸ“° HackerNews API
Haskell
40
star
6

LearnOpenGL.hs

LearnOpenGL.com examples ported to Haskell
Haskell
27
star
7

s3-signer

☁️ Presigned S3 URLs for Haskell
Haskell
24
star
8

bittrex

πŸ’Έ Haskell bindings to the Bittrex cryptocurrency exchange
Haskell
24
star
9

graphql-meta

Lexing, parsing, pretty-printing, and metaprogramming facilities for dealing with GraphQL schemas and queries
Haskell
21
star
10

Assembler.py

Simple assembler written in Python that translates assembly code into binary. Based on the nand2tetris Hack platform specification
Assembly
21
star
11

LC3

πŸ’Ύ The LC3 virtual machine
Haskell
20
star
12

servant-from-scratch

Yet another Haskell servant talk
Haskell
12
star
13

c-ffi-example

Example usage of the Haskell C FFI with hsc2hs
Haskell
11
star
14

miso-from-html

Lex, parse and pretty print HTML as Miso View syntax
Haskell
9
star
15

AdventOfCode2018

Christmas code don't write itself
Haskell
9
star
16

ses-html

πŸ“§ SES SendEmail for Haskell
Haskell
9
star
17

typed-interpolation

Type-level interpolations in various forms
Haskell
9
star
18

tripletown

Console-based version of TripleTown
Haskell
8
star
19

ext-stg-interpreter-talk

Presentation on the external STG interpreter from Csaba Hruska
8
star
20

scythe

Fast, RFC-4180 compliant, CSV lexing.
Haskell
8
star
21

type-level-json

RFC8259 compliant JSON parser, at the type level.
Haskell
8
star
22

aoc2017

πŸŽ„ Advent of code 2017 ... ho' ho' ho', so much code' code' code', merry christmas!
Haskell
8
star
23

vm

A tiny virtual machine
Haskell
7
star
24

nixFromStack

Generate nix expressions from stack files
Nix
7
star
25

Jaskell

A compiler for the Jack Programming language, written in Haskell.
Haskell
7
star
26

miso-presentation

Presentation on miso - wip
7
star
27

servant-selda

Experiments with Servant and Selda
Haskell
7
star
28

servant-route

Type-safe web routes for servant DSLs
Haskell
7
star
29

call-swift-from-haskell

Call a Hello World Swift function from Haskell
Haskell
6
star
30

aoc2020

Advent of Code 2020
Haskell
6
star
31

grin-chat

Talk about GRIN
6
star
32

War

War in Haskell
Haskell
6
star
33

lens-th-rewrite

GHC plugin to rewrite lens Template Haskell splices into pure functions
Haskell
6
star
34

pg-query

Haskell bindings to libpg-query
Haskell
6
star
35

ghcjs-mithril

Haskell bindings to mithril.js
JavaScript
5
star
36

compiler-in-haskell

Just a toy compiler written in Haskell.
Haskell
5
star
37

aoc2021

Haskell
5
star
38

trie

This Trie is so fly
Haskell
5
star
39

Hello-HaLVM

Example "Hello World" HaLVM web-server running on the Xen Hypervisor
Haskell
4
star
40

FiveCardDraw

An implementation of 5 Card Draw Poker in C with Monte Carlo Simulations
C
4
star
41

tstack

A concurrent, thread-safe, transactional stack
Haskell
4
star
42

servant-wasm

Servant support for delivering WebAssembly
Haskell
4
star
43

csv-benchmarks

Benchmarking CSV lexing w/ various Haskell CSV libraries.
Haskell
4
star
44

bitpay

bitpay api
Haskell
3
star
45

hello-rust-haskell-nix

Calling statically linked Rust from Haskell, using a Nix environment
Nix
3
star
46

TinyMap

A pure, strict and extremely space efficient HashMap with good asymptotics
Haskell
3
star
47

ipopt-hs

ipopt-hs for GHC 8.6.3 ( I didn't write these bindings )
Haskell
3
star
48

gce-hydra-nixops-nginx

Hydra behind nginx running on GCE deployed via nixops
Nix
3
star
49

circleci

Haskell bindings to CircleCI's API
Haskell
3
star
50

hackage-dep-scrape

Pet project for scraping HTML off hackage
Haskell
3
star
51

file-io

File I/O experiments in Haskell
Haskell
3
star
52

static-warp

Simple server to deliver static files
Haskell
3
star
53

functional-lexing-and-parsing-talk

Functional lexing and parsing talk
Haskell
3
star
54

remote-iserv

Cross-compile TH splices on iOS
Nix
3
star
55

coinbase

Coinbase.com API for Haskell
Haskell
3
star
56

HaLVM-Lightning-Talk

A hypothetical HaLVM lightning talk
CSS
3
star
57

CompactMap

A mirror repo of Lemmih's compact-map, 7.8.2 compatible
Haskell
2
star
58

aoc2022

Haskell
2
star
59

adhocdb

In-memory databse on-the-fly
Haskell
2
star
60

bootstrap-datagrid

A datagrid for Twitter Bootstrap 3
JavaScript
2
star
61

www.haskellstudy.com

A static site created with Hakyll to house the progress of an independent haskell study
Haskell
2
star
62

99Haskell

My attempt at solving the 99 prolog problems in Haskell
Haskell
2
star
63

wai-streams

io-streams for WAI
Haskell
2
star
64

waffle

Haskell API bindings to the Waffle.io project management tool
Haskell
2
star
65

bounded-queue

An implementation of a bounded queue
Haskell
2
star
66

persistent-generic

Generic facilities for working with Persistent classes
Haskell
2
star
67

v4

Amazon v4 request generation
Haskell
2
star
68

libvirt-hs

Mirror of http://hackage.haskell.org/package/libvirt-hs
Haskell
2
star
69

advent-of-code-2019

Ho' ho' ho', all that code' code' code', merry christmas
Haskell
2
star
70

Hangman

Hangman Haskell
Haskell
1
star
71

snaplet-ses-html

A snaplet for the ses-html package
Haskell
1
star
72

z3-haskell

Mirror of https://bitbucket.org/iago/z3-haskell
Haskell
1
star
73

HilbertRTree

Hilbert R-Tree in Haskell
Haskell
1
star
74

io-streams-http

Deprecated, use https://github.com/vertigomedia/http-client-streams
Haskell
1
star
75

chess

Chess in Haskell
Haskell
1
star
76

LatestPkgVersion

Command line utility to get the latest version number of any package on hackage
Haskell
1
star
77

abc

Mirror of abc verifier
C
1
star
78

openarms

Web service for Open Arms ministry in Chicago
Haskell
1
star
79

network-prototype

Client server implementation in io-streams
Haskell
1
star
80

persistent-th-rewrite

Rewrite persistent Template Haskell into pure functions and definitions.
Haskell
1
star
81

cryptopals

Cryptopals challenges
Haskell
1
star
82

demo-jobset

Demo package to be built by hydra CI
Nix
1
star
83

wordfreq

Word frequency counter written in haskell
JavaScript
1
star
84

WebServer

Simple web server implementation written in Haskell
Haskell
1
star
85

oracle-simple

Modern bindings to Oracle odpic... WIP
C
1
star
86

ghcjs-benchmark-test

GHCJS and JS DOM text node benchmark test
Haskell
1
star
87

PurelyFunctionalDataStructures

Some purely functional data structures
Haskell
1
star
88

hpodder

A rendition of the hpodder project from RWH. Using xml instead of HaXml.
Haskell
1
star
89

snaplet-dynamo

Snaplet for the dynamo package
Haskell
1
star
90

BerkeleyDB

A mirror repo of Lemmih's BerkeleyDB, 7.8.2 compatible
Haskell
1
star
91

selection_sort

Selection sort implemented in Rust
Rust
1
star
92

angular-snap-jwt

A prototype of angular.js, snap and JWT authentication
Haskell
1
star
93

HaskellLessons

Haskell Learning
Haskell
1
star
94

supervise

Facilitate the spawning, maintenance and resolution of asynchronous operations running concurrently
Haskell
1
star