Deploy Web App with Grunt Compiled Assets to Heroku
Hold on Cowboy
This blog post is pretty old. Be careful with the information you find in here. The Times They Are A-Changin'
The conundrum is how do you deploy a web app to Heroku that needs to be compiled without including compiled files in your source?
Maybe you have some SASS that needs to be compiled into CSS. Maybe you want to minify your JavaScript, or cache bust with some appended hash tags. In any case you want to run some tasks on your code to produce your distribution or build.
Here are some options.
Just include them in your source code
This is the least desirable, but you could just include your dist
or build
folder in your source code. This gets to be messy as you will have compiled assets in your source code and if you have multiple people deploying you will get merge conflicts and what not. Only use this if you’re nuts.
Have Heroku compile them for you
You can do this by including all your devDependencies
in your dependencies
in your package.json
file. Then have a Grunt task for compiling that is hooked to npm prepublish. Here is an example that will run grunt --env production
on Heroku when Heroku runs npm install
.
"scripts": {
"prepublish": "grunt --env production"
},
This works, but the drawbacks are having to include all those devDependencies in your code and then having Heroku download them and run. My Grunt tasks are kind of elaborate, so this becomes a pain for me. This can blow up in your face in the rare instance that npm is having issues :D.
Use a local distribution Git branch
This is a strategy I’ve started to use and works pretty good. It uses a local branch to add commit your compiled assets to Heroku, but doesn’t pollute your main branches (master and develop). Here is how it goes.
Setup
- Your
dist
orbuild
folder is listed in.gitignore
so that the files there are generally ignored by git. - You create a branch that is used just to compile and push to Heroku.
git checkout -b dist
- Run your Grunt task to create your distribution files
grunt buildprod
- In that branch you force git to include all the
dist
orbuild
files that your Grunt task just made
git add -f ./dist
git commit -m 'Adding dist files'
- Now you can deploy to Heroku using the dist branch to push like this. This command tells git to push the local
dist
branch to the remoteheroku
branch ofmaster
. We use force.
git push heroku dist:master --force
- Now your files are on Heroku and have the compiled version
Updating Heroku
- Back on your
develop
branch you do a bunch of work, commit, etc. - When you get ready to deploy again you will checkout your
dist
branch, then rebase against your develop branch
git checkout dist
git rebase develop
- Run your Grunt task
grunt buildprod
- Add newly created dist files
git add -f ./dist
git commit -m 'Adding dist files'
- Now you can deploy to Heroku using the dist branch to push like this. This command tells git to push the local
dist
branch to the remoteheroku
branch ofmaster
. We use force.
git push heroku dist:master --force
- Now your files are on Heroku and have the compiled version
Somethings to keep in mind, you can change these values to match your environment.
- My remote is called
heroku
- My local branch for deploying to Heroku is called
dist
- My local folder that holds compiled assets is in
./dist
- I originally created the branch
dist
fromdevelop
, usemaster
if that’s your gig.