Research collaborate build

Sep 16, 2020

Express.js, Django & Laravel - The Backend Badasses

A backend developers journey through the Big 3 to figure out what is best and when.
Rajat
RajatSoftware Engineer
lines

In this article, I’m going to explain Django REST Framework and, at the same time, compare it to ExpressJS (NodeJS Framework) and Laravel (PHP Framework).

Basics

Express.js

If you check out the home page of ExpressJS, you will find it describing itself as a minimal and flexible Node.js web application framework. It is because Express.js is nothing but a very thin layer over Node.js, which is a Javascript runtime environment. Node.js, in its raw form, is very difficult to implement and Express.js hides all the complexities that lie within. We are able to use Javascript on the server-side because of Node.js and easily because of Express.js. Among all the framework's that Node.js has, Express.js has the most minimalistic implementation.

Laravel

PHP is most powerful full-stack web framework out there. It has an easy implementation, great community support (which only comes after a framework has proved it's worth), has a great guide to their implementation and its architecture makes it stand out. Laravel is already preloaded with things like sessions, cookies, caching management and are easily configured using their config files. With the help of its command-line tool artisan, Laravel makes development fast and keeps us unbothered from the trouble of maintaining a proper structure.

Django REST

A framework that claims that you can develop your applications much faster using it and is truly acknowledged for that is Django. Django is Python's most popular web framework and a great option for your higher scalable applications ready to be deployed after running some checks on its setting.py file, which assures you of the security of your application. Fast development and great security are the two things Django provides.

Let's talk about Django REST. Well, Django REST is a more abstract version of Django solely abiding by the Representational State Transfer principle. Django REST has subclassed and modified the Django classes to provide the user with more layered and we will handle most of the things so you don't have to worry approach.

Structure

Express.js

  • When using express-generator, it gives us a structure like this:

Screenshot 2020-08-20 at 10.24.38 AM.png

  • We can build our Express application from scratch by initializing a directory using the npm init command too.
  • Generally, Express.js is referred to as an MVC framework but it is not. We have to make it an MVC.
  • We can configure our application using the .env file, but it won't have built-in support for that. We have to use the dotenv module to load our environmental variables.
  • package.json is the file that keeps track of packages (It's a JS thing).
  • To use UI, we have to install a templating engine (EJS, pug, handlebar, etc). It will create views directory for us. We can use partials inside the views directory to avoid code redundancy.

Laravel

We can generate a Laravel app using Laravel installer or composer. Both will give you the structure as shown below:

Screenshot 2020-08-20 at 10.36.53 AM.png

  • Laravel is an MVC framework, but still the Models folder is missing from its directory structure. In the next versions, it will come preloaded with App\Models directory.
  • We have .env file and files in the config folder to configure our application. In the config folder, we have multiple files, one each for the app, database, queues and so on, keeping each component's concern separate.
  • The composer.json is there for us to keep track of PHP packages we have installed and you already know why package.json exists. The webpack.mix.js helps us compile our CSS and JS files into a single bundle.
  • The php artisan make:choose_functionalities_from_the_listed_ones will create a separate directory if it does not exist before creating a file for your functionality.
  • Laravel has a built-in blade templating engine to compile your views and already comes with the views directory.

Django REST

  • Let's look at the basic structure provided to us by the command django-admin startproject projectname. We will get the structure as follows: we have a one-parent directory and inside it, we have another directory that contains the files needed to boot our application.

Screenshot 2020-08-22 at 6.47.29 PM.png

  • Collection of apps under a project: This is the architecture of Django. We can add more apps to Django using python manage.py startapp appName. These apps are nothing but directories containing specific functionality. The startapp command will give you a directory with the following structure.

Screenshot 2020-08-22 at 10.59.06 PM.png

  • Each app directory contains an init.py file that is generally empty. It signifies that the current directory is a Python package directory.
  • The manage.py file contains the code to execute our commands. (python manage.py command_you_want_execute)
  • The views represent the controllers in Django. So, your business logic will go into the views.py directory.
  • Django doesn't have a utility to handle environmental variables as well. The setting.py file is the place where we configure our application. The use of an external module is required to load environment variables from the .env file.
  • There is no particular way of organizing templates. The templates in Django are .html files and are compiled using DTL(Django Template Engine) Or Jinja2(A popular alternative to DTL).

Server (HTTP/HTTPS)

ExpressJs

  • Express.js calls the listen method on its app instance which in turn calls the Node.js raw implementation of creating a server and since Node.js under the hood uses the http module, your server is ready to serve HTTP requests.

const app = require('express')();

app.listen(8000, ()=> {
	console.log('Listening');
});

  • There is a slight modification to enforce HTTPS.

const https = require('https');
const app = require('express')();
const fs = require('fs');

const options = {
  key: fs.readFileSync('key.pem'), // SSL certificate key
  cert: fs.readFileSync('cert.pem') // SSL certificate
};

https.createServer(options, app).listen(8000);

  • There is much more to HTTPS rather than just creating a server using an SSL certificate, but security management in Express.js requires much more expertise.

Laravel

  • Laravel boots the server from its bootstrap directory. It creates an instance of an application by calling Illuminate/Foundation/Application object which requires the full path of your project's directory. Laravel at the time binds the interfaces with their component.
  • Update Apache configuration to enforce HTTPS by providing it the SSL certificate key and the certificate itself.
  • You can configure or add the middleware to your Laravel project to redirect HTTP requests to HTTPS.

Django REST

  • All Python-based web frameworks are WSGI compliant. WSGI (Web Server Gateway Interface) is an interface that governs how the web server communicates with your web application
  • To load our application we have a WSGI application callable object. (A Python function, class or class instance with the call method)

// Django implementation to create application callable
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

application = get_wsgi_application()
// A WSGI application
class Application(object):
    def __call__(self, environ, start_fn):
        start_fn('200 OK', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"

app = Application()

  • Configuring the security of our application is the one thing that Django outshines everyone in. Your application can be configured to follow the HTTPS protocol by setting some flags in setting.py file.

// Redirect your application to HTTPS
SECURE_SSL_REDIRECT = os.getenv('SECURE_SSL_REDIRECT') == 'True'

// Allow cookies set from only HTTPS connection
SESSION_COOKIE_SECURE = os.getenv('SESSION_COOKIE_SECURE') == 'True'

// Allow CSRF cookies from only HTTPS connection
CSRF_COOKIE_SECURE = os.getenv('CSRF_COOKIE_SECURE') == 'True'

Request Validation

Express.js

  • No built-in implementation for validation.
  • Has a lot of npm libraries ready to contribute for validation.
  • Some popular libraries are
    1. express-validator (Suitable for express application).
    2. validator.
    3. joi.

Laravel

  • Most powerful validation built-in library among all three frameworks.
  • Automatic validation and rejection using Illuminate/Http/Request objects' validate method.
  • Can manually validate the request object and return response in your preferred way.
  • Vast options are available for vast error case scenarios.
  • Great documentation to follow up on any particular validation.

Django REST

  • Forms are Django thing and Serializers are Django REST's way of validating the request body.
  • Automatic rejection on validation, provided you set a flag to enable this.
  • Serializers validate your data and convert complex object data, such as model instance, to Python native data type.
  • The primary goal of serializers is to serialize and de-serialize the data. They might not be very good at handling complex validation types on their own (can write your own custom validation).

Middlewares (Session, Cookies, Caching, Throttling)

Express.js

  • Middlewares in Express.js have access to the request object, response object, and next function.

let myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

  • Calling the next function is the trigger to the next middleware in the series.
  • Express.js needs to install external modules to handle session, cookie, throttle management. They are configured where they are declared.
  • Session Middleware
    • Can use express-session module to enable session.
    • By default, implementation exists to use cookies.

let session = require('express-session')

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

  • Cookie Middleware
    • Can use the cookie-parser module to parse cookies and set them.

let app = express()
app.use(cookieParser())  

//Use secret to sign cookies
app.use(cookieParser('iwontgivemycookie', {}));

  • Throttling Middleware
    • There might be many modules to handle this, but Express.js official docs suggest the use of the express-rate-limit module.
    • Has a built-in store as a memory but also has options such as Redis, Memcached, and mongo to use as a store.

const rateLimit = require("express-rate-limit");
 
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100
});

// Apply it before hitting any endpoint
app.use("/api/", apiLimiter);

  • Caching Middleware
    • You can just directly use Redis, memory, a file as a storage utility for the cache or you can use an npm package that will utilize these storage units for you and will provide you some easy implementation and extra features.

Laravel 

  • The middleware in Laravel is provided with two arguments: Request object and a next function call.

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}​

  • The next function calls the next middleware in series with the request as an argument to it, but unlike in Express.js, the call to next returns a response back to the same middleware. We can make some alterations to the response object or execute any operation we want to perform after passing control to the next middleware. It's basically a boomerang.
  • The option to apply middleware globally, or on certain controllers, can set their priority order.
  • Applying middleware to a group of routes can be done in many ways.
  • Laravel is pre-loaded with configurations and libraries to handle sessions, cookies, caching, and throttling management.
    • We can configure them from the config file.

Django REST

  • Django & Laravel's middleware implementation is quite similar. We can perform some operations after passing control to the next middleware.
  • Let's look at an example of Django Middleware implementation. You might not find middleware implementation using this approach in some of the Django's libraries because this is the updated implementation. Earlier Django middlewares subclass MiddlewareMixin Class to create custom middlewares.

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

  • The get_response method here calls the next middleware or the view in line.
  • Apart from this Django provides three other methods/hooks to have more control over data flow
    • process_view: Gets called just before executing view or middleware.
    • process_exception: When a view encounters an error, this hook gets called.
    • process_template_response: This hook is made specifically to run when the view uses the render method or returns a TemplateResponse.
  • Middlewares can be globally applied by listing them under the middleware section in the setting.py file. Seems easy.
  • Django does not provide any boilerplate code to handle per view or middleware on selected views scenario. It can be done using the process_view hook which is given view_function (the view that's to be called) as an argument. A series of if conditions can be placed to check if we wanna apply this middleware here. Yeah, a little inconvenient.
  • Django REST tries to separate the authentication from the raw middleware kind of approach. It can be best explained using these following code:

Screenshot 2020-08-29 at 6.07.40 PM.png
Screenshot 2020-08-29 at 6.07.55 PM.png

  • This approach of Django is more flexible than the middleware one since it allows us to use authentication on the per-view basis too. We are allowed to create our custom authentication class.
  • Django REST also comes with pre-loaded libraries to manage session, cookies, caching, throttling. Session and cookies management already exists and there is a need to include throttling and caching libraries.

ORM

Express.js

  • No built-in ORM.
  • Can use the external library sequelize for it (There are many options available though).
  • Sequelize comes with its command-line tool which helps in generating models, migration, and seeders.

Laravel

  • Laravel has a built-in eloquent ORM.
  • Laravel comes with the command-line utility to handle generating models, migrations, seeders.
  • Laravel ORM is very powerful and has great documentation to witness it.

Django REST

  • Django stands head to head with Laravel on this one.
  • Django startapp command gives us a new directory with Model.py to store our model details, and a migration directory to store migrations that are generated from the command-line.
  • Django REST utilizes the same ORM, but have customized views to handle basic CRUD operation on its own with minimal lines of code, though Django ORM is capable of handling complex queries as well.

CRON & Queues

Express.js

  • The node-schedule or node-cron are the popular libraries that can help to schedule our cron jobs. Meanwhile, we have packages like bull and Kue for queues management in Express.js.
  • Using cron packages, a job is scheduled as soon as the server boots up.
  • The server will keep on listening & processing the queues as long as it is up & running.
  • Bull and Kue provide us a default dashboard to give us a UI representation of our queue management. Some of the packages may not have that functionality.

Laravel

  • With the option of configuring queues from the config file. Laravel already has a built-in queue management service.
  • Easy implementation of queues.
  • Allows naming our own queues without having to declare them at first.
  • Laravel has its own command scheduler to run the scheduled jobs but Laravel relies on the server crontab entries to keep on running its command scheduler.
  • The artisan commands are there to keep on listening to queues, but they can't run forever so a daemon process is needed to run in the background.

Django REST 

  • Django and ExpressJs are partners in this scenario.
  • Django needs an external library like celery (which is a python built module and is easily configurable with our Django application)
  • Celery can be used both for queues management and job scheduling.
  • Django has quite a popular and helpful module called django_extension which gives us a handful of command-line utilities to handle creating jobs, commands, show URLs, etc. Then, job scheduling can be done using the same approach as I mentioned for Laravel, but we are still one down with queue against Laravel even after using django_extension.

Conclusion

Phew! You made it this far.

If you are new to the programming world & after going through this documentation, you might be thinking very low of Express.js. Well, you should not. Express.js was not created as a full-stack web framework. It was created to make the dream that Node.js gave us - Running Javascript at server-side a lot more developer-friendly and easy to use. Though Express.js make us wander around the web, go through the documentation of modules and integrate it into your application on your own, but it gives you a much more detailed overview of your functionality. Express.js doesn't hold back in performance and scalability due to this. You can always choose Express.js if you want a fast performing, highly scalable server and want to explore the web a bit more.

Laravel already wins in lots of scenarios in this article. It is loaded with the necessities that an application needs for a good head start and is easily configurable. Laravel's great documentation makes it easy for any developer to work with it.

Go with Django if you want your application to develop at a faster speed and are concerned about the security of your application. Sites like Pinterest, The Washington Post, Instagram are built using Django, so you can't question the scalability of Django. Its DRY principle is the reason Django is able to do so much with very few lines of code and doesn't get heavy as the application continues to grow.

Performance of each of this framework is excellent, so don't worry about that.

At the end You cannot judge a framework in an absolute sense. It all depends on your use case.

Thank you for reading!

Hire our Development experts.