Recently, I have been investing some time learning VueJS and I found that it is a very interesting framework to play around with. In fact, I have been working on a new project prototype for the last few days and wanted to show it to some people, so I wanted to publish it somewhere in the Internet.
I decided to deploy the project on Heroku so I started to research what is the best way to do it. To my surprise, I did not find much about it apart from a few posts like Quick-n-clean way to deploy Vue + Webpack apps on Heroku and Easily deploy a Vue + Webpack App to Heroku in 5 Steps. Nevertheless, I ended up with a different setup and this is the topic of this post.
Assuming that a Heroku account is already created and the VueJS project already exists, the approach explained in the mentioned articles that I found in my research could be summarized in the following steps:
- Write a minimal NodeJS web server using Express
- Build the assets locally
- Add the
distfolder to the Git repository, so it is included when pushing to Heroku
What I did not like of these solutions was the need to build the site locally and check-in the changes within the
dist folder. I wanted to have this step handled by Heroku when pushing a new version of my application.
Let’s assume we have a VueJS project generated using
vue-cli with the
webpack template. Just to be clear, the project was created using the following command:
Of course, we also need a Heroku account and a new application created there. Heroku will use the NodeJS buildpack because our project contains a
package.json in the root folder.
Step 1: Add a minimal NodeJS server
This is a step borrowed from the mentioned blog posts. We have to add a
server.js file in the project’s root folder containing the following code:
1 2 3 4 5 6 7 8 9 10 11
Since this code uses Express, we need to add this dependency to our project:
You can test this server locally by running the following commands:
Step 2: Setup package.json scripts
We need to tweak the
scripts section in the
package.json. If the package file provided by the Vue Webpack template was not modified, it should include two important tasks,
1 2 3 4 5 6
By default, the
start script will be executed by Heroku to start the server. For this reason, we will change the command associated to
start to run our custom server script:
1 2 3 4 5
Please note you can not use
npm run start anymore to run the development server in your computer. I decided to use
npm run dev directly but you could add a new entry in the
scripts section with an alias for that.
We still have to add something to make sure that the
dist folder is built in our Heroku instance every time the code is deployed, otherwise the server script is not going to work properly. We will use a special script called
heroku-postbuild which is documented here. The idea is to build the site using this special hook, so let’s add it to our
1 2 3 4
Let’s explain the command a bit. First of all, we need to install the dependencies that are used to build the assets. In a VueJS project created with the Webpack template, all the needed dependencies are in
devDependencies, so we have to add the
—no-shrinkwrap option is used to avoid possible conflicts with the packages installed by Heroku during the installation process (where the production dependencies were installed). However, it could be an unnecessary option in most cases.
And of course, we are running
npm run build to actually build the site before the server is started.
Step 3: Try it and enjoy!
We are now ready to deploy to Heroku. Assuming we already have a Git repository, we need to add the Heroku remote repo:
And the command to deploy our application is:
It will push the code, trigger the build steps and start the NodeJS script that will serve our site made with VueJS
There might be some discussion around the decision of having a build step in Heroku instead of checking in the
dist folder. Building the site locally would lead to a less complicated Heroku setup because we can just assume that the
dist folder is always present. However, having the
dist folder in our Git repository does not seem a good practice because it will make harder to read commit changes and deal with merge conflicts. Also, it will require some effort and discipline from every developer in the team to keep the right built version of the assets in the repository. For all these reasons, we prefer to build the site as an automated step into the deployment process.
Speaking about the
heroku-postbuild hook, some people are actually using
post-install which seems to also work on Heroku. The purpose of this npm hook is to be invoked when a package is installed and, in my opinion, it should be used in the context of the library project, not in an application project. I would rather use the most specific hook provided by Heroku.
Regarding the need to run
npm install in the
heroku-postbuild hook to install our
devDependencies, we could discuss a few available alternatives to solve the problem:
Do not use
The simplest approach would be to move everything to
dependencies and do not use
devDependencies at all. In fact, I was comparing the process to deploy a React project created with create-react-app) to Heroku and realized that all the scripts and dependencies needed to build the site are actually in the
dependencies section. This is what you find in the
package.json file in such cases (the
react-scripts package contains all the dependencies used to build the site):
1 2 3 4 5 6 7 8 9 10
Note that there is no
devDependencies there. Therefore, it is safe to just run
npm run build in the
heroku-postbuild hook, since all the necessary packages to build the site were already installed at that point by the default deployment process in Heroku.
In any case, I think it is a good practice to keep dependencies well organized in both categories,
depDependencies. As a consequence, we opted for the inclusion of the additional
npm install in the
heroku-postbuild hook step instead of changing the default configuration provided by
Set NPM_CONFIG_PRODUCTION to false
Setting the environment variable
false causes that packages from
devDependencies will also be installed by default in the deployment process in Heroku. The default value is
true because the most common case would be to install only the items from the
It would be a valid solution to tweak this value and have the
heroku-postbuild script just running
npm run build. Even so, note this change also affects the value of
NODE_ENV as explained here . There is a chance that it could cause some side effect in the build process but this is unlikely to happen using the default Webpack configuration for VueJS projects, as far as I can tell.
Hope you find this post useful and have your VueJS project finally deployed to Heroku! If you have any problem following the steps please leave a comment so we can find a solution together and improve this article.