What does Booting an Application mean?

A typical LoopBack application is made up of many artifacts in different files,organized in different folders. Booting an Application means:

  • Discovering artifacts automatically based on a convention (a specific foldercontaining files with a given suffix)
  • Processing those artifacts (this usually means automatically binding them tothe Application’s Context)@loopback/boot provides a Bootstrapper that uses Booters to automaticallydiscover and bind artifacts, all packaged in an easy-to-use Mixin.

What is an artifact?

An artifact is any LoopBack construct usually defined in code as a Class.LoopBack constructs include Controllers, Repositories, Models, etc.

Usage

@loopback/cli

New projects generated using @loopback/cli or lb4 are automatically enabledto use @loopback/boot for booting the Application using the conventionsfollowed by the CLI.

Adding to existing project

See Using the BootMixin to add Boot to your Projectmanually.


The rest of this page describes the inner workings of @loopback/boot foradvanced use cases, manual usage or using @loopback/boot as a standalonepackage (with custom booters).

BootMixin

Boot functionality can be added to a LoopBack 4 Application by mixing it withthe BootMixinmixin.This mixin adds the BootComponent to your Application as well as conveniencemethods such as app.boot() and app.booters(). The Mixin also allowsComponents to set the property booters as an Array of Booters. They will bebound to the Application and called by the Bootstrapper.

Since this is a convention-based Bootstrapper, it is important to set aprojectRoot, as all other artifact paths will be resolved relative to thispath.

Tip: application.ts will likely be at the root of your project, so its pathcan be used to set the projectRoot by using the _dirname variable. (Seeexample below)_

Using the BootMixin

  1. import {BootMixin} from "@loopback/boot";
  2. class MyApplication extends BootMixin(Application) {
  3. constructor(options?: ApplicationConfig) {
  4. super(options);
  5. // Setting the projectRoot
  6. this.projectRoot = __dirname;
  7. // Set project conventions
  8. this.bootOptions: BootOptions = {
  9. controllers: {
  10. dirs: ['controllers'],
  11. extensions: ['.controller.js'],
  12. nested: true,
  13. }
  14. }
  15. }
  16. }

Now just call app.boot() from index.ts before starting your Applicationusing app.start().

app.boot()

A convenience method to retrieve the Bootstrapper instance bound to theApplication and calls its boot function. This should be called before anApplication’s start() method is called. This is an async function andshould be called with await.

  1. class MyApp extends BootMixin(Application) {}
  2. async main() {
  3. const app = new MyApp();
  4. app.projectRoot = __dirname;
  5. await app.boot();
  6. await app.start();
  7. }

app.booters()

A convenience method to manually bind Booters. You can pass any number ofBooter classes to this method and they will all be bound to the Applicationusing the prefix (booters.) and tag (booter) used by the Bootstrapper.

  1. // Binds MyCustomBooter to `booters.MyCustomBooter`
  2. // Binds AnotherCustomBooter to `booters.AnotherCustomBooter`
  3. // Both will have the `booter` tag set.
  4. app.booters(MyCustomBooter, AnotherCustomBooter);

BootComponent

This component is added to an Application by BootMixin if used. ThisComponent:

  • Provides a list of default booters as a property of the component
  • Binds the conventional Bootstrapper to the ApplicationIf using this as a standalone component without the BootMixin, you will needto bind the booters of a component manually.
  1. app.component(BootComponent);

Bootstrapper

A Class that acts as the “manager” for Booters. The Bootstrapper is designed tobe bound to an Application as a SINGLETON. The Bootstrapper class provides aboot() method. This method is responsible for getting all bound Booters andrunning their phases. A phase is a method on a Booter class.

Each boot() method call creates a new Context that sets the app context asits parent. This is done so each Context for boot gets a new instance ofbooters but the same context can be passed into boot so selective phasescan be run in different calls of boot.

The Bootstrapper can be configured to run specific booters or boot phases bypassing in BootExecOptions. This is experimental and subject to change.Hence, this functionality is not exposed when calling boot() viaBootMixin.

To use BootExecOptions, you must directly call bootstrapper.boot() insteadof app.boot(). You can pass in the BootExecOptions object with the followingproperties:

PropertyTypeDescription
bootersConstructor<Booter>[]Array of Booters to bind before running boot()
filter.bootersstring[]Names of Booter classes that should be run
filter.phasesstring[]Names of Booter phases to run

Example

  1. import {BootMixin, Booter, Binding, Bootstrapper} from '@loopback/boot';
  2. class MyApp extends BootMixin(Application) {}
  3. const app = new MyApp();
  4. app.projectRoot = __dirname;
  5. const bootstrapper: Bootstrapper = await this.get(
  6. BootBindings.BOOTSTRAPPER_KEY,
  7. );
  8. bootstrapper.boot({
  9. booters: [MyCustomBooter],
  10. filter: {
  11. booters: ['MyCustomBooter'],
  12. phases: ['configure', 'discover'], // Skip the `load` phase.
  13. },
  14. });

Booters

A Booter is a class that is responsible for booting an artifact. A Booter doesits work in phases which are called by the Bootstrapper. The following Bootersare a part of the @loopback/boot package and loaded automatically viaBootMixin.

Controller Booter

This Booter’s purpose is to discover Controller type Artifactsand to bind them to the Application’s Context.

You can configure the conventions used in your project for a Controller bypassing a controllers object on BootOptions property of your Application.The controllers object supports the following options:

OptionsTypeDefaultDescription
dirsstring | string[]['controllers']Paths relative to projectRoot to look in for Controller artifacts
extensionsstring | string[]['.controller.js']File extensions to match for Controller artifacts
nestedbooleantrueLook in nested directories in dirs for Controller artifacts
globstring A glob pattern string. This takes precendence over above 3 options (which are used to make a glob pattern).

Repository Booter

This Booter’s purpose is to discover Repository typeArtifacts and to bind them to the Application’s Context. The use of this Booterrequires RepositoryMixin from @loopback/repository to be mixed into yourApplication class.

You can configure the conventions used in your project for a Repository bypassing a repositories object on BootOptions property of your Application.The repositories object supports the following options:

OptionsTypeDefaultDescription
dirsstring | string[]['repositories']Paths relative to projectRoot to look in for Repository artifacts
extensionsstring | string[]['.repository.js']File extensions to match for Repository artifacts
nestedbooleantrueLook in nested directories in dirs for Repository artifacts
globstring A glob pattern string. This takes precendence over above 3 options (which are used to make a glob pattern).

DataSource Booter

This Booter’s purpose is to discover DataSource type Artifactsand to bind them to the Application’s Context. The use of this Booter requiresRepositoryMixin from @loopback/repository to be mixed into your Applicationclass.

You can configure the conventions used in your project for a DataSource bypassing a datasources object on BootOptions property of your Application.The datasources object support the following options:

OptionsTypeDefaultDescription
dirsstring | string[]['datasources']Paths relative to projectRoot to look in for DataSource artifacts
extensionsstring | string[]['.datasource.js']File extensions to match for DataSource artifacts
nestedbooleantrueLook in nested directories in dirs for DataSource artifacts
globstring A glob pattern string. This takes precendence over above 3 options (which are used to make a glob pattern).

Service Booter

Description

Discovers and binds remote service proxies or local service classes or providersusing app.service().

IMPORTANT: For a class to be recognized by ServiceBooter as a serviceprovider, it either has to be decorated with @bind or the class name must endwith Provider suffix and its prototype must have a value() method.

Options

The options for this can be passed via BootOptions when callingapp.boot(options: BootOptions).

The options for this are passed in a services object on BootOptions.

Available options on the services object on BootOptions are as follows:

OptionsTypeDefaultDescription
dirsstring | string[]['services']Paths relative to projectRoot to look in for Service artifacts
extensionsstring | string[]['.service.js']File extensions to match for Service artifacts
nestedbooleantrueLook in nested directories in dirs for Service artifacts
globstring A glob pattern string. This takes precedence over above 3 options (which are used to make a glob pattern).

Custom Booters

A custom Booter can be written as a Class that implements the Booterinterface. The Class must implement methods that corresponds to a phase name.The phases are called by the Bootstrapper in a pre-determined order (unlessoverridden by BootExecOptions). The next phase is only called once theprevious phase has been completed for all Booters.

Phases

configure

Used to configure the Booter with its default options.

discover

Used to discover the artifacts supported by the Booter based on convention.

load

Used to bind the discovered artifacts to the Application.