This library provides the imports-orchestrator library to control the order in which Angular components and modules are loaded. This can be useful when optimizing page performance in an Application.
const APP_IMPORTS_ORCHESTRATION = {
'first': 1,
'second': 2,
'third': 3,
};
export type AppImportsOrchestration = typeof APP_IMPORTS_ORCHESTRATION;
export const appConfig = {
providers: [
// ...
provideImportsOrchestration(
// specify the priority of your imports (queue works from low to high)
APP_IMPORTS_ORCHESTRATION,
// routes should be resolved as quickly as possible:
withSuspendWhileRouting(),
// automatically adjusts the number of concurrent imports depending on the client's connection:
withConcurrencyRelativeToDownlinkSpeed(4, 1)
),
],
};
import {AppImportsOrchestration} from "./app.config";
@Component({
selector: 'example',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ImportsOrchestratorDirective],
template: `
<ng-container
import="second"
[inputs]="{ text: headline }"
[outputs]="{ click: onClick }"
></ng-container>
<import
identifier="first"
[inputs]="{ text: description }"
[outputs]="{ click: onClick }"
></import>
`,
})
// Your dynamic imports can be added with this decorator
@Imports<AppImportsOrchestration>({
'first': importStandalone(
() => import('@some/thing')
),
'second': importNgModule(
() => import('@other/fancy-lib')
),
'third': importPromise(() =>
fetch('/assets/example.json').then((res) => res.json())
),
})
export class ExampleComponent {
@Input() headline = 'Some catchy title';
@Input() description = 'Elaborate description';
private readonly importService = inject(ImportService);
constructor() {
this.fetchExample();
}
public async fetchExample(): Promise<void> {
const item = this.importService.createQueueItem('third', NEVER);
// you can await the item here, but you don't have to
try {
const result = await this.importService.addItemToQueue(item);
console.log('result', result);
} catch (e) {
console.error(e);
}
}
}
- Standalone components with
importStandalone(() => import('path/to/esm')
- NgModules (with or without bootstrapped components), using
importNgModule(() => import('path/to/esm').then(m => m.SomeNgModule)
- Arbitrary promises (eg. fetch) via
importPromise(() => fetch('http://some.url/json').then(result => result.json)
withConcurrencyStatic(value: number)
(default)withConcurrencyRelativeToDownlinkSpeed(max: number = 4, min: number = 1)
withoutRouting()
(default, as some apps do not use routing),withSuspendWhileRouting(suspendForInitialNavigation = true)
, routes should be resolved as fast as possible, so this will cause the queue to suspend processing until routing is finished
withLogger(logger: Console, prefix: string = '[ImportsOrchestrator]')
by defaultConsole
is used
withTimeout(timeout: number = 10000)
Timeout applies to each item on the queue individually by default, 10000ms are applied
Please see apps/imports-orchestrator-example/src/app/app.component.ts
and apps/imports-orchestrator-example/src/app/home/home.component.ts
on how to use.
Warning: API is not stable. Everything is subject to change.
Run nx serve imports-orchestrator-example
to explore.
Run nx serve imports-orchestrator-example
for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.
✨ This workspace has been generated by Nx, a Smart, fast and extensible build system. ✨ Visit the Nx Documentation to learn more.