Skip to content

The Ultimate Guide to Understanding and Using the MEAN Stack

The MEAN stack has become one of the most popular and powerful ways for developers to rapidly build dynamic, data-driven web applications. MEAN is an acronym that stands for MongoDB, Express.js, Angular, and Node.js – the four key technologies that make up this end-to-end JavaScript stack.

By utilizing JavaScript across the entire web app, from the database to the backend server to the frontend UI, MEAN enables a highly efficient and productive development process. Let‘s dive into what each component of the MEAN stack does and how they all work together. We‘ll also walk through detailed examples of using MEAN to build real-world applications.

Breaking Down the MEAN Acronym

Before we get hands-on with the MEAN stack, it‘s important to understand the role that each technology plays:

MongoDB – This is the database layer of the stack. MongoDB is a NoSQL database that stores data in flexible, JSON-like documents. It‘s known for high performance, easy scalability, and dynamic querying. In MEAN, MongoDB serves as the primary data store.

Express.js – Express is a minimalist web framework that runs on Node.js. It provides a robust set of features for building web applications and APIs, like route handling, HTTP utility methods, and middleware support for request processing. Express acts as the backend web application framework in MEAN.

Angular – Developed by Google, Angular is a TypeScript-based framework for building dynamic frontend user interfaces. It provides a component-based architecture, declarative templates, dependency injection, and seamless integration with backend services. Angular powers the client-side of MEAN applications.

Node.js – Node is a JavaScript runtime built on Chrome‘s V8 engine. It allows running JavaScript on the server, making it possible to use a single language throughout your web app. Node also comes with a huge ecosystem of open-source libraries accessed through the npm package manager. It serves as the platform for running the MEAN backend.

By combining these technologies, MEAN enables an isomorphic development approach – using JavaScript on both the frontend and backend. This has huge benefits in terms of code reusability, unified data serialization, and leveraging existing JavaScript developer skills.

Why Use the MEAN Stack? Key Benefits and Use Cases

There are many good reasons why MEAN has gained widespread adoption for web development:

  1. Full-Stack JavaScript – By using JavaScript across the entire application stack, you can maximize code reuse and cohesion. Developers only need to know one language well.

  2. High Performance – Node.js and Express enable building highly scalable, event-driven server-side code. MongoDB also delivers high read-write speeds. Angular compiles to optimized JavaScript for fast browser rendering. Together, MEAN apps have excellent performance.

  3. Cloud-Native – MEAN is ideal for deploying to cloud platforms like AWS, Azure, and Heroku. You can easily containerize the app or deploy serverless functions. The stack is lightweight and flexible.

  4. Extensive Tooling & Resources – Each component of MEAN has a large community with in-depth tutorials, open-source projects, and tooling. This makes ramping up and troubleshooting easier.

  5. Real-Time & Single-Page Apps – MEAN excels at building real-time applications with WebSocket support. It‘s also great for single-page apps that render views client-side.

Some key use cases where MEAN shines include:

  • Real-time collaboration tools
  • Social networks and discussion forums
  • Content management systems
  • Backend APIs for mobile apps
  • Workflow automation and form-based apps
  • Dashboards with live data updates

Now that we understand the why, let‘s see how to actually use MEAN to build something.

Getting Started With the MEAN Stack

We‘ll walk through building a basic TODO application to demonstrate the fundamentals of the MEAN stack. Our app will allow creating, reading, updating and deleting TODO items with a MongoDB backend and Angular frontend.

Prerequisites

Make sure you have the following installed before starting:

  • Node.js & npm
  • MongoDB
  • Angular CLI

Backend Setup with Node.js and Express

First, let‘s set up a new Node project and install the necessary dependencies:

mkdir mean-todo
cd mean-todo
npm init -y
npm install express body-parser mongoose

Next, create a file called server.js with the following code to set up an Express server:

const express = require(‘express‘);
const bodyParser = require(‘body-parser‘);
const app = express();

// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Routes
app.get(‘/‘, (req, res) => {
    res.send(‘Welcome to the MEAN TODO app!‘);
});

// Start server
const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

This sets up a basic Express server with body-parser middleware and a default route. We can run it with:

node server.js

Connecting to MongoDB

