So you’ve got a cool node app written in Coffeescript and you want to deploy it to Heroku?
Seems like it should be easy these days, right?
Not so much. Well, let’s be honest, we’re in the future, you don’t have to manually manage servers, etc. (Thank you Heroku!) but deploying a Coffeescript app is still no small task as there are a bunch of gotchas. Hopefully this will help.
Structure of Coffeescript node app
The following instructions assume you have the following rough structure to your application:
1 2 3 4 5
The general idea here is that your app source .coffee files will live in the /src directory and when they’re pushed to Heroku, they’ll magically be compiled into the /target directory as js files.
This is optimal as it means this compilation happens once with each push and so there is no ongoing performance hit from the server having to convert .coffee to .js on the fly.
So after pushing your app will look like this on the Heroku servers:
1 2 3 4 5 6 7
Where target/app.js is the compiled version of src/app.coffee
Heroku has things called Buildpacks which are a bundle of scripts to be run when code is pushed to Heroku. They have official Buildpacks for Node, Rails, and the other most common frameworks, but none for Coffeescript as of the time of this writing.
To add this buildpack to a new node app you can use the following command to create the app:
You can also add it to an existing app:
You will have to make sure your Procfile is properly configured for this as well.
It should contain the following:
Note how it’s hitting target/app.js which will be the compiled copy of your app.
Even though you may have an empty target directory on your local machine, it will get populated with the compiled app code on push to Heroku.
During development, you can run your code locally without compilation if you’d like:
If you want to do this with Foreman it’s easy to create a Procfile.dev and tell Foreman to use it:
Liquid error: ClassNotFound: no lexer for alias ‘dev’ found
Then to run it:
You can also compile the code manually, just as the Buildpack will on a push to Heroku:
My favorite approach is to have all of this happen automagically, with some linting as well using Grunt Grunt to watch for changes and compile everything in the /src directory into the /target directory.
First, if you haven’t already, install the Grunt dependencies:
Then create or edit your Gruntfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Then run it:
Not only will that watch the directory for changes and compile it whenever a file is written, but it will also lint the files! Then the app can be run:
Or, since this is just the way it will look when pushed to Heroku, you can use Foreman with the normal Procfile to run it:
Note how under the coffee task I have
1 2 3 4 5 6 7
This basically instructs Grunt to recurse through every subdirectory of src/, find each .coffee file, and compile it to create a .js doppelganger under target/.
This means src/app.coffee becomes target/app.js and src/config/db.coffee becomes target/config/db.js and so on.
If you’re going to do this local auto-compilation, I suggest adding target/ to your .gitignore file. No need for that to get committed to your repo!
Of course this is all well and good, but until you actually push it to Heroku it isn’t doing you much good!
You should see something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Note: I replaced all the npm dependency installation as … above for brevity
Note how it says Coffeescript app detected
This is due to the Buildpack referenced above. If it finds .coffee files in the src directory, it recognizes it as a Coffeescript app.
After it has installed the dependencies, including the coffee-script module, it will compile the coffee source from src/ into target/ and start your app.