Elm and Express: A Simple Client-Server Implementation

When I do a side project, I usually want to spin up something quickly, and most of my projects have some sort of client talking to a server. Recently, I’ve been exploring Elm, so I decided to find a quick way to put together a simple client and server using Elm and Express. Here’s what I’ve come up with.

The Express Server

I decided to use Express to build the server. Express is a lightweight framework for Node.js applications, so it does not take a lot of code to get something up and running. For client-server communication, I chose WebSockets. They’re easy to use with Elm, and so far, they have been pretty pain-free.

To get started, you need to install Express and the WebSockets module for Express in your project’s directory using npm:

npm install express

npm install express-ws

Now we can set up the skeleton of our Express server. Create a file server.js with the following code:


var express = require('express');
var app = express();
var expressWS = require('express-ws')(app);

var portNumber = 1234;

app.listen(portNumber, function() {
  console.log(`Listening on port ${portNumber}`);
});

// more to come here...

You can now run the server with this command:

node server.js

Back in the console, you should see a message telling you what port the server is listening to:

express-server-listening

Now let’s set up a WebSocket that clients can connect to. In server.js, add the following code:


app.ws('/hello', function(websocket, request) {
  console.log('A client connected!');

  websocket.on('message', function(message) {
    console.log(`A client sent a message: ${message}`);
    websocket.send('Hello, world!');
  });
});

And that’s all we need for our server to send and receive messages.

The Elm Client

The server is finished, so now we can start creating our Elm client. If you haven’t already, check out the Elm tutorial. It’ll go through how to install Elm. Since we’ll be following the basic architecture described there, it may be helpful to quickly read it over.

Create a new file client.elm and add the following code:


import Html exposing (..)
import Html.App as App
import Html.Events exposing (..)
import WebSocket

main : Program Never
main =
  App.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }


type alias Model = List String

type Msg
  = Send
  | Receive String


init : (Model, Cmd Msg)
init =
  (["Welcome!"], Cmd.none)


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Send ->
      (model, WebSocket.send "ws://localhost:1234/hello" "Hello, server!")

    Receive message ->
      ((List.append model [message]), Cmd.none)


subscriptions : Model -> Sub Msg
subscriptions model =
  WebSocket.listen "ws://localhost:1234/hello" Receive


view : Model -> Html Msg
view model =
  let
    renderMessage msg =
      div [] [ text msg ]
  in
    div []
      [ div [] (List.map renderMessage model)
      , button [onClick Send] [text "Send message to server!"]
      ]

There’s nothing too fancy going on here. To interact with our server, we just needed a few things:

  • The Send action, which is triggered by clicking the button, sends a message to the specified route.
  • A listener to the WebSocket in our subscriptions, which will watch out for incoming messages and trigger the Receive action.

Before you can run this, you have to install the WebSocket library with the following command: elm package install elm-lang/websocket.

With that, our application should be ready to run. Assuming the Express server is running, fire up your Elm client with elm-reactor and open up http://localhost:8000/client.elm on a browser. You should be able to see the button we created. Clicking on that button will send a message to the server, which will respond to the client and add a message to the list.

simple-elm-client

Conclusion

That’s all there is to it! Any time I’m working on a side project that requires a client-server architecture, I tend to start off with something like this and continue building on it. Hopefully, this helps you get started using Elm and Express.

Conversation
  • Alan says:

    Thank you for a very nice tutorial and it all works first time!!
    I am learning Elm and wondered if you have any thoughts/insights re routing.
    The example in the Elm tutorial seems quite complicated to me.
    Regards

  • Comments are closed.