0
0
ExpressHow-ToBeginner · 4 min read

How to Structure an Express Project: Best Practices and Example

To structure an Express project, organize your code into folders like routes for URL handlers, controllers for business logic, and middleware for reusable functions. Keep your app.js or server.js file simple by importing these modules, which makes your project easier to maintain and scale.
📐

Syntax

An Express project typically has a main file like app.js or server.js that sets up the server and imports routes. Routes define URL paths and link to controller functions that handle requests. Middleware functions run before routes to process requests or handle errors.

  • app.js/server.js: Entry point to start the server.
  • routes/: Folder for route definitions.
  • controllers/: Folder for request handling logic.
  • middleware/: Folder for reusable functions like authentication.
  • models/: (optional) Folder for database models.
javascript
const express = require('express');
const app = express();

const userRoutes = require('./routes/userRoutes');

app.use(express.json());
app.use('/users', userRoutes);

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
💻

Example

This example shows a simple Express project structure with separate files for routes and controllers. The app.js file imports the user routes and starts the server. The routes/userRoutes.js file defines URL paths and connects them to controller functions. The controllers/userController.js file contains the logic to handle requests.

javascript
// app.js
const express = require('express');
const app = express();
const userRoutes = require('./routes/userRoutes');

app.use(express.json());
app.use('/users', userRoutes);

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

// routes/userRoutes.js
const express = require('express');
const router = express.Router();
const { getUsers, getUserById } = require('../controllers/userController');

router.get('/', getUsers);
router.get('/:id', getUserById);

module.exports = router;

// controllers/userController.js
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

exports.getUsers = (req, res) => {
  res.json(users);
};

exports.getUserById = (req, res) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (!user) return res.status(404).json({ message: 'User not found' });
  res.json(user);
};
Output
Server running on port 3000 GET /users => [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}] GET /users/1 => {"id":1,"name":"Alice"} GET /users/3 => {"message":"User not found"}
⚠️

Common Pitfalls

Common mistakes include putting all code in app.js, which makes the project hard to read and maintain. Another pitfall is mixing route definitions with business logic instead of separating them into controllers. Forgetting to use express.json() middleware can cause issues parsing JSON request bodies.

javascript
// Wrong: All code in app.js
const express = require('express');
const app = express();

app.get('/users', (req, res) => {
  res.json([{ id: 1, name: 'Alice' }]);
});

app.listen(3000);

// Right: Separate routes and controllers
// routes/userRoutes.js
const express = require('express');
const router = express.Router();
const { getUsers } = require('../controllers/userController');
router.get('/', getUsers);
module.exports = router;

// controllers/userController.js
exports.getUsers = (req, res) => {
  res.json([{ id: 1, name: 'Alice' }]);
};
📊

Quick Reference

  • app.js/server.js: Start server, import routes.
  • routes/: Define URL paths, connect to controllers.
  • controllers/: Handle request logic.
  • middleware/: Functions for request processing.
  • models/: Database schemas (optional).
  • Use express.json() to parse JSON bodies.
  • Keep files small and focused on one task.

Key Takeaways

Organize Express projects by separating routes, controllers, and middleware into folders.
Keep your main server file simple by importing modular code.
Use middleware like express.json() to handle request parsing.
Avoid putting all logic in one file to keep code maintainable.
Name files and folders clearly to reflect their purpose.