Now let‘s connect our Express backend to a MongoDB database using Mongoose ODM. First install it:

npm install mongoose

Then add the following to server.js to establish the DB connection:

const mongoose = require(‘mongoose‘);

mongoose.connect(‘mongodb://localhost/mean-todo‘, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log(‘Connected to the database!‘);
}).catch(err => {
    console.log(‘Cannot connect to the database!‘, err);
    process.exit();
});

This connects to a locally running MongoDB instance. For production, you‘d want to use a cloud-hosted MongoDB service.

Next, let‘s define a Mongoose schema and model for our TODO items:

const todoSchema = new mongoose.Schema({
    title: String,
    completed: Boolean
});

const Todo = mongoose.model(‘Todo‘, todoSchema);

We now have a Todo model that we can use to interact with TODO documents in the MongoDB database.

Defining API Routes

Let‘s build out an API for our TODO app by adding Express routes to create, read, update, and delete todos.

Add the following route handlers to server.js:

// GET all todos
app.get(‘/todos‘, async (req, res) => {
    try {
        const todos = await Todo.find();
        res.json(todos);
    } catch (err) {
        res.status(500).send(err);
    }
});

// POST a new todo
app.post(‘/todos‘, async (req, res) => {
    const todo = new Todo({
        title: req.body.title,
        completed: false
    });

    try {
        const savedTodo = await todo.save();
        res.json(savedTodo);
    } catch (err) {
        res.status(400).send(err);
    }
});

// GET a single todo by ID
app.get(‘/todos/:id‘, async (req, res) => {
    try {
        const todo = await Todo.findById(req.params.id);
        res.json(todo);
    } catch (err) {
        res.status(404).send(err);
    }
});

// PUT (update) an existing todo by ID
app.put(‘/todos/:id‘, async (req, res) => {
    try {
        const updatedTodo = await Todo.findByIdAndUpdate(
            req.params.id,
            { $set: req.body },
            { new: true }
        );
        res.json(updatedTodo);
    } catch (err) {
        res.status(400).send(err);
    }
});

// DELETE a todo by ID
app.delete(‘/todos/:id‘, async (req, res) => {
    try {
        await Todo.findByIdAndDelete(req.params.id);
        res.json({ message: ‘Todo deleted‘ });
    } catch (err) {
        res.status(400).send(err);
    }
});

These route handlers use Mongoose to perform CRUD operations against the MongoDB database. We now have a fully functional backend API for the app!

Frontend with Angular

With the backend API in place, let‘s build a frontend interface using Angular to interact with it.

First, install the Angular CLI if you haven‘t already:

npm install -g @angular/cli

Then generate a new Angular project in a separate folder:

ng new mean-todo-frontend
cd mean-todo-frontend

Run ng serve and visit http://localhost:4200 to see the default Angular app.

Now, let‘s generate an Angular service to encapsulate the API calls to our backend:

ng generate service todo

Update todo.service.ts with methods to make HTTP requests to the backend API:

import { Injectable } from ‘@angular/core‘;
import { HttpClient } from ‘@angular/common/http‘;
import { Observable } from ‘rxjs‘;

@Injectable({
  providedIn: ‘root‘
})
export class TodoService {
  private baseUrl = ‘http://localhost:3000/todos‘; 

  constructor(private http: HttpClient) { }

  getTodos(): Observable<any> {
    return this.http.get(`${this.baseUrl}`);
  }

  getTodo(id: string): Observable<any> {
    return this.http.get(`${this.baseUrl}/${id}`);
  }

  createTodo(data: any): Observable<any> {
    return this.http.post(`${this.baseUrl}`, data);
  }

  updateTodo(id: string, data: any): Observable<any> {
    return this.http.put(`${this.baseUrl}/${id}`, data);
  }

