DEV Community

Martin
Martin

Posted on

Deploy a Vue app with a Nodejs backend to Heroku

Many tutorials about deploying a Vue app to Heroku are using a very simple setup with no server (or a really simple one only using express as a server dependency).

But what about deploying an app with more complex server which has a lot of dependencies? I couldn’t find a good and working tutorial, so I wrote this one.

Setup

My Vue App is not only a frontend, but also needs a backend. Of course I could deploy the frontend and backend to different services and maybe utilize CDNs for the frontend, but I wanted to have everything in the same repository and server.

All the Node.js server code is in the root folder and I have a seperate frontend folder for my Vue.js app.

Developing the project locally was no problem. That’s why I thought pushing to Heroku would as well be a piece of cake.

My server code needs a simple npm install && npm start and the Vue.js app has to be build with npm run build. On the server side I am using fastify and with the help of fastify-static I am serving the frontend/dist folder to the users.

So, in order to build everything upon deployment, the command for the build step in my root package.json would be: cd frontend && npm run build? Wrong!

Analysis and Solution

First of all, all the Vue.js dependencies are not installed, so we are missing a npm install in the frontend folder. But Heroku apparently sets NODE_ENV=prod and NPM_CONFIG_PRODUCTION=true so when running an npm install no devDependencies get installed. I tried different approaches to get Heroku to install and build everything correctly (e.g. https://stackoverflow.com/questions/22954782/install-devdependencies-on-heroku , https://dev.to/jmbejar/how-to-quickly-deploy-a-vuejs-app-to-heroku-5b0f) but in the end I resorted to a simple build script:

#/bin/bash
npm install —only=dev # installs only dev dependencies
npm install            # installs prod dependencies
npm run build          # builds the Vue.js app
Enter fullscreen mode Exit fullscreen mode

This script resides in the frontend folder. And I call this script from the root package.json by using

“heroku-postbuild”: “cd frontend && ./build.sh”,

Now upon deployment all my server dependencies get installed as well as my Vue.js frontend being build.

There are surely other ways to accomplish this, but my approach works for me and is easy to understand.

Top comments (4)

Collapse
 
dakujem profile image
Andrej Rypo

Why would you want to install dev deps on a production server? 🤷‍♂️

Collapse
 
junkern profile image
Martin

That's a good question and one I also asked myself before writing that article. What are the alternatives?
Building the application one my local machine and commiting the dist folder? And, because I would often forget to build my project before committing, I would add a pre-commit hook which builds the project.
However, some people consider adding build artifacts as bad practice 🤷‍♂️
We are actually on the same page here, I am also against installing dev dependencies on a production server. But often things are a trade off and for this project, I decided to install dev dependencies and against having build artifacts in my repo.

Do you have another alternative in mind?

Collapse
 
dakujem profile image
Andrej Rypo

How about making the necessary "dev" deps into production ones? That's what you do with PHP at least - you only install dev deps for your local/dev and test environments, but install the production deps only once you deploy the app to production.

I'm not yet versed with JS, it might be different there, but what other purpose would there be in dev deps, if they were supposed to be installed every time anyway? It wouldn't make sense. (Although that would not be the first time something made no sense in JS 😁).
Like, you don't need Vue CLI service for production, right? Neither a linter. My assumption is this, the "production" deps are meant for environments like Node, where "dev" ones can be omitted, but you still need the "dev" ones to build a production build, which you are doing in the build step of the Heroku deployment.

Thread Thread
 
junkern profile image
Martin • Edited

(Disclaimer: I am also not really knowledgeable with the whole React/Vuejs build pipeline, so I might state wrong things. Maybe I should spent some time in the future to look further into the build things)

You are perfectly explaining the approach React is taking: They add their built tool to the prod dependencies. Vue.js has a different approach/philosophy. I might try out your idea with the next project, but it probably won't work. The CLI service actually provides the build command to build the project. There might be a way to do it "light weight" (which I don't know of) but I am not very confident it will work. I am writing my Vue projects with Typescript, so I would need the whole TypeScript dependencies.

But you are right, when you use the approach written in the article, it does not make any sense to have build tools in the dev dependencies. Let's see if I try another solution the next time I use Vue.js on Heroku.

Thanks for raising those valid points!