|
| 1 | +--- |
| 2 | +lang: en |
| 3 | +title: 'Booting an Application' |
| 4 | +keywords: LoopBack 4.0, LoopBack 4 |
| 5 | +tags: |
| 6 | +sidebar: lb4_sidebar |
| 7 | +permalink: /doc/en/lb4/Booting-an-Application.html |
| 8 | +summary: |
| 9 | +--- |
| 10 | + |
| 11 | +## What does Booting an Application mean? |
| 12 | + |
| 13 | +A typical LoopBack application is made up of many artifacts in different files, |
| 14 | +organized in different folders. **Booting an Application** means: |
| 15 | + |
| 16 | +* Discovering artifacts automatically based on a convention (a specific folder |
| 17 | + containing files with a given suffix) |
| 18 | +* Processing those artifacts (this usually means automatically binding them to the Application's Context) |
| 19 | + |
| 20 | +`@loopback/boot` provides a Bootstrapper that uses Booters to automatically |
| 21 | +discover and bind artifacts, all packaged in an easy-to-use Mixin. |
| 22 | + |
| 23 | +### What is an artifact? |
| 24 | + |
| 25 | +An artifact is any LoopBack construct usually defined in code as a Class. LoopBack |
| 26 | +constructs include Controllers, Repositories, Models, etc. |
| 27 | + |
| 28 | +## Usage |
| 29 | + |
| 30 | +### @loopback/cli |
| 31 | + |
| 32 | +New projects generated using `@loopback/cli` or `lb4` are automatically enabled |
| 33 | +to use `@loopback/boot` for booting the Application using the conventions |
| 34 | +followed by the CLI. |
| 35 | + |
| 36 | +### Adding to existing project |
| 37 | + |
| 38 | +See [Using the BootMixin](#using-the-bootmixin) to add Boot to your Project manually. |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +The rest of this page describes the inner workings of `@loopback/boot` for advanced use |
| 43 | +cases, manual usage or using `@loopback/boot` as a standalone package (with custom |
| 44 | +booters). |
| 45 | + |
| 46 | +## BootMixin |
| 47 | + |
| 48 | +Boot functionality can be added to a LoopBack 4 Application by mixing it with the |
| 49 | +`BootMixin`. The Mixin adds the `BootComponent` to your Application as well as |
| 50 | +convenience methods such as `app.boot()` and `app.booters()`. The Mixin also allows |
| 51 | +Components to set the property `booters` as an Array of `Booters`. They will be bound |
| 52 | +to the Application and called by the `Bootstrapper`. |
| 53 | + |
| 54 | +Since this is a convention-based Bootstrapper, it is important to set a `projectRoot`, |
| 55 | +as all other artifact paths will be resolved relative to this path. |
| 56 | + |
| 57 | +_Tip_: `application.ts` will likely be at the root of your project, so its path can be |
| 58 | +used to set the `projectRoot` by using the `__dirname` variable. _(See example below)_ |
| 59 | + |
| 60 | +### Using the BootMixin |
| 61 | + |
| 62 | +`Booter` and `Binding` types must be imported alongside `BootMixin` to allow TypeScript |
| 63 | +to infer types and avoid errors. _If using `tslint` with the `no-unused-variable` rule, |
| 64 | +you can disable it for the import line by adding `// tslint:disable-next-line:no-unused-variable` |
| 65 | +above the import statement_. |
| 66 | + |
| 67 | +```ts |
| 68 | +import {BootMixin, Booter, Binding} from "@loopback/boot"; |
| 69 | + |
| 70 | +class MyApplication extends BootMixin(Application) { |
| 71 | + constructor(options?: ApplicationConfig) { |
| 72 | + super(options); |
| 73 | + // Setting the projectRoot |
| 74 | + this.projectRoot = __dirname; |
| 75 | + // Set project conventions |
| 76 | + this.bootOptions: BootOptions = { |
| 77 | + controllers: { |
| 78 | + dirs: ['controllers'], |
| 79 | + extensions: ['.controller.js'], |
| 80 | + nested: true, |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | +} |
| 85 | +``` |
| 86 | + |
| 87 | +Now just call `app.boot()` from `index.ts` before starting your Application using `app.start()`. |
| 88 | + |
| 89 | +#### app.boot() |
| 90 | + |
| 91 | +A convenience method to retrieve the `Bootstrapper` instance bound to the |
| 92 | +Application and calls its `boot` function. This should be called before an |
| 93 | +Application's `start()` method is called. _This is an `async` function and should |
| 94 | +be called with `await`._ |
| 95 | + |
| 96 | +```ts |
| 97 | +class MyApp extends BootMixin(Application) {} |
| 98 | + |
| 99 | +async main() { |
| 100 | + const app = new MyApp(); |
| 101 | + app.projectRoot = __dirname; |
| 102 | + await app.boot(); |
| 103 | + await app.start(); |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +#### app.booters() |
| 108 | + |
| 109 | +A convenience method to manually bind `Booters`. You can pass any number of `Booter` |
| 110 | +classes to this method and they will all be bound to the Application using the |
| 111 | +prefix (`booters.`) and tag (`booter`) used by the `Bootstrapper`. |
| 112 | + |
| 113 | +```ts |
| 114 | +// Binds MyCustomBooter to `booters.MyCustomBooter` |
| 115 | +// Binds AnotherCustomBooter to `booters.AnotherCustomBooter` |
| 116 | +// Both will have the `booter` tag set. |
| 117 | +app.booters(MyCustomBooter, AnotherCustomBooter); |
| 118 | +``` |
| 119 | + |
| 120 | +## BootComponent |
| 121 | + |
| 122 | +This component is added to an Application by `BootMixin` if used. This Component: |
| 123 | + |
| 124 | +* Provides a list of default `booters` as a property of the component |
| 125 | +* Binds the conventional Bootstrapper to the Application |
| 126 | + |
| 127 | +_If using this as a standalone component without the `BootMixin`, you will need to |
| 128 | +bind the `booters` of a component manually._ |
| 129 | + |
| 130 | +```ts |
| 131 | +app.component(BootComponent); |
| 132 | +``` |
| 133 | + |
| 134 | +## Bootstrapper |
| 135 | + |
| 136 | +A Class that acts as the "manager" for Booters. The Bootstrapper is designed to be |
| 137 | +bound to an Application as a `SINGLETON`. The Bootstrapper class provides a `boot()` |
| 138 | +method. This method is responsible for getting all bound `Booters` and running |
| 139 | +their `phases`. A `phase` is a method on a `Booter` class. |
| 140 | + |
| 141 | +Each `boot()` method call creates a new `Context` that sets the `app` context |
| 142 | +as its parent. This is done so each `Context` for `boot` gets a new instance of |
| 143 | +`booters` but the same context can be passed into `boot` so selective `phases` can be |
| 144 | +run in different calls of `boot`. |
| 145 | + |
| 146 | +The Bootstrapper can be configured to run specific booters or boot phases |
| 147 | +by passing in `BootExecOptions`. **This is experimental and subject to change. Hence, |
| 148 | +this functionality is not exposed when calling `boot()` via `BootMixin`**. |
| 149 | + |
| 150 | +To use `BootExecOptions`, you must directly call `bootstrapper.boot()` instead of `app.boot()`. |
| 151 | +You can pass in the `BootExecOptions` object with the following properties: |
| 152 | + |
| 153 | +| Property | Type | Description | |
| 154 | +| ---------------- | ----------------------- | ------------------------------------------------ | |
| 155 | +| `booters` | `Constructor<Booter>[]` | Array of Booters to bind before running `boot()` | |
| 156 | +| `filter.booters` | `string[]` | Names of Booter classes that should be run | |
| 157 | +| `filter.phases` | `string[]` | Names of Booter phases to run | |
| 158 | + |
| 159 | +### Example |
| 160 | + |
| 161 | +```ts |
| 162 | +import { BootMixin, Booter, Binding, Bootstrapper } from "@loopback/boot"; |
| 163 | + |
| 164 | +class MyApp extends BootMixin(Application) {} |
| 165 | +const app = new MyApp(); |
| 166 | +app.projectRoot = __dirname; |
| 167 | + |
| 168 | +const bootstrapper: Bootstrapper = await this.get( |
| 169 | + BootBindings.BOOTSTRAPPER_KEY |
| 170 | +); |
| 171 | +bootstrapper.boot({ |
| 172 | + booters: [MyCustomBooter], |
| 173 | + filter: { |
| 174 | + booters: ["MyCustomBooter"], |
| 175 | + phases: ["configure", "discover"] // Skip the `load` phase. |
| 176 | + } |
| 177 | +}); |
| 178 | +``` |
| 179 | + |
| 180 | +## Booters |
| 181 | + |
| 182 | +A Booter is a class that is responsible for booting an artifact. A Booter does its |
| 183 | +work in `phases` which are called by the Bootstrapper. The following Booters are |
| 184 | +a part of the `@loopback/boot` package and loaded automatically via `BootMixin`. |
| 185 | + |
| 186 | +### Controller Booter |
| 187 | + |
| 188 | +This Booter's purpose is to discover [Controller](Controllers.md) type Artifacts and to bind |
| 189 | +them to the Application's Context. |
| 190 | + |
| 191 | +You can configure the conventions used in your |
| 192 | +project for a Controller by passing a `controllers` object on `BootOptions` property |
| 193 | +of your Application. The `controllers` object supports the following options: |
| 194 | + |
| 195 | +| Options | Type | Default | Description | |
| 196 | +| ------------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- | |
| 197 | +| `dirs` | `string \| string[]` | `['controllers']` | Paths relative to projectRoot to look in for Controller artifacts | |
| 198 | +| `extensions` | `string \| string[]` | `['.controller.js']` | File extensions to match for Controller artifacts | |
| 199 | +| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for Controller artifacts | |
| 200 | +| `glob` | `string` | | A `glob` pattern string. This takes precendence over above 3 options (which are used to make a glob pattern). | |
| 201 | + |
| 202 | +### Repository Booter |
| 203 | + |
| 204 | +This Booter's purpose is to discover [Repository](Repositories.md) type Artifacts and to bind |
| 205 | +them to the Application's Context. The use of this Booter requires `RepositoryMixin` |
| 206 | +from `@loopback/repository` to be mixed into your Application class. |
| 207 | + |
| 208 | +You can configure the conventions used in your |
| 209 | +project for a Repository by passing a `repositories` object on `BootOptions` property |
| 210 | +of your Application. The `repositories` object supports the following options: |
| 211 | + |
| 212 | +| Options | Type | Default | Description | |
| 213 | +| ------------ | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- | |
| 214 | +| `dirs` | `string \| string[]` | `['repositories']` | Paths relative to projectRoot to look in for Repository artifacts | |
| 215 | +| `extensions` | `string \| string[]` | `['.repository.js']` | File extensions to match for Repository artifacts | |
| 216 | +| `nested` | `boolean` | `true` | Look in nested directories in `dirs` for Repository artifacts | |
| 217 | +| `glob` | `string` | | A `glob` pattern string. This takes precendence over above 3 options (which are used to make a glob pattern). | |
| 218 | + |
| 219 | +### Custom Booters |
| 220 | + |
| 221 | +A custom Booter can be written as a Class that implements the `Booter` interface. The Class |
| 222 | +must implement methods that corresponds to a `phase` name. The `phases` are called |
| 223 | +by the Bootstrapper in a pre-determined order (unless overridden by `BootExecOptions`). |
| 224 | +The next phase is only called once the previous phase has been completed for all Booters. |
| 225 | + |
| 226 | +#### Phases |
| 227 | + |
| 228 | +**configure** |
| 229 | + |
| 230 | +Used to configure the `Booter` with its default options. |
| 231 | + |
| 232 | +**discover** |
| 233 | + |
| 234 | +Used to discover the artifacts supported by the `Booter` based on convention. |
| 235 | + |
| 236 | +**load** |
| 237 | + |
| 238 | +Used to bind the discovered artifacts to the Application. |
0 commit comments