I am setting up a new project that will be using Phoenix and Elm together, so I am taking this opportunity to document the process to make it easier for others to set up as well. Maybe I should turn this into a mix 'new'able template sometime...
Initial Setup
Note
If you are adding elm to an existing phoenix project then feel free to skip this step.
First things first, make sure you already have nodejs (6+), npm, Elm, Erlang, Elixir, and Phoenix installed.
So lets start with a basic phoenix app, will be using normal integer IDs in the model, using brunch as that is what comes with Phoenix (feel free to adjust to your own if you use another bundler), and just fairly stock. Let's name it, oh, MyServer. So let's run this in your shell of choice:
At this point it should also be good to set it up as a git repo, it is never too early to make your repository:
$ git init Initialized empty Git repository in /home/<user>/elixir/my_server/.git/ $ git add . # Snip ton of files added to your new git repo $ git commit # Snip ton of files committed to your repo |
Other than making sure your database is setup if you are using one and so forth, that should be all the basics. Now let's add elm to the project.
Adding Elm to Phoenix via brunch
First we need to actually have the project get and manage elm, so open your ./package.json file and go to the "devDependencies" section and add a new elm entry such as:
"elm-brunch": "~0.7.0",
This will handle downloading and installation of elm-brunch and elm itself. If you wish you can run npm install now to get it, otherwise phoenix will get it for you when we run it later.
Next we need to open the brunch-config.js file. Go to the exports.config.paths.watched section. You will want to add a new a new path for where-ever you want to put your elm source files. I prefer them to go in to web/elm so that is what I am adding to that section:
"web/elm",
We should, though not need to, but I highly recommend adding an elmBrunch configuration inside your brunch-config.js file. To do so continue down to the exports.config.plugins section and we need to add a new section after your babel section (as always don't forget any commas on newlines as appropriate). Let's start with this configuration:
The inline comments should be able to describe what is going on, and keep in mind that any 'root' Main program you may have in Elm should be listed in mainModules so they all get combined into one file to share the elm standard library and save a ton of space.
Setup Elm Itself
Setting up elm itself just involves setting up its package file, to do that make a file named elm-package.json and populate it with:
The version must always start out with 1.0.0, enforced by much of Elm itself. Alter the summary, repository, and license as makes sense, but keep summary to less than 80 characters, this will also error out at you in Elm if too long. The source-directories must contain a list of only "web/elm" or where-ever you chose to place it, or else it can try to compile a lot more than you expect. The "exposed-modules" is only used if you are making a distributable Elm library, which not really for this project. The two listed dependencies are the usual to get started with a basic Elm program, like a Counter. And finally the "elm-version" should be self-explanatory, all versioning in Elm is semver and enforced by the Elm system.
Next, though optional, I would highly recommend adding the following line to your .gitignore file to ignore the elm cache directory:
/elm-stuff/
With these are we are now ready to create the first Elm file and hook it into the application.
Creating our first Elm application in Phoenix
Create the file web/elm/Main.elm or of whatever file you put in your mainModules section and open it up. Let's go ahead and do the usual Elm counter app so we can make sure that it works and so that we have something to wire up:
This is the standard beginner counter app from the Elm docs and will work wonderfully for testing the integration with the Phoenix system.
At this point, since I like intellisense in my IDE's, go ahead and compile this all by running mix phoenix.server to start the server and let brunch build it all, make sure you can access the main web page. You will notice that if you save the Main.elm file again then phoenix will auto-rebuild it for you since the server is running in dev mode and we adjusted the brunch watch path to include the elm directory. Go ahead and save the Main.elm file at least once now to make sure it recognizes it and rebuilds it, and to make sure we get the web/static/js/elm.js file generated. It is good to have this file in this directory as Elm fits into the ES6 module system fine and so it will be properly optimized and minimized by brunch in release deploys.
Embed Elm in a Phoenix Page
In general the elm.someApp.fullscreen should not be used, all it does is just do elm.someApp.embed(document.body), and if you want to add it to the body then explicitly doing so is better anyway. For now let's go ahead and add it to our index page of this default app so open up web/templates/page/index.html.eex, let's wipe it out and replace it all with just this:
<div id="counter-app"></div> |
A nice simple div with an id of whatever you want to hook to. Next open your web/static/js/app.js and at the bottom of it add this:
import Elm from "./elm.js" let counterDiv = document.getElementById("counter-app") if (counterDiv !== undefined) { Elm.Main.embed(counterDiv) } |
Inside the if is a good place to register ports and such as well if you need any for your app. But right now you should be able to load your browser to the main index page and see your counter. I seem to be able to get around 100 clicks per second with my mouse-macro on my system. :-)
Ending Notes
From this point on you can continue to grow the app, add more apps, etc. If you make multiple main apps, say MyMain.elm and AnotherMain.elm then you would just embed them respectively via Elm.MyMain.embed(whateverDiv) and Elm.AnotherMain.embed(anotherDiv). It is quite easy to expand as you so need. If you want one app per page and do not want to combine all the javascript together then you can disable the combining into a single Elm file option and use the normal Phoenix/Brunch stuff to make multiple top-level javascript files. I personally prefer everything in one main big file as it reduces the overall storage and download size, but it might be better to split it if you have a lot of very large apps on a lot of pages, otherwise I'd say do not worry about it.
If there is anything that I should clarify or if the standards change with Elm then please notify me and I will attempt to answer any question as best I can. :-)
Comments
Comments powered by Disqus