Over the past two years I have been involved in a project that was built on the Laravel framework. For those not familiar with it, Laravel is a PHP based MVC framework that supports a variety of project types including regular database driven websites and microservices.
Laravel’s popularity is not least due to the fact that many of the features you are likely to need come out of the box. This includes amongst others:
- Models, Views, Controllers
- Eloquent ORM
- Database Migrations
- Wrappers for queues
- Authentication, Encryption and Hashing
- Unit tests
In this article, therefore, we will do a comparison of AdonisJS with Laravel so engineers and architects looking to migrate over or build a hybrid solution know what to expect.
Laravel and its counterpart Lumen (aimed at microservices) provide simple out of the box installation along with a development environment called Homestead which incorporates Vagrant.
AdonisJS is also easy to setup and can be installed directly onto a machine with NodeJS present without needing to install separate web servers such as NGINX. This process is handled by npm as follows:
npm i -g @adonisjs/cli
There are three options for project types available to you. A lightweight version which does not include all the features of AdonisJS, an API-only version which is more akin to Lumen, and the full install which is the counterpart to Laravel. The full install is the default option.
In this article we will be concentrating on the more extensive installation option and comparing it to Laravel 5.6.
To create a project with the full install version you can run:
Once installed it can be served using:
adonis serve --dev
You project will now be available on port 3333 on 127.0.0.1.
And that’s it, you are now ready to start developing.
Framework structure comparison
Now let’s take a look at how the configuration files are structured in both frameworks. Broadly speaking, configuration files are used for defining such things as database connection details, whether the site is in debug mode, the session drivers and so on.
Laravel stores relevant config files under the config directory in the root of the project and AdonisJS has also followed this model.
Both frameworks use the following files which Laravel developers will be familiar with:
app.js and it’s counterpart app.php
auth.js – auth.php
database.js – database.php
session.js – session.php
Laravel, being the more mature framework, also offers configuration options for a variety of other features out the box including queues, services and mail. Whilst some of these extra features may be available for AdonisJS, they will need to be installed separately. You can find a list of the official packages currently supported here:
We will also cover this in a little more detail later in the post.
Like Laravel, AdonisJS also adopts the use of .env files to populate variables within the configuration files based upon the environment the application is installed in. Engineers can then use a set of defaults in the config files, so if a .env file isn’t present it falls back to these. Here is in a example of the types of parameters you can set:
Kernel files and namespaces
In addition to the configuration files, some of the benefits of Laravel are the ability to extend the framework via middleware added to the kernel.php and also to create namespaces for classes. The types of middleware features that can be integrated through this kernel file include wrapping HTTP requests and responses.
AdonisJS has kept this feature with a kernel.js file available under the start directory.
In addition to the kernel file, we also see the use of namespaces in AdonisJS. The app directory we discussed previously has the feature of being autoloaded. This means that we do not have to rely on using relative paths to reference files, but can instead use namespaces as we do in Laravel. Here we can see a comparison between Laravel and AdonisJS in this regard:
const UserService = use('App/Services/User')
use App\Services\User as UserService;
Apart from some syntactic differences, the two frameworks are practically identical in their approach to this.
Next up we shall compare the core components of the MVC. AdonisJS has adopted the same approach as Laravel by placing the Models and Controllers nested under the app directory.
One subtle difference you will notice however is that the path under Laravel 5.6 is app/Http/Controllers whereas in AdonisJS it is app/Controllers/Http. In the later case this allows the separation of AdonisJS websocket controllers into their own app/Controllers/ws directory.
Laravel also stores the Middleware we mentioned previously under the Http directory, compared to AdonisJS where it sits at the root of the app directory. Where both frameworks agree on structure is that the Exception directories are also both placed at the root of app.
These differences are overall not difficult to overcome, and for Laravel developers, the feel of AdonisJS and its directory structure will be natural.
The final piece of the MVC acronym is of course the Views. In both frameworks these are achieved via templates stored in the resources/views directory.
One great feature about AdonisJS is the adoption of an ORM that is very similar to Eloquent. The underlying library that the Query Builder is built upon is Knex.js. It supports many of the typical methods you will be familiar with from writing queries in Eloquent.
How do we create and modify tables though?
AdonisJS has also adopted this approach and uses the Knex syntax which is once again similar to Laravel. One difference in nomenclature/convention however is that when a migration is generated, AdonisJS will automatically suffix schema to the filename and classname. Laravel on the other hand allows you to use the term table, which you will see in their documentation on migration generation.
Like Laravel, AdonisJS uses a routes file to plug Controllers into endpoints. The routes in AdonisJS can be found under the start directory as compared to Laravel where they are stored in the root folder of the project.
On comparing the two, apart from the slight differences in syntax we can see they look almost identical:
All the same concepts apply between both frameworks, with the ability to group endpoints and define the HTTP verbs accepted for the endpoint.
This can make porting an existing project from Laravel much easier as the Vue.js code can be repurposed for the AdonisJS version.
Command line tools
Laravel developers will of course be familiar with using artisan to run command line tasks such as kicking off migrations. This concept has also been ported over to AdonisJS with the adonis command. Here too you can run migrations and roll them back.
--help) flag gives you a list of all the supported features including creating controllers and migration stub files amongst others.
The adonis command is actually a wrapper for an underlying technology called Ace and proxies all the commands for your project. You can read about this in more depth here.
As a result of implementing this technology, developers can create their own custom commands, and AdonisJS provides a handy adonis command to do just this:
So as with artisan you can build the custom command line tools you need to support your development projects.
So what’s missing?
We’ve done a quick walk through of some of the similarities between the two frameworks. You are probably now wondering where they differ and what’s missing? We’ve given a quick overview of three of these below.
1 – No queues out of the box
That’s right, unlike Laravel, AdonisJS does not provide the wrappers for queues with the basic install. However, AdonisJS does provide a handy guide on how to wrap existing queuing packages such as bee-queue with service providers
2 – The Mail feature has to be installed separately.
Another great feature of Laravel is the Mail API built on-top of SwiftMailer coupled with drivers for Mailgun, SES and others. This comes as part of the standard Laravel install. However, with AdonisJS the mail feature needs to be installed separately using:
adonis install @adonisjs/mail
…followed by registering the provider in the app.js file. This isn’t a huge hassle, but perhaps AdonisJS will bundle this with the default install in future releases.
3 – The File System feature also has to be installed separately.
Like Laravel, AdonisJS provides a wrapper for underlying technologies (Flydrive) that allow interaction with remote and local filesystems. However, like the Mail feature this needs to be installed separately via adonis:
adonis install @adonisjs/drive
Once installed it can then be registered in the providers inside of the app.js file. Currently the File System functionality only supports Amazon S3 out of the box and of course the local file system.
Overall, the lack of features compared to Laravel is largely due to the maturity of the framework. However, as with Laravel as the project grows we should expect to see a great set of functionality supported out the box.
Hopefully this quick walkthrough has given you a good comparison between some of the features that AdonisJS shares with Laravel and where some areas are still a little behind.
Here is a quick recap of these features:
As you can see from this table, Adonis can do many of the key things that Laravel can.
If you are looking to migrate a system from Laravel to NodeJS, we would love to hear from you!