An example GHCJS + Miso single page application.
897
An example GHCJS + Miso single page application.

The application is packed as a Docker image, so you can launch it with a single command.
docker run -d -p 4000:4000 ytaka23/miso-tutorial-app:latest
Access http://localhost:4000.
You can also build the application from source code. Note that, if it's your first experience of GHCJS, it takes a long time to set up the compiler.
git clone https://github.com/y-taka-23/miso-tutorial-app.git
cd miso-tutorial-app
./run.sh
The script prepares compilation environments according to each stack.yaml, builds both of the client/server side stuffs and starts the web server. Access http://localhost:4000.
This project is ported from Elm implementation. Miso framework aims to provide "The Elm Architecture" for GHCJS, thus its architecture looks very close to the original Elm application. Nevertheless, the Miso implementation has several interesting differences.
Isomorphism, also known as server side rendering (SSR,) is one of the most remarkable features of Miso framework. Implementing both of the client and server sides in the same language, that is Haskell, Miso can reuse most of the application and optimize the cost of renering.
As with The Elm Architecture, an isomorphic Miso application consists of the following parts:
In Miso isomorphism, the models, actions and views are "shared" between the client/server sides. When a browser accesses the web server for the first time, the server returns an HTML file built from the initial model and the view logic. Next, when the user changes the current URL (by a subscription) or accesses external APIs (by an effect,) JavaScript re-renders the page by the shared view and routing logic in the client side only.
| Client | Shared | Server |
|---|---|---|
| Update | Model | (Servant Server) |
| Subscription | Action | |
| Effect | View | |
| Routing |
On the top of Haskell's powerful type system, Miso can denote its routing as types, in the similar way with Servant. The following defines three routes : /, /players and /players/:id as a single page application.
type Route =
TopRoute
:<|> ListRoute
:<|> EditRoute
type TopRoute = View Action
type ListRoute = "players" :> View Action
type EditRoute = "players" :> Capture "ident" PlayerId :> View Action
Besides, for the server side, Miso converts and extends the client side routes to define the APIs. In the following snippet there are four APIs:
JsonApi returns JSON files for XHR by Miso effects; /api/players and /api/players/:id.IsomorphicApireturns HTML files generated by SSR.StaticApi returns static resources including JavaScript.NotFoundApi returns the 404 error page.type Api = JsonApi :<|> IsomorphicApi :<|> StaticApi :<|> NotFoundApi
type JsonApi =
"api" :> "players" :> Get '[JSON] [Player]
:<|> "api" :> "players" :> Capture "id" PlayerId
:> ReqBody '[JSON] Player :> Put '[JSON] NoContent
type IsomorphicApi = ToServerRoutes Route HtmlPage Action
type StaticApi = "static" :> Raw
type NotFoundApi = Raw
In The Elm Architecture, the update function has a type:
update : Msg -> Model -> (Model, Cmd Msg)
On the other hand in Miso:
updateModel :: Action -> Model -> Effect Action Model
The Effect type is a sort of aliases, to handle IO actions asynchronously, implemented as:
data Effect action model = Effect model [Sub action]
type Sub action = Sink action -> IO ()
type Sink action = action -> IO ()
It means that Miso can do arbitrary IO actions as effects. Moreover it provides several constructors to simply denote update with/without effects:
(<#) :: model -> IO action -> Effect action model
noEff :: model -> Effect action model
Let's back to the example. Here fetchPlayers is just an IO action to fetch a player list via external connection. updateModel passes the result to SetPlayers, then again updateModel sets the player list without effects.
fetchPlayers :: IO (Either String [Player])
updatePlayer :: Either String Player -> Model -> Model
updateModel FetchPlayers m = m <# do
SetPlayers <$> fetchPlayers
updateModel (SetPlayer eP) m = noEff $ updatePlayer eP m
For more detail, see the implementation.
Content type
Image
Digest
Size
6.6 MB
Last updated
about 8 years ago
docker pull ytaka23/miso-tutorial-app