Integrating Rocket and Elm with Brunch
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.
- [Rust, Cargo & Rustup](https://www.rust-lang.org/en-US/install.html)
- [Node & NPM](https://docs.npmjs.com/getting-started/installing-node)
- [Elm](https://guide.elm-lang.org/install.html)
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!