Deploy Web App with Grunt Compiled Assets to Heroku

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 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 

  1. Your dist or build folder is listed in .gitignore so that the files there are generally ignored by git.
  2. You create a branch that is used just to compile and push to heroku. git checkout -b dist
  3. Run your Grunt task to create your distribution files grunt buildprod
  4. In that branch you force git to include all the dist or build files that your Grunt task just made git add -f ./dist git commit -m 'Adding dist files'
  5. 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 remote heroku branch of master. We use force. git push heroku dist:master --force
  6. Now your files are on Heroku and have the compiled version

Updating Heroku 

  1. Back on your develop branch you do a bunch of work, commit, etc.
  2. 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
  3. Run your Grunt task grunt buildprod
  4. Add newly created dist files git add -f ./dist git commit -m 'Adding dist files'
  5. 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 remote heroku branch of master. We use force. git push heroku dist:master --force
  6. 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. 1. My remote is called heroku 2. My local branch for deploying to heroku is called dist 3. My local folder that holds compiled assets is in ./dist 4. I originally created the branch dist from develop, use master if that’s your gig.

Did this help you out? It took me a few days to piece together all this information together, I hope this saves you some time (who knows, maybe the future me will be thankful I wrote this down). Let me know your thoughts. shanestillwell@gmail.com