Quick-n-clean way to deploy Vue + Webpack apps on Heroku

As we had seen in the last post, Webpack makes it very easy to set up and manage your Vue app.

We had discussed a way to deploy the Vue app on Heroku by making Heroku do all the hard work of building and deploying your app each time to push to Heroku (either directly, or triggering a push via Github integration).

Now, in case you want your development workflow to be separate from your build-and-deploy process you can choose to build static assets locally and send only the built app to Heroku. This way your app size is kept to the minimum and deploys are clean and lightning fast! Outlined here is one of the ways to to this:

1. Build your app

Building the app is easy

❯❯❯ npm run build
Time: 4284ms
Asset Size Chunks Chunk Names
static/app.e891c19906e14bededa7.js 86.1 kB 0 [emitted] app
static/app.a5bdd419ee86440c24eb6e435a0a50af.css 584 bytes 0 [emitted] app
static/app.e891c19906e14bededa7.js.map 683 kB 0 [emitted] app
static/app.a5bdd419ee86440c24eb6e435a0a50af.css.map 1.28 kB 0 [emitted] app
index.html 236 bytes [emitted]

You’ll see that Webpack creates chunks of static assets in the ‘dist’ folder with a single index.html file which can be served using a web server.

2. Create build files

These files are needed so that Heroku knows how to serve your static assets each time we push them to Heroku’s remote git repo. We’ll use 2 small files for this purpose. In your ‘./dist’ folder, create the following:

File #1: package.json

{
"name": "blog",
"version": "1.0.0",
"description": "personalblog",
"author": "Awesome Author",
"private": true,
"scripts": {
"postinstall": "npm install express"
}

}

The main purpose of creating this file is to tell Heroku to install the express server which will be used to serve your app. We don’t need to add any dependencies here since the original package.json file in the root folder of your app was used to build the static assets using all the dependencies listed there.

File #2: server.js

var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
app = express();
app.use(serveStatic(__dirname));
var port = process.env.PORT || 5000;
app.listen(port);
console.log('server started '+ port);

This is very similar to the file we created in the previous post. This file will be used when Heroku runs ‘npm start’ to run your app after deploying it. You can test this file locally to make sure everything is correct:

❯❯❯ cd dist
~/vue/blog/dist (master|✔)
❯❯❯ npm start
> blog@1.0.0 start /Users/sagar/vue/blog/dist
> node server.js
server started 5000

3. Set up local git repo

Assuming your app is in the directory ‘blog’ and you have a Heroku app called ‘vue-deploy-example’, first add the git remote like you would do with any other app. This would allow you to push to the remote git repo.

❯❯❯ cd blog
❯❯❯ heroku git:remote -a vue-deploy-example
set git remote heroku to https://git.heroku.com/vue-deploy-example.git

The ‘dist’ folder is not version controlled by default but for this workflow we would want it to be. So remove ‘dist/’ from your ‘.gitignore’ file and create a commit to add you ‘dist’ folder to git:

❯❯❯ git status --short
 M .gitignore
?? dist/
❯❯❯ git add .
❯❯❯ git commit -m "Adding dist folder"
[master 5c005aa] Adding dist folder
6 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 dist/index.html
create mode 100644 dist/static/app.a5bdd419ee86440c24eb6e435a0a50af.css
create mode 100644 dist/static/app.a5bdd419ee86440c24eb6e435a0a50af.css.map
create mode 100644 dist/static/app.e891c19906e14bededa7.js
create mode 100644 dist/static/app.e891c19906e14bededa7.js.map

Ok, we’re almost there!

4. Push only ‘dist’ folder to Heroku

First, set the build-pack for the Heroku app

❯❯❯ heroku buildpacks:set heroku/nodejs
Buildpack set. Next release on vue-deploy-example will use heroku/nodejs.

Now each time you want to deploy you can just run the following:

❯❯❯ git subtree push --prefix dist heroku master

This command would push only the ‘dist’ folder to Heroku. Since there is no building required, Heroku would run the ‘postinstall’ command we set up in the ‘package.json’ file which would install the express server, which in-turn would run your app.

Bonus

Optionally, you can create a ‘deploy’ npm command by adding the following line in the ‘scripts’ section of your main package.json file (not the one that we created in the ‘dist’ folder, but the origin package.json in the root folder of your app):

"scripts": {
...
  "deploy": "git subtree push — prefix dist heroku master"
...
}

so that each time you want to deploy a new version on Heroku, you can just run this:

❯❯❯ npm run build
❯❯❯ npm deploy

If you’re having trouble, do check the Heroku logs ($ heroku logs) for your app or Heroku’s troubleshooting guide.


The source code of a demo app which uses this deploy process including the additional files we created can also be found here: