Deploying your Nuxt+Rails API app to production with Heroku

Quinn Daley
5 min readApr 22, 2018

--

If you followed along with the last post, you will have created a working decoupled Nuxt (Vue.js) & Rails API application in development using Docker.

Docker also excels in production, and it wouldn’t take too much effort to tweak those Dockerfiles and deploy it to something like Rancher, if that’s how your organisation works.

However, I’m still a big fan of Heroku for deploying applications to production. It’s not the cheapest, and it has some flaws (not least that it still doesn’t support http/2), but the advantages are huge when you’ve only got a small team — getting metrics and scalability with a nice user interface with zero configuration has to be worth the extra cost!

In this guide, I show you how to deploy the app you created in the last post to Heroku.

Getting around Factor I with git subtree

Heroku prides itself on being able to run any application that conforms with the Twelve-Factor specification. Now, I’m a big fan of that specification, but it is going to cause us some problems here because of Factor I: Codebase.

Instead of creating different git repos for the frontend and backend, we’ve put them in the same repo together. This isn’t strictly Twelve-Factor, but we wanted to do so in order to use docker-compose to orchestrate the two components together, and I still think this is a valid thing to do, despite what Factor I tells us.

Enter git subtree. This little-used git command is normally used to vendor third-party code into your repo, but it can also be used for contributing that vendored code back upstream. Which means it can be used to generate fresh git repos with the correct version history from subdirectories on the fly.

A command like:

git subtree push --prefix autheg-backend heroku master

is a way of saying “push a git repo containing just the files and history of the autheg-backend directory to the remote branch heroku/master”. This knowledge will allow us to create separate Heroku apps for our frontend and backend subdirectories in the tutorial below.

[An aside: There are other ways to achieve this, including deploying everything into the same Heroku application. This definitely has some advantages but it is also necessarily complex: Heroku will route all incoming traffic to whichever dyno type in your application has the name ‘web’. Since we need two different services to handle web traffic, we’d need to create and manage a third service (e.g. nginx) acting as ‘web’ and routing the appropriate traffic to the correct dyno.]

Part I: Deploying the backend

Rails and Heroku are best friends and have been since the early days of either of them, so deploying the backend is about as easy as it can be.

Make sure you have the Heroku CLI installed and then go into the top-level directory of your autheg repo.

First, create yourself an app. You won’t be able to use the autheg-backend name because I’ve taken it, but pick whatever name you like:

heroku apps:create autheg-backend

That will have added a git remote called “heroku” to your repo. Because we’re going to have two remotes, let’s rename them.

git remote rename heroku backend

Now we can use that magical git subtree command to push the backend up to that remote:

git subtree push --prefix autheg-backend backend master

(Here “prefix” refers to the name of the directory, so it will be the same for you.)

Wait for the Heroku Ruby buildpack to build your backend application. As part of the process, it will automatically detect that this Rails app needs a Postgres database and provision one of those for you, putting its access details in the DATABASE_URL environment variable, which Rails knows to use to connect to the database.

To provision the database schema, you just need to do:

heroku run -a autheg-backend rails db:schema:load

One last thing we need to do: we need to set the JWT_SECRET environment variable so we have a unique secret for signing our JWTs. We’ll use the “rails secret” command to generate a secret for us.

heroku config:set -a autheg-backend JWT_SECRET=$(heroku run -a autheg-backend rails secret)

Now your app should be running! You can create a user using the Rails console:

heroku run -a autheg-backend rails console
User.create! email: %{test@example.com}, password: %{password}

(I’m using %{quoting} above instead of normal straight quotes only because Medium likes to convert them into invalid “smart quotes”.)

And now try logging in at a REST console like YARC using your https://autheg-backend.herokuapp.com/api/users/sign_in endpoint to check it’s all working as expected.

Fantastic. Your backend is provisioned and you didn’t even need to change one line of your codebase!

Part I(b): CORS

If, when you built out the backend before, you used ‘localhost:3000’ in your config/initializers/cors.rb file, you’ll encounter network errors. You can either change this to a ‘*’ to allow connections from all domains, or you can add your new frontend domain like this:

origins 'localhost:3000', 'autheg.herokuapp.com'

and redeploy using git subtree.

Part II: Deploying the frontend

The frontend is a little trickier, but thankfully the Nuxt documentation on Heroku is very helpful!

First, let’s create the app as we did for the backend:

heroku apps:create autheg
git remote rename heroku frontend

Now, before we deploy we’re going to need to make some changes. The Nuxt app needs to be built to run in production mode, which means we’re going to need to install the dev dependencies as well as the application dependencies into our Heroku container.

The following command tells your app to run in production mode and on all interfaces (0.0.0.0) but tells yarn/npm to run in development mode, so that all the dev packages are installed as part of the build process.

heroku config:set -a autheg NODE_ENV=production HOST=0.0.0.0 NPM_CONFIG_PRODUCTION=false

We also have to make a small change to the autheg-frontend/package.json file, so that Heroku knows to build the app after all the files have been deployed. Add the following to the scripts section:

“heroku-postbuild”: “npm run build”

You’ll need to commit this change to version control so it’s included in the push.

One last thing: we need to tell our frontend app where to find our backend app. Thankfully, the Nuxt Axios module has us covered automatically with the API_URL environment variable:

heroku config:set -a autheg API_URL=https://autheg-backend.herokuapp.com/api

OK. Moment of truth! Try deploying using git subtree:

git subtree push --prefix autheg-frontend frontend master

If it all went according to plan, you should be able to see your app at (insert your app’s name into) https://autheg.herokuapp.com/

Try creating some data on the backend and logging in as you did in your development environment. Works for me!

Redirected to the login page
Examples I created in my production database. Woo!

As before: if this article’s been helpful, please share it around, throw me a few claps, or let me know how you’re getting on in the comments.

--

--

Quinn Daley

Quinn is the main developer at Fish Percolator: changing the world in small ways through technology. https://www.fishpercolator.co.uk/