  deleteTodo(id: string): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`);
  }
}

This service provides methods to get, create, update, and delete todos by making the corresponding HTTP requests to our backend API.

Next, generate an Angular component to display the list of todos:

ng generate component todos

Update the todos.component.ts file to use the TodoService to fetch and display todos:

import { Component, OnInit } from ‘@angular/core‘;
import { TodoService } from ‘../todo.service‘;

@Component({
  selector: ‘app-todos‘,
  templateUrl: ‘./todos.component.html‘,
  styleUrls: [‘./todos.component.css‘]
})
export class TodosComponent implements OnInit {
  todos: any;

  constructor(private todoService: TodoService) { }

  ngOnInit(): void {
    this.getTodos();
  }

  getTodos(): void {
    this.todoService.getTodos()
      .subscribe(todos => this.todos = todos);
  }
}

And update todos.component.html with the template to display the list of todos:

<h2>My Todos</h2>

<ul>
  <li *ngFor="let todo of todos">
    {{todo.title}}
  </li>
</ul>

Finally, update app.component.html to include the todos component:



<app-todos></app-todos>

Run the Angular dev server with ng serve and you should see your list of todos from the database!

From here, you can expand the Angular frontend with forms and buttons to create, update, and delete todos. The TodoService already has methods to make the corresponding API calls.

By leveraging Angular‘s declarative templates, component-based architecture, and integration with backend services, you can build out a rich, interactive frontend for the MEAN stack app.

Advanced MEAN Stack Topics

We‘ve covered the basics of using the MEAN stack, but there are many more advanced topics to explore:

  • User Authentication – Add user registration and login by using the Passport.js library with JSON Web Tokens (JWT). Store encrypted user credentials in MongoDB.

  • Real-Time Updates – Use Socket.IO to add real-time functionality to your MEAN apps. For example, you could have the TODO list automatically update across clients when an item is added or removed.

  • Deployment – Deploy your MEAN app to production by using a cloud provider like Heroku or AWS. You‘ll need to set up a production-grade MongoDB database and configure the appropriate environment variables.

  • Code Sharing – Since Angular also uses TypeScript, you can share interfaces, models, and validation logic with your Express backend for an even more cohesive codebase.

  • Testing – Each layer of the MEAN stack has a variety of testing tools. Integrate unit testing and end-to-end testing into your development workflow for improved reliability.

This is just scratching the surface of what‘s possible with the MEAN stack. It‘s an incredibly flexible and powerful set of technologies for building modern web applications.

MEAN Stack vs. Other Web Development Stacks

The MEAN stack is just one approach to full-stack web development. Some other common stacks include:

  • LAMP – Linux, Apache, MySQL, PHP
  • Ruby on Rails – Ruby, Rails framework, various databases
  • MERN – MongoDB, Express, React, Node.js
  • Django – Python, Django framework, various databases

The MEAN stack stands out for its end-to-end JavaScript approach. For teams that are already experienced with JavaScript, adopting MEAN means not having to context-switch between different languages and paradigms.

The component-based architecture of Angular also makes it easy to build large, complex frontend applications. React (as seen in the MERN stack) takes a slightly different approach with a more flexible library-based model.

Ultimately, the choice of web stack comes down to the specific needs and constraints of your project. The MEAN stack is ideal when you need a scalable, extensible, real-time application with an emphasis on frontend complexity.

For teams that are already invested in JavaScript and want to use it across the entire web stack, MEAN is the natural choice. Its huge ecosystem and community support also make it a safe bet for long-term projects.

Conclusion

We‘ve taken a deep dive into the MEAN stack and seen how MongoDB, Express.js, Angular, and Node.js combine to enable full-stack web development with JavaScript.

By using a common language across the stack, MEAN empowers developers to build complex apps with less context-switching and more code reuse. The event-driven nature of Node.js and the rich frontend architecture of Angular also lend themselves to building highly responsive, real-time applications.

We walked through a step-by-step example of using MEAN to build a basic application. From setting up a project skeleton to defining a data model to building out API routes to integrating with an Angular frontend, we saw all the key aspects of the stack working together.

There are many more advanced topics and use cases to explore with the MEAN stack, from user authentication to real-time updates to testing and deployment. The flexibility and scalability of the stack make it a solid choice for a wide variety of web development projects.

At the end of the day, the MEAN stack is a powerful approach that enables teams to build full-featured web applications with less complexity and more code reuse. Its vibrant ecosystem and community also ensure that developers have the resources they need to succeed.

Hopefully, this guide has given you a solid foundation to start working with the MEAN stack. Happy coding!