Free Consultation

Information Technology

How to deploy a Vue App with a Node.js Backend to Heroku

Dhaval Baldha

15 Jul 2025

5 MINUTES READ

How to deploy a Vue App with a Node.js Backend to Heroku

Introduction

Deploying a full-stack application with a Vue.js frontend and Node.js backend can seem daunting, but Heroku makes this process straightforward. In this comprehensive guide, we'll walk through deploying your Vue.js application with a Node.js backend to Heroku, covering everything from project structure to production optimization.

Prerequisites

Before we start, ensure you have:

  • Node.js and npm installed on your machine
  • A Heroku account (free tier is sufficient)
  • Heroku CLI installed
  • Git installed and configured

Project Structure Overview

For this deployment, we'll assume a project structure where both the frontend and backend are in the same repository:

my-fullstack-app/
├── client/          # Vue.js frontend
│   ├── src/
│   ├── public/
│   ├── package.json
│   └── vue.config.js
├── server/          # Node.js backend
│   ├── routes/
│   ├── models/
│   ├── package.json
│   └── server.js
├── package.json     # Root package.json
└── README.md

Step 1: Prepare Vue.js Frontend

First, let's configure a Vue.js application for production deployment.

Configure Vue.js Build Settings

Create or update your client/vue.config.js:

const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
  transpileDependencies: true,
  outputDir: '../server/public',
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true
      }
    }
  }
})

This configuration:

  • Builds the Vue app into the server/public directory
  • Sets up a proxy for API calls during development

Update API Base URL

In your Vue.js app, create an environment-aware API configuration:

const API_BASE_URL = process.env.NODE_ENV === 'production' 
  ? '/api' 
  : 'http://localhost:5000/api'

export default API_BASE_URL

Step 2: Configure Your Node.js Backend

Update Your Server Configuration

Modify your server/server.js to serve the Vue.js build files:

const express = require('express')
const path = require('path')
const cors = require('cors')

const app = express()
const PORT = process.env.PORT || 5000

// Middleware
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// API routes
app.use('/api', require('./routes/api'))

// Serve static files from Vue.js build
app.use(express.static(path.join(__dirname, 'public')))

// Handle client-side routing
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'public/index.html'))
})

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`)
})

Environment Variables

Create a .env file in your server directory for local development:

NODE_ENV=development
DATABASE_URL=your_database_url
JWT_SECRET=your_jwt_secret

Step 3: Configure Package.json Files

Root Package.json

Create a package.json in your project root:

{
  "name": "my-fullstack-app",
  "version": "1.0.0",
  "description": "Full-stack Vue.js and Node.js app",
  "main": "server/server.js",
  "scripts": {
    "start": "node server/server.js",
    "heroku-postbuild": "npm run build",
    "build": "cd client && npm install && npm run build && cd ../server && npm install",
    "dev": "concurrently \"npm run server\" \"npm run client\"",
    "server": "cd server && npm run dev",
    "client": "cd client && npm run serve"
  },
  "engines": {
    "node": "18.x",
    "npm": "8.x"
  },
  "dependencies": {},
  "devDependencies": {
    "concurrently": "^7.6.0"
  }
}

Server Package.json

Ensure your server/package.json includes all necessary dependencies:

{
  "name": "server",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

Step 4: Prepare for Heroku Deployment

Create Heroku App

# Login to Heroku
heroku login
# Create a new Heroku app
heroku create your-app-name

# Add Node.js buildpack
heroku buildpacks:set heroku/nodejs

Configure Environment Variables

Set your environment variables on Heroku:

heroku config:set NODE_ENV=production
heroku config:set DATABASE_URL=your_production_database_url
heroku config:set JWT_SECRET=your_production_jwt_secret

Create Procfile

Create a Procfile in your project root:

web: npm start

Step 5: Database Configuration (Optional)

If you're using a database, configure it for Heroku:

PostgreSQL Example

# Add PostgreSQL add-on
heroku addons:create heroku-postgresql:hobby-dev

# Get database URL
heroku config:get DATABASE_URL

Update your server code to use the database URL:

const { Pool } = require('pg')

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
})

Step 6: Deploy to Heroku

Initialize Git and Deploy

bash
# Initialize git repository
git init

# Add files to git
git add .
git commit -m "Initial commit"

# Add Heroku remote
heroku git:remote -a your-app-name

# Deploy to Heroku
git push heroku main

Monitor Deployment

bash
# View logs
heroku logs --tail

# Open your app
heroku open

Step 7: Post-Deployment Configuration

Custom Domain (Optional)

bash
# Add custom domain
heroku domains:add www.yourdomain.com

# Configure DNS settings with your domain provider
# Point CNAME to your-app-name.herokuapp.com

SSL Certificate

Heroku provides free SSL certificates:

bash
# Enable automatic certificate management
heroku certs:auto:enable

Troubleshooting Common Issues

Build Failures

Issue: npm ERR! Missing script: "heroku-postbuild"

Solution: Ensure your root package.json includes the heroku-postbuild script.

Issue: Module not found errors

Solution: Check that all dependencies are listed in package.json, not just devDependencies.

Runtime Errors

Issue: App crashes immediately after deployment

Solution: Check Heroku logs with heroku logs --tail and ensure your server listens on process.env.PORT.

Issue: API calls fail in production

Solution: Verify your API base URL configuration and ensure routes are properly prefixed.

Performance Issues

Issue: Slow initial load times

Solution: Implement code splitting in your Vue.js app and enable gzip compression in Express.

Optimization Tips

Frontend Optimization

  1. Enable Vue.js production optimization

    // vue.config.js
    module.exports = {
      productionSourceMap: false,
      configureWebpack: {
        optimization: {
          splitChunks: {
            chunks: 'all'
          }
        }
      }
    }
  2. Implement lazy loading:

    // router/index.js
    const routes = [
      {
        path: '/dashboard',
        component: () => import('../views/Dashboard.vue')
      }
    ]

Backend Optimization

  1. Enable compression:

    const compression = require('compression')
    app.use(compression())
  2. Implement caching:

    app.use(express.static('public', {
      maxAge: '1d',
      etag: false
    }))

Security Considerations

Environment Variables

Never commit sensitive information to your repository. Use Heroku config vars:

heroku config:set API_KEY=your_secret_key
heroku config:set DATABASE_PASSWORD=your_db_password

HTTPS Enforcement

Redirect HTTP to HTTPS in production:

// Redirect HTTP to HTTPS in production
if (process.env.NODE_ENV === 'production') {
  app.use((req, res, next) => {
    if (req.header('x-forwarded-proto') !== 'https') {
      res.redirect(`https://${req.header('host')}${req.url}`)
    } else {
      next()
    }
  })
}

