DEV Community

nermineslimane
nermineslimane

Posted on

Always separate app and server files !

This is considered one of the best-practices of working with node/express
Most of us we just combine them in one single file declaration like follows

const express = require('express');

const app = express();
app.use(express.json());
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const httpServer = require('http').createServer(app);

httpServer.listen(PORT, () => {
  console.log(`listening on *:${process.env.PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Well that's not the best we can do

Otherwise: Your API will be accessible for testing via HTTP calls only (slower and much harder to generate coverage reports). It probably won't be a big pleasure to maintain hundreds of lines of code in a single file.

So what's the alternative?

The api declaration and the the network related configuration should be separated to gain us :

  • testing the API in-process without having to perform the network calls
  • Faster testing execution
  • Getting wider coverage metrics of the code
  • Allows deploying the same API under flexible and different network conditions
  • Better separation of concerns and cleaner code

How to do it ?

API declaration should reside in app.js:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

Enter fullscreen mode Exit fullscreen mode

Server network declaration, should reside in /bin/www
const app = require('../app');
const http = require('http');


// Get port from environment and store in Express.
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

// Create HTTP server.
const server = http.createServer(app);
Enter fullscreen mode Exit fullscreen mode

And the global project structure should be like follows

Image description

I hope this was helpful to develop more good habits and best practices !

Top comments (4)

Collapse
 
florianwaltherprivate profile image
Florian Walther

Thank you, I've been wondering about this. Where would you put the code that connects to MongoDB Atlas? In app or server?

Collapse
 
sonimonish00 profile image
Monish Soni

I had the same doubt earlier, what i think is that it is better to put Mongodb atlas code in server.js bcz in real world scenario, http server needs to connect to db first and then start which would be more convenient if u put it in server.js rather than app.js. Also put MongoDB Connection as separate module/file.
Following is my folder structure :

Backend

  • App (Follows MVC)
    • index.js (Contains express app code & calls to MVC part)
    • Controller
    • Middlewares
    • Models
    • Routes
  • Database (MongoDB Atlas/mongoose Connection)
    • db.config.js
  • Env (Environment variable prod/dev - For mongodb url, etc.)
    • .env
  • server.js (Main entry point - code related to http server, mongodb conn etc. here)
Collapse
 
florianwaltherprivate profile image
Florian Walther

Thank you, that makes sense! Especially the point about starting the server after the connection was successful.

Collapse
 
xarlizard profile image
Charlie

Really helpful explanation 🙏