Deploying Vue apps to heroku - the right way
We will deep dive directly into the subject. Heroku is a great platform to deploy servers and websites. Armed with heroku and Vue.js you can develop and ship websites very quickly. There are some articles around this topic already like this one or this one or perhaps this one. So why bother writing another article about it?
The presented solutions in the articles above are not scalable and flexible!
If you already deploy to heroku by building your app locally or by pushing your dist folder, you might consider to stop doing that. Why? Because this approach is not very flexible and scalable. If you push your dist folder to source control or consider having another git repo or git sub modules inside dist folder you will encounter several problems:
- Merge conflicts inside dist folder when working with multiple people
- Useless commits of files from the dist folder
- Issues with initializing separate git repos/sub modules inside dist folder.
- You have to build your app locally! This can create a lot of issues when building on different machines/operating systems and so on.
- The deployment process is not fully automated
Let’s fix it
In order to fix the problems above we need one thing and that is to build the website directly on heroku. Let’s see how that can be done. We will start with a simple Vue CLI 3 project.
- Initialize the project. Make sure you have latest vue cli installed
npm install -g @vue/clithen initialize the project
vue create vue-heroku-the-right-way
After initializing everything you should have at least these 2 commands in your package.json
"serve": "vue-cli-service serve", "build": "vue-cli-service build",
As a side note, we don’t really need Vue CLI 3. This stuff can be done with any setup as long as you have an output folder with files you can statically serve.
2. Add a node server to serve your files. For this we need a simple express server like this one
const express = require('express'); const serveStatic = require("serve-static") const path = require('path'); app = express(); app.use(serveStatic(path.join(__dirname, 'dist'))); const port = process.env.PORT || 80; app.listen(port);
and save it in your project root under
server.js or another name that you prefer.
Make sure you
npm install --save-dev express serve-static
3. Add package.json scripts to start the node server
That’s right. We need 2 scripts to almost finish the setup.
"postinstall": "npm run build", "start": "node server.js",
The start script is the default script heroku will try to run once it installs dependencies and the postinstall script will be the script which heroku will automatically run after installing dependencies but before starting the app.
This will lead to heroku building your app on the server. Why should I care about it?
- You never have to care about building your app locally
- You can automate everything. Heroku has some integrations with github and can trigger deploys on commits. Since everything is run on the server, it can build and deploy your app seamlessly.
- Builds are more deterministic. Heroku will always do a clean install and build and therefore produce more deterministic builds.
- You can configure environmental variables for different environments directly on heroku.
4. Add heroku remote and push to it
Under the settings of your app in heroku, you will find a git url. Add it as a remote
git remote add heroku git_url_here then simply
git push heroku master When pushing, you will see that heroku will pull your repo, install dependencies, build then run your start command. You will never have to build your app locally unless you want to inspect errors locally.
Since postinstall command will run whenever you add a dependency, you might be annoyed by the fact that a build is run after installing a dependency.
We can easily fix that by running
postinstall conditionally like so
"postinstall": "if test \"$NODE_ENV\" = \"production\" ; then npm run build ; fi ",
This will conditionally run our postinstall script only if NODE_ENV is set to production. We can set node env in heroku very easily in the settings tab like so