Continuous Deployment

GitHub Integration

  1. Connect your Heroku app to GitHub:

    • Go to your Heroku dashboard
    • Navigate to the "Deploy" tab
    • Connect to GitHub and select your repository
  2. Enable automatic deploys:

    • Choose the branch to deploy (usually main)
    • Enable "Wait for CI to pass" if you have tests

GitHub Actions (Alternative)

Create a file at .github/workflows/deploy.yml:

yaml
name: Deploy to Heroku

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: akhileshns/heroku-deploy@v3.12.12
      with:
        heroku_api_key: ${{secrets.HEROKU_API_KEY}}
        heroku_app_name: "your-app-name"
        heroku_email: "your-email@example.com"

Monitoring and Maintenance

Heroku Metrics

Monitor your app's performance:

  • Enable Heroku Metrics in your dashboard
  • Set up alerts for response time and error rate
  • Monitor memory usage and dyno performance

Logging

Implement structured logging:

const winston = require('winston')

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console()
  ]
})

app.use((req, res, next) => {
  logger.info(`${req.method} ${req.path}`)
  next()
})

Conclusion

Deploying a Vue.js application with a Node.js backend to Heroku involves several steps, but following this guide ensures a smooth deployment process. The key points to remember are:

  1. Proper project structure with clear separation of frontend and backend
  2. Correct configuration of build scripts and environment variables
  3. Proper handling of static files and client-side routing
  4. Security considerations for production deployment
  5. Monitoring and maintenance for long-term success

With this setup, you'll have a scalable, production-ready full-stack application running on Heroku. The platform's ease of use, combined with the powerful combination of Vue.js and Node.js, provides an excellent foundation for modern web applications.

Remember to test your deployment thoroughly, monitor performance, and keep your dependencies updated for the best results. Happy deploying!

Share:


Dhaval Baldha
Dhaval Baldha

Co-founder

Dhaval is a visionary leader driving technological innovation and excellence. With a keen strategic mindset and deep industry expertise, he propels the company towards new heights. His leadership and passion for technology make him a cornerstone of Techvoot Solutions' success.

Linkedin

// We are here to help you

Trusting in Our Expertise

  • 30 Hours Risk Free Trial.
  • Direct Communication With Developer.
  • On-time Project Delivery Assurity.
  • Assign Dedicated PM.
  • Get Daily Update & Weekly Live Demo.
  • Dedicated team 100% focused on your product.
  • Sign NDA for Security & Confidentiality.

Collaborate with Techvoot Solutions

Upload: .jpg, .png, .pdf, .csv, .xlsx, .doc, .docx file as document.