ngx-fastboot is a dynamic configuration loader for Angular applications. It optimizes the startup performance by loading configurations in a separate chunk during compilation.
Modern web applications often require a multitude of providers, which can increase the initial bundle size and slow down application startup. Splitting code into multiple chunks helps mitigate these issues by:
- Reducing Initial Bundle Size: By moving configuration-related code into separate chunks, the initial bundle size is minimized, leading to faster load times and improved performance.
- Improving Load Performance: Smaller initial bundles load quicker, especially over slower network connections, enhancing the user experience.
- Mitigating Compilation Warnings: Angular may generate warnings if the initial bundle size exceeds recommended limits. ngx-fastboot helps distribute the load, reducing the likelihood of these warnings.
- Dynamic Configuration Loading: Load and resolve Angular providers dynamically.
- Performance Optimization: Improve application startup performance by offloading configuration to a separate chunk.
- Seamless Integration: Easy integration with existing Angular projects.
- Support for Lazy Configurations: Load Angular Providers lazily for better performance.
with npm:
npm install ngx-fastboot
with pnpm:
pnpm add ngx-fastboot
with yarn:
yarn add ngx-fastboot
To use ngx-fastboot, import the fast
function and call it with your Angular application's bootstrapApplication
function, root component, and configuration options.
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import provideMyDefaultExportFeatures from './default-export-features.config';
import { provideMyOtherFeatures } from './my-other-features.config';
import { fast } from 'ngx-fastboot';
bootstrapApplication(AppComponent, {
providers: [
MyProvider,
provideMyDefaultExportFeatures,
provideMyOtherFeatures,
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
MyProvider,
() => import('./default-export-features.config'), // default export config
() => import('./my-other-features.config').then((m) => m.provideMyOtherFeatures),
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
ngx-fastboot
provides great flexibility in how providers are loaded. Each element of the providers
field can be either a single provider or an array of providers, depending on the needs of your application.
You can specify these providers in three main ways:
-
Static import: The traditional method used during the application's bootstrap, where providers are imported and directly included at configuration time. This approach is simple but can increase the initial bundle size.
-
Dynamic Named Import: To reduce the bundle size, you can load providers dynamically using a named import. In this way, providers are only loaded when they are actually needed.
-
Dynamic Default Import: Similar to named import, but loads the provider or a group of providers using the default export of the module. This is useful when a module exports a single provider or an array of providers as a default value.
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { MyProvider } from 'providers/my-provider';
import { OtherProvider } from 'providers/other-provider';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
MyProvider,
OtherProvider,
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
providers/my-provider.ts
export const MyProvider: Provider = ....;
providers/other-provider.ts
export const OtherProvider = [
provideHttpClient(),
ReactiveFormsModule,
provideZoneChangeDetection({ eventCoalescing: true }),
] satisfies Array<Provider | EnvironmentProviders>;
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
() => import('providers/my-provider').then((m) => m.MyProvider), // single
() => import('providers/other-provider').then((m) => m.OtherProvider), // array
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
providers/my-provider.ts
const MyProvider: Provider = ....;
export default MyProvider;
providers/other-provider.ts
export default [
provideHttpClient(),
ReactiveFormsModule,
provideZoneChangeDetection({ eventCoalescing: true }),
] satisfies Array<Provider | EnvironmentProviders>;
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
() => import('providers/my-provider'), // single
() => import('providers/other-provider'), // array
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { MyStaticImportedProvider } from './providers/my-static-imported-provider';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
MyStaticImportedProvider,
() => import('providers/my-provider').then((m) => m.MyProvider),
() => import('providers/other-provider'),
]
}).then(appRef => {
console.log('App is bootstrapped');
}).catch(error => {
console.error('Error bootstrapping the app', error);
});
Similar to providers, you can manage the root component of the application both statically and dynamically. Dynamically loading the root component can help reduce the initial bundle size.
The classic method to bootstrap the root component involves a static import:
fast(bootstrapApplication, AppComponent, {
providers: [...]
});
To optimize bundle size, the root component can be loaded dynamically with a named import:
fast(
bootstrapApplication,
() => import('./app-component').then((m) => m.AppComponent), {
providers: [...]
});
Alternatively, you can use a dynamic default import if the root component is exported as the default from the module:
fast(
bootstrapApplication,
() => import('./app-component'), {
providers: [...]
});
This example shows how to integrate Sentry with ngx-fastboot for error monitoring and performance tracing in your Angular application.
src/app/configs/sentry.config.ts
import { APP_INITIALIZER, EnvironmentProviders, ErrorHandler, Provider } from '@angular/core';
import { Router } from '@angular/router';
import {
createErrorHandler,
init,
TraceService,
} from '@sentry/angular-ivy';
export default [
{
provide: ErrorHandler,
useValue: createErrorHandler({
showDialog: false,
logErrors: true,
}),
},
{
provide: TraceService,
deps: [Router],
},
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [TraceService],
multi: true,
},
] satisfies Array<Provider | EnvironmentProviders>;
src/app/configs/sentry.init.ts
import {
browserTracingIntegration,
init,
replayIntegration,
} from '@sentry/angular-ivy';
export function initSentryConfig() {
init({
dsn: '<your-dsn>',
integrations: [browserTracingIntegration(), replayIntegration()],
...etc
});
console.info('Sentry initialized.');
}
src/main.ts
import { AppComponent } from './app.component';
import { bootstrapApplication } from '@angular/platform-browser';
import { fast } from 'ngx-fastboot';
fast(bootstrapApplication, AppComponent, {
providers: [
() => import('./app/configs/sentry.config'),
],
})
.then(() => import('./app/configs/sentry.init')
.then((init) => init.initSentryConfig()))
.catch(error => {
console.error('Error bootstrapping the app', error);
});
Dynamically loads the specified providers in the configuration and bootstraps an Angular application.
bootstrap
: The Angular application's bootstrap function (typicallybootstrapApplication
).rootComponent
: The root component of the application, which should be of typeFastComponent
.options
: (Optional) The application configuration, including the providers to be loaded. It should conform to theFastApplicationConfig
type. Providers can beProvider
,EnvironmentProviders
, or lazy modules that return these providers.
A Promise
that resolves to an ApplicationRef
instance of the bootstrapped application. The bootstrap method is called with the root component and the updated configuration with the resolved providers.
export type FastApplicationConfig = ApplicationConfig & {
providers: Array<FastProvider>
}
export type FastProvider = Provider | EnvironmentProviders | LazyModule<Provider | EnvironmentProviders | Array<Provider | EnvironmentProviders>>;
export type LazyModule<T> = () => Promise<T | { default: T }>;
export type AngularProvider = Provider | EnvironmentProviders;
export type FastComponent = Type<unknown> | LazyComponent;
export type LazyComponent = LazyModule<Type<unknown>>;
We welcome contributions! Please read our Contributing Guide to learn how you can help improve ngx-fastboot.
ngx-fastboot is licensed under the MIT License. See the LICENSE file for more information.
angular, angular performance, dynamic configuration, lazy loading, angular bootstrap, ngx-fastboot
For any questions or feedback, please open an issue.