Integrating Rocket and Elm with Brunch

Frank Panetta
4 min readJul 4, 2017

--

Authored: July 2017

I couldn’t find any tutorials on how to get Elm up and running on Rocket, so here’s my attempt. I don’t go into to much detail about what each component does, but I do explain how to get going. I hope you find it useful.

Versions

Rust: v1.20.0-nightly

Rustup: v1.5.0

Rocket: v0.2.8

Elm: v0.18.0

Elm-Brunch: v0.8.0

NPM: v3.10.10

Node: v6.10.2

Brunch: v2.10.7

Source Code: https://github.com/fattenap/rocket-elm

Step 0: Install Dependencies

Before starting this tutorial, you will need to ensure that the following applications are installed.

Step 1: Create our Application

The first thing we will do is create a Rust binary application.

$> cargo new rocket-elm --bin

Enter the rocket-elm directory and ensure that we are using the Rust nightly build for this project.

$> cd rocket-elm
$> rustup override set nightly

Take a second to review what’s included in our new project. The project has two files Cargo.toml and src/main.rs. Cargo.toml is used by Rust’s package manager, Cargo. We will need to add Rocket as a dependency to our project.

[dependencies]
rocket = "0.2.8"
rocket_codegen = "0.2.8"

The src/main.rs file is our Rust source file and simply prints “Hello world!”.

fn main() {
println!("Hello, world!");
}

Let’s run our application.

$> cargo run

cargo run will download all the dependencies, compile our main.rs file and run the application. You should see “Hello world!” output to the console. If you did, then we’re good to move on.

Step 2: Serve up some HTML

In the previous step “Hello world!” was printed to the console. That’s not going to do us any good, we need to serve up some HTML. So let’s implement Rocket’s version of Hello world!

Replace the code in main.rs with

#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}

fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}

Save, compile and run, then open the browser at http://localhost:8000. Boom! You have a running web server.

I won’t go into the details of what’s going on here, but you can probably see that a GET request returns the string “Hello, world!”.

Now that the server is running, let’s take a look at how we integrate Elm.

Step 3: Set up Web Development

In the root directory of the project, create an app directory. This is where we will keep all the front-end web development stuff.

$> mkdir app

Now we need to start configuring our environment. We are using NPM and Brunch, so initialise an NPM project and select the defaults at the prompts. The answer’s to the questions are unimportant for our project.

$> cd app
$> npm init

Open the package.json file delete the main key and replace scripts with

"scripts": {
"deploy": "brunch build --production",
"watch": "brunch watch --stdin"
},

Then install our development dependencies.

npm install --save-dev auto-reload-brunch babel-brunch brunch clean-css-brunch css-brunch elm elm-brunch uglify-js-brunch

Create an empty configuration file for Brunch called brunch-config.js.

$> touch brunch-config.js

Update brunch-config.js to include the following

exports.config = {
// See http://brunch.io/#documentation for docs.
files: {
javascripts: {
joinTo: "js/app.js"
},
stylesheets: {
joinTo: "css/app.css"
}
},
conventions: { // This option sets where we should place non-css and non-js assets in.
// By default, we set this to "/assets/static". Files in this directory
// will be copied to `paths.public`, which is set below to "../public".
assets: /^(static)/
},
// paths configuration paths: {
// Dependencies and current project directories to watch
watched: ["static", "css", "js", "vendor", "elm"],
// Where to compile files to
public: "../public"
},
// Configure your plugins
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
ignore: [/vendor/]
},
elmBrunch: {
elmFolder: "elm",
mainModules: ["Main.elm"],
outputFolder: "../js"
},
},
modules: {
autoRequire: {
"js/app.js": ["js/app"]
}
}
};

For this configuration to work, we need to add some directories.

$> mkdir css elm js static vendor

And finally, let the Rocket server know where to find our files. Go back to src/main.rs and replace the code with code below.

#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;use std::io;
use std::path::{Path, PathBuf};
use rocket::response::NamedFile;
#[get("/")]
fn index() -> io::Result<NamedFile> {
NamedFile::open("public/index.html")
}
#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("public/").join(file)).ok()
}
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/", routes![index, files])
}
fn main() {
rocket().launch();
}

This includes everything we need to get us started developing an Elm application.

Step 4: Write some Elm

To start writing Elm, we need to go into the elm directory.

$> cd elm

Then we need to create an Elm project by running

$> package install elm-lang/html

Answer “Yes” at the prompt. This will download the required elm dependencies.

Once that completes, create a Main.elm file

$> touch Main.elm

Add the Elm code below to the file.

module Main exposing (..)import Html exposing (text)main =
text "Hello from Elm!"

We’re almost there…

Go into the static directory under the app directory and create and index.html file with the following html.

<div id=elm-container></div>
<script src="js/app.js"></script>

Then go to the js directory under the app directory and create an app.js file with the following code

import Elm from './main';
const elmDiv = document.querySelector('#elm-container');
if (elmDiv) {
Elm.Main.embed(elmDiv);
}

Step 5: Launch!

To start your application, go to the app directory build your application with

$> brunch build

If you see an error like could not load module ‘./main’ it means that the main.js file wasn’t created yet. Just rebuild and it should compile without error. Once you have compiled your web files, go into the projects root directory and run

$> cargo run

to compile and run Rocket server. If all went well, when you visit http://localhost:8000/, you should see “Hello from Elm!” in your browser.

Step 6: Keep coding

If you are after live reloading of you web source files, from the app directory run

$> npm run watch

This will watch your source directories and refresh the browser whenever you save.

Enjoy!

--

--