We got up and running with a new application in the previous post. In this post, lets will take a step ahead and learn about some of the key concepts of AdonisJS.
I think it is very important to know about your tools before you starting using them. So let's spend another post without writing any code.
Ace commands
In this last post, we start the development server by running the node ace serve --watch
command, so let's start by breaking it down
-
node
is the node binary installed on your computer. -
ace
is a Javascript file in the root of your project. We removed the.js
extension, coz it is easier to typenode ace
overnode ace.js
- After the
ace
keyword is the command name and the arguments/flags required by the command.
Why the hell did not create a command-line binary that can be installed globally?
You might be thinking, why there isn't a command-line binary that can be installed globally and then use it as follows
adonis serve --watch
adonis make:controller <Name>
# and so on
The answer is, you cannot have project-specific commands with a global binary and a backend server usually needs project-specific commands. For example:
- A command to run queue workers
- A command to migrate the database
- Or maybe if you play fancy, then command to set up the project by creating an admin user and seeding data.
AdonisJS is not the first one to do this. Django has manage.py
file. Laravel has an artisan
file. However, when looking at the Node.js landscape, the concept feels a bit alien, hence requires explanation.
Directory structure
The default project structure of AdonisJS contains a bunch of files and folders by default. You may get overwhelmed at first by looking at the directory structure, especially when you are new to the framework. So, let's go ahead and talk about the important files and folders.
The .adonisrc.json
file
The .adonisrc.json
is one of the most important files as it is responsible for configuring your project and workspace.
Even though the file contains the bare minimum config by default. It allows overriding almost every convention used by the framework.
Run the following command to see the complete set of available options and their pre-configured defaults.
node ace dump:rcfile
About Fx
fx is a commandline utility to make the JSON output interactive
The server.ts
file
The server.ts
file is the entry point of your HTTP server. Running this file directly will boot your application and then starts the HTTP server.
This is a file you will run on your production server after it gets compiled to Javascript.
The app
directory
The app
directory contains most of your application code. HTTP controllers, middleware, models, services, and much more live inside this folder.
The config
directory
The config
directory is dedicated to storing all the configuration required by your app. By default, we create a handful of well-documented configuration files that are used by the framework core and first-party packages.
As your application will grow, you can also use this directory to store additional configuration files.
The start
directory
The start
directory contains all the files that you want to load only once during the application boot phase. We also call them preloaded files.
There is no technical limitation or hard coded rule that files inside this directory will be loaded only once. But more of a convention we follow to communicate a clear intent.
The resources
directory
The resources
directory is dedicated to storing edge templates inside a subdirectory called views
.
It is also recommended to use this directory also for storing un-compiled frontend assets like SASS files or frontend JavaScript. After compiling the frontend assets, they must be moved to the public
directory, since the resources
directory is not exposed to the internet.
The public
directory
The public
directory is exposed to the internet and all the files can be accessed by their path.
Given the following files inside the public
folder
public
├── app.js
├── logo.png
└── style.css
You can access them as
http://localhost:3333/app.js
http://localhost:3333/logo.png
http://localhost:3333/style.css
The database
directory
AdonisJS recommends storing the database schema migrations, seeders and factories inside the database directory.
We keep them outside of the app
directory because they are usually not part of the runtime code and get executed as a separate step during development or pre-deployment.
Typescript first
AdonisJS is a Typescript first framework. Beyond using it as a marketing term, we have invested a lot in building first-class primitives for a better typescript experience. In a nutshell, it includes
- First-class support for running Typescript source directly without compiling during development.
- Inbuilt command
node ace build
to create a standalonebuild
folder that can be deployed to the production server. - Support for static types for environment variables.
- Data validator that extracts static types after performing the runtime validations.
- Application-aware REPL that can compile and run the typescript code directly.
If you find value in adopting Typescript, then you can also bet on AdonisJS, as we are always looking for ways to fully embrace typescript.
Fully featured, not full-stack
AdonisJS is a fully featured and not a full-stack framework. The term full-stack is generally used when someone or something is equipped with both the web frontend and the backend.
AdonisJS has zero opinions on how you create your frontend.
- Want to server render HTML? We got your back with a pretty decent template engine.
- Want to use React, Vue, or Svelte? Use AdonisJS to create a JSON API and then develop your frontend as an independent app consuming the API
- Want to develop a Mobile app? Again, consume the same API and build a native mobile app
A lot of us think that if a framework is not full-stack, then it is a micro-framework. For god sake, there are a gazillion things that we do and should do on the backend. For example:
- Managing the data layer wisely. It includes sanitizing data, hashing/encrypting values with secret keys, and a much more
- User authentication and authorization
- Sending emails
- Queue jobs
- Validations
- Managing file uploads
- Interacting with 3rd party APIs. No, you cannot connect with 3rd party APIs securely from your frontend app.
- Payments & Subscriptions
A fully-featured framework like AdonisJS makes all this easy.
Top comments (7)
User authentication and authorization - For the authorization we have to wait because I was looking for a package for a couple of days, and I found nothing. I hope you upgrade adonis-guard package soon. That’s the only one package that I missed in the framework. Good job anyway.
make, rake, etc?
What am I not understanding?
They are tasks runner and not command line apps that ships with their own set of commands. Plus there are many other subtle things. For example:
The task code itself doesn't rely on (or import) anything from rake itself. Whereas with ace commands, your very first import is a
BaseCommand
from ace itselfSo the rails command is a task runner too?
guides.rubyonrails.org/command_lin...
None of those commands require ruby be called directly on the command line. What is ace doing that I'm missing?
Your comments feels like "lets see if I can begin a fight". I am more than happy, if you can suggest an alternative way to have project specific commands by installing a global binary.
Once you suggest an implementation. We both can together go through the merits and de-merits of your implementation and mine and happy to choose yours if it stands out :)
You wrote in bold text "you cannot have project-specific commands with a global binary".
In other words: it is impossible to do this
Being a rails developer I'd been running the "rails" command for years so I was just wondering why this statement was so definitive and I was wondering if ace was doing something rails can't.
Being a developer in general I was wondering why a global node script couldn't just do a cwd and go from there.
Thanks for sharing so detailed articles. Looking forward for more of these!