Playing Next Lesson In
seconds

Let's Learn AdonisJS 7 #1.3

Lifecycle & Project Structure Tour

In This Lesson

Explore the AdonisJS project structure, folder organization, and application lifecycle. Understand the key directories and their purposes.

Created by
@tomgobich
Published

Our application starts in the bin directory. It contains an entry point file for the three different types of environments our server can start within.

  1. Console, for Ace CLI commands

  2. Server, for our HTTP server

  3. Test, for testing

Unless you're doing something advanced, you won't need to give much thought to this directory. Once here, we enter the boot phase.

Boot Phase

The boot phase is where things get registered within our application, and it's Inversion of Control (IoC) Container.

adonisrc.ts

As part of this, our adonisrc.ts file is read. This file is within the root of our project and is a primary point where things get registered for inclusion within our project. It contains things like:

  • Assembler Hooks - hooks run by the assembler (like generated files)

  • Commands from packages

  • Service Providers - registers providers to hook into the lifecycle

  • Preload files - registers files to be run during the start phase

  • Test suites - registers suites or types of tests used in our application

  • Meta files - registers files to be copied to production builds

Config Files

Next, the configuration files within our application will be included. These can be found in the config folder. There's an app config for general settings for our HTTP server, auth for authentication, database for database configuration and so on.

Service Providers

Registered Service Providers are also read here. Service Providers are classes containing lifecycle hooks, allowing them to perform code at these various stages of our application. Below is an example of an empty Service Provider class.

import type { ApplicationService } from '@adonisjs/core/types'

export default class ExampleProvider {
  constructor(protected app: ApplicationService) {}

  /**
   * Register bindings to the container
   */
  register() {}

  /**
   * The container bindings have booted
   */
  async boot() {}

  /**
   * The application has been booted
   */
  async start() {}

  /**
   * The process has been started
   */
  async ready() {}

  /**
   * Preparing to shutdown the app
   */
  async shutdown() {}
}
Copied!

The boot phase will run the register then boot methods in the order defined within the adonisrc.ts providers array. We'll touch on these as part of the last module in this series, but they can be found within the providers folder. This folder isn't included in our project structure until we create a provider.

Start Phase

The start phase is where things begin to get initialized. This is where the start directory shines, as its general purpose is to hold files that should be preloaded as part of the start process, like our route definitions, even listeners, and middleware registrations.

By default, we're started with three files here:

  • env.ts holds environment variable type definitions

  • kernel.ts is where our middleware is registered

  • routes.ts is where our routes are defined

Files from this directory that we want to run need to be explicitly included within the preloads array in our adonisrc.ts file. Note, these files are imported in parallel and may not execute in the order defined.

// adonisrc.ts
export default defineConfig({
	// ...
	
  /*
  |--------------------------------------------------------------------------
  | Preloads
  |--------------------------------------------------------------------------
  |
  | List of modules to import before starting the application.
  |
  */
  preloads: [
    () => import('#start/routes'),
    () => import('#start/kernel'),
    () => import('#start/globals'),
  ],

	// ...
})
Copied!

Additionally, during this phase the start then ready methods within Service Providers are also run.

Ready

Once the start phase is done, our server is ready to receive requests! This is where our application's domain logic comes into play.

App

The app directory holds our domain logic, like:

  • Controllers for handling route requests

  • Exceptions for handling application exceptions

  • Middleware for running logic between requests or responses

  • Models for integrating with our database

  • Validators for ensuring data validity before its reception

More can and will get added to this directory as we continue building an application as well.

Resources

When we server render views from our route handlers or controllers, those views and their assets get defined within our resources directory. When we opened http://localhost:3333 in our browser, the HTML page we ultimately saw is defined within here.

Ancillary Directories

That leaves the directories and files not specific to our dev server's lifecycle.

  • tests/ holds our test specifications and bootstrapping logic

  • database/ holds migrations, factories, and seeders used to shape our database and its initial data.

  • .adonisjs/ holds files generated by our server for type-safety and shouldn't be altered directly.

  • node_modules/ is where our project's dependencies are held

  • .env holds our environment variables

  • ace.js is a JavaScript entrypoint for the Ace CLI that imports the bin entrypoint

  • vite.config.js holds our Vite configuration for resourceful assets

  • tsconfig.json holds TypeScript's configuration

  • eslint.config.js holds ESLint's configuration

  • package.json holds NPM scripts and dependencies needed for our application, among other things

  • package-lock.json holds locked-in dependency versions so your whole team stays on the same versions.

  • .editorconfig is a config to hold presets for our text editor

  • .gitignore will inform Git to ignore certain files so they're excluded from our source control

  • .prettierignore tells Prettier to ignore certain files from its formatting

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!