Setting Up Your First Backend Server for Vue.js (Part 2)

Elevating Your Vue.js App: A Comprehensive Guide to Backend Integration

Transform Your Frontend into a Full-Stack Application

Introduction:

Welcome to Part 2 our series on building a Shipping Label Generator with Vue.js! In Part 1, we created a basic frontend for our application. Now, we’re going to take it to the next level by adding a local backend with data persistence. This will allow us to store our shipping labels and retrieve them later, making our app much more useful in a real-world scenario.

What We’re Building

  • A local MongoDB database to store our shipping labels
  • A backend server using Express.js to handle API requests
  • The ability to save shipping labels to the database
  • A feature to retrieve and display previously created labels

These additions will transform our app from a simple form to a full-fledged web application with data persistence.


Why Add a Backend to Your Vue.js Application?

In the world of web development, creating a stunning frontend is only half the battle. While Vue.js excels at crafting interactive and responsive user interfaces, many applications require more than just a pretty face. This is where backend integration comes into play, transforming your standalone frontend into a powerful, full-stack application.

Adding a backend to your Vue.js application opens up a world of possibilities:

  • Data Persistence: Store user data, preferences, and application state beyond the current session.
  • Authentication and Authorization: Implement secure user accounts and role-based access control.
  • Complex Business Logic: Offload heavy computations and sensitive operations to the server.
  • API Integration: Communicate with third-party services and APIs securely.
  • Scalability: Handle increased load and data volume more efficiently.

In this comprehensive guide, we’ll walk through the process of adding a backend to a Vue.js application. We’ll use a shipping label generator as our example project, but the principles and techniques we’ll cover are applicable to any Vue.js application.

Whether you’re following along with our shipping label generator or applying these concepts to your own unique project, this guide will equip you with the knowledge to take your Vue.js skills to the next level.

Prerequisites

Before we dive in, make sure you have the following installed:

  • Node.js (version 12 or higher)
  • npm (usually comes with Node.js)
  • Vue CLI (install with npm install -g @vue/cli)
  • A code editor (like Visual Studio Code, Sublime Text, or WebStorm)

Familiarity with Vue.js basics is assumed, but we’ll explain backend concepts thoroughly for those new to server-side development.

Part 1: Setting Up the Backend Environment

1.1 Choosing a Backend Technology Stack

For our shipping label generator (and this guide), we’ll use the following stack:

  • Node.js: A JavaScript runtime built on Chrome’s V8 JavaScript engine.
  • Express.js: A minimal and flexible Node.js web application framework.
  • MongoDB: A document-based NoSQL database.
  • Mongoose: An Object Data Modeling (ODM) library for MongoDB and Node.js.

This stack, often referred to as the MEVN stack (MongoDB, Express.js, Vue.js, Node.js), provides a robust and scalable foundation for full-stack JavaScript applications.

1.2 Installing MongoDB

First, let’s install MongoDB. The process varies depending on your operating system:

For macOS (using Homebrew):

brew tap mongodb/brew
  brew install mongodb-community
  

For Windows:

1. Download the MongoDB Community Server from the official MongoDB website.

2. Run the installer and follow the installation wizard.

3. Optionally, install MongoDB Compass, a GUI for MongoDB.

For Linux (Ubuntu):

sudo apt-get update
  sudo apt-get install -y mongodb
  

After installation, start the MongoDB service:

  • macOS: brew services start mongodb-community
  • Windows: MongoDB should start automatically as a Windows service
  • Linux: sudo service mongodb start

Verify the installation by opening a terminal and running:

mongo --version
  

This should display the MongoDB version if the installation was successful.

1.3 Setting Up the Project Structure

Now, let’s set up our project structure. We’ll create separate directories for our frontend and backend:

mkdir shipping-label-generator
  cd shipping-label-generator
  mkdir frontend backend
  

Your project structure should look like this:

shipping-label-generator/
  ├── frontend/
  └── backend/
  

We’ll focus on the backend for now, but keep in mind that your Vue.js frontend will reside in the frontend/ directory.

Part 2: Creating the Backend Server

2.1 Initializing the Backend Project

Navigate to the backend directory and initialize a new Node.js project:

cd backend
  npm init -y
  

This creates a package.json file with default values.

2.2 Installing Dependencies

Install the necessary packages for our backend:

npm install express mongoose body-parser cors dotenv
  

Let’s break down what each package does:

  • express: Web application framework for Node.js
  • mongoose: MongoDB object modeling tool
  • body-parser: Middleware to parse incoming request bodies
  • cors: Middleware to enable Cross-Origin Resource Sharing
  • dotenv: Loads environment variables from a .env file

2.3 Creating the Server File

Create a new file called server.js in the backend directory:

touch server.js
  

Open server.js in your code editor and add the following code:

const express = require('express');
  const mongoose = require('mongoose');
  const bodyParser = require('body-parser');
  const cors = require('cors');
  require('dotenv').config();
  
  const app = express();
  const PORT = process.env.PORT || 5000;
  
  // Middleware
  app.use(cors());
  app.use(bodyParser.json());
  
  // Connect to MongoDB
  mongoose.connect(process.env.MONGODB_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.log('MongoDB connection error:', err));
  
  // Routes
  app.get('/', (req, res) => {
    res.send('Welcome to the Shipping Label Generator API');
  });
  
  // Start server
  app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
  });
  

This sets up a basic Express server with MongoDB connection, CORS support, and body parsing middleware.

2.4 Setting Up Environment Variables

Create a .env file in the backend directory to store environment variables:

touch .env
  

Add the following to the .env file:

PORT=5000
  MONGODB_URI=mongodb://localhost:27017/shipping_labels
  

This sets the server port and MongoDB connection URI. Make sure to add .env to your .gitignore file to keep sensitive information out of version control.

Part 3: Defining the Data Model

3.1 Creating the Shipping Label Schema

Create a new directory called models in the backend folder:

mkdir models
  cd models
  touch ShippingLabel.js
  

Open ShippingLabel.js and define the schema for our shipping labels:

const mongoose = require('mongoose');

  const shippingLabelSchema = new mongoose.Schema({
    recipientName: {
      type: String,
      required: true,
    },
    recipientAddress: {
      street: {
        type: String,
        required: true,
      },
      city: {
        type: String,
        required: true,
      },
      state: {
        type: String,
        required: true,
      },
      zipCode: {
        type: String,
        required: true,
      },
      country: {
        type: String,
        required: true,
      },
    },
    senderName: {
      type: String,
      required: true,
    },
    senderAddress: {
      street: {
        type: String,
        required: true,
      },
      city: {
        type: String,
        required: true,
      },
      state: {
        type: String,
        required: true,
      },
      zipCode: {
        type: String,
        required: true,
      },
      country: {
        type: String,
        required: true,
      },
    },
    weight: {
      type: Number,
      required: true,
    },
    shippingMethod: {
      type: String,
      enum: ['Standard', 'Express', 'Priority'],
      required: true,
    },
    trackingNumber: {
      type: String,
      unique: true,
    },
    createdAt: {
      type: Date,
      default: Date.now,
    },
  });
  
  module.exports = mongoose.model('ShippingLabel', shippingLabelSchema);
  

This schema defines the structure of our shipping label documents in MongoDB. It includes fields for recipient and sender information, package weight, shipping method, and a unique tracking number.

Part 4: Creating API Routes

4.1 Setting up the Router

Create a new directory called routes in the backend folder:

mkdir routes
  cd routes
  touch shippingLabels.js
  

Open shippingLabels.js and add the following code:

const express = require('express');
  const router = express.Router();
  const ShippingLabel = require('../models/ShippingLabel');
  
  // GET all shipping labels
  router.get('/', async (req, res) => {
    try {
      const shippingLabels = await ShippingLabel.find();
      res.json(shippingLabels);
    } catch (err) {
      res.status(500).json({ message: err.message });
    }
  });
  
  // GET a specific shipping label
  router.get('/:id', getShippingLabel, (req, res) => {
    res.json(res.shippingLabel);
  });
  
  // POST a new shipping label
  router.post('/', async (req, res) => {
    const shippingLabel = new ShippingLabel({
      recipientName: req.body.recipientName,
      recipientAddress: req.body.recipientAddress,
      senderName: req.body.senderName,
      senderAddress: req.body.senderAddress,
      weight: req.body.weight,
      shippingMethod: req.body.shippingMethod,
      trackingNumber: generateTrackingNumber(),
    });
  
    try {
      const newShippingLabel = await shippingLabel.save();
      res.status(201).json(newShippingLabel);
    } catch (err) {
      res.status(400).json({ message: err.message });
    }
  });
  
  // UPDATE a shipping label
  router.patch('/:id', getShippingLabel, async (req, res) => {
    if (req.body.recipientName != null) {
      res.shippingLabel.recipientName = req.body.recipientName;
    }
    // Add similar checks for other fields
  
    try {
      const updatedShippingLabel = await res.shippingLabel.save();
      res.json(updatedShippingLabel);
    } catch (err) {
      res.status(400).json({ message: err.message });
    }
  });
  
  // DELETE a shipping label
  router.delete('/:id', getShippingLabel, async (req, res) => {
    try {
      await res.shippingLabel.remove();
      res.json({ message: 'Shipping label deleted' });
    } catch (err) {
      res.status(500).json({ message: err.message });
    }
  });
  
  // Middleware function to get a shipping label by ID
  async function getShippingLabel(req, res, next) {
    let shippingLabel;
    try {
      shippingLabel = await ShippingLabel.findById(req.params.id);
      if (shippingLabel == null) {
        return res.status(404).json({ message: 'Shipping label not found' });
      }
    } catch (err) {
      return res.status(500).json({ message: err.message });
    }
  
    res.shippingLabel = shippingLabel;
    next();
  }
  
  // Helper function to generate a unique tracking number
  function generateTrackingNumber() {
    return 'TN' + Math.random().toString(36).substr(2, 9).toUpperCase();
  }
  
  module.exports = router;
  

This router implements CRUD (Create, Read, Update, Delete) operations for shipping labels. It includes routes to get all labels, get a specific label, create a new label, update an existing label, and delete a label.

4.2 Integrating the Router with the Server

Now, let’s update our server.js file to use the new router:

const express = require('express');
  const mongoose = require('mongoose');
  const bodyParser = require('body-parser');
  const cors = require('cors');
  require('dotenv').config();
  
  const app = express();
  const PORT = process.env.PORT || 5000;
  
  // Middleware
  app.use(cors());
  app.use(bodyParser.json());
  
  // Connect to MongoDB
  mongoose.connect(process.env.MONGODB_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.log('MongoDB connection error:', err));
  
  // Routes
  const shippingLabelRoutes = require('./routes/shippingLabels');
  app.use('/api/shipping-labels', shippingLabelRoutes);
  
  app.get('/', (req, res) => {
    res.send('Welcome to the Shipping Label Generator API');
  });
  
  // Start server
  app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
  });
  

This update integrates our shipping label routes into the main server file, making them accessible under the /api/shipping-labels endpoint.

Part 5: Testing the API

Now that we have set up our backend, let’s test it to make sure everything is working correctly.

5.1 Starting the Server

In your terminal, navigate to the backend directory and run:

node server.js
  

You should see messages indicating that the server is running and MongoDB is connected.

5.2 Testing with Postman

We’ll use Postman to test our API endpoints. If you don’t have Postman installed, you can download it from https://www.postman.com/downloads/.

Here are some tests you can run:

  1. Create a new shipping label (POST request)
    URL: http://localhost:5000/api/shipping-labels
    Body (raw JSON):
    {
    "recipientName": "John Doe",
    "recipientAddress": {
    "street": "123 Main St",
    "city": "Anytown",
    "state": "CA",
    "zipCode": "12345",
    "country": "USA"
    },
    "senderName": "Jane Smith",
    "senderAddress": {
    "street": "456 Elm St",
    "city": "Othertown",
    "state": "NY",
    "zipCode": "67890",
    "country": "USA"
    },
    "weight": 2.5,
    "shippingMethod": "Standard"
    }

  2. Get all shipping labels (GET request)
    URL: http://localhost:5000/api/shipping-labels
  3. Get a specific shipping label (GET request)
    URL: http://localhost:5000/api/shipping-labels/{id}
    Replace {id} with the ID of a shipping label you created.
  4. Update a shipping label (PATCH request)
    URL: http://localhost:5000/api/shipping-labels/{id}
    Body (raw JSON):
    {
    "recipientName": "John Doe Jr.",
    "weight": 3.0
    }

  5. Delete a shipping label (DELETE request)
    URL: http://localhost:5000/api/shipping-labels/{id}

Run these tests to ensure that your API is working correctly. You should be able to create, read, update, and delete shipping labels.

Conclusion

Congratulations! You’ve successfully set up a backend server for your Vue.js Shipping Label Generator application. This backend provides a robust API for managing shipping labels, including creating new labels, retrieving existing ones, updating label information, and deleting labels.

Here’s a summary of what we’ve accomplished:

  1. Set up a MongoDB database for storing shipping label data
  2. Created an Express.js server to handle API requests
  3. Defined a Mongoose schema for our shipping label data model
  4. Implemented CRUD operations for shipping labels
  5. Tested our API endpoints to ensure everything is working correctly

With this backend in place, your Vue.js frontend can now interact with a persistent data store, allowing users to create and manage shipping labels effectively. In the next part of this series, we’ll focus on integrating this backend with our Vue.js frontend, creating a seamless full-stack application.

Remember, this backend can be adapted and expanded to suit various needs. You might want to add user authentication, implement more complex business logic, or integrate with shipping carrier APIs for real-time shipping rates and tracking. The possibilities are endless!

Happy coding, and we’ll see you in the next part where we’ll bring our frontend and backend together!

Join Our Community!

🌟 Get exclusive insights and the latest IT tools and scripts, straight to your inbox.

🔒 We respect your privacy. Unsubscribe at any time.

Andy N

Information Technology Support Analyst with over seven years of experience (in the telecommunications and manufacturing industries) ranging from user support to administering and maintaining core IT systems.

Related Posts

×