How to Lazy Load Scripts and Styles

    You do not have to provide the LazyLoadService at module or component level, because it is already provided in root. You can inject and start using it immediately in your components, directives, or services.

    You can use the load method of LazyLoadService to create a <script> or <link> element in the DOM at the desired position and force the browser to download the target resource.

    The first parameter of load method expects a LoadingStrategy. If you pass a ScriptLoadingStrategy instance, the LazyLoadService will create a <script> element with given src and place it in the designated DOM position.

    1. import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core';
    2. @Component({
    3. template: `
    4. <some-component *ngIf="libraryLoaded$ | async"></some-component>
    5. `
    6. })
    7. class DemoComponent {
    8. libraryLoaded$ = this.lazyLoad.load(
    9. LOADING_STRATEGY.AppendAnonymousScriptToHead('/assets/some-library.js'),
    10. constructor(private lazyLoadService: LazyLoadService) {}
    11. }

    The load method returns an observable to which you can subscibe in your component or with an pipe. In the example above, the NgIf directive will render <some-component> only if the script gets successfully loaded or is already loaded before.

    If you pass a StyleLoadingStrategy instance as the first parameter of load method, the LazyLoadService will create a <link> element with given href and place it in the designated DOM position.

    The load method returns an observable to which you can subscibe in your component or with an AsyncPipe. In the example above, the NgIf directive will render <some-component> only if the style gets successfully loaded or is already loaded before.

    Please refer to LoadingStrategy to see all available loading strategies and how you can build your own loading strategy.

    You have quite a bit of freedom to define how your lazy load will work. Here is an example:

    1. const domStrategy = DOM_STRATEGY.PrependToHead();
    2. const crossOriginStrategy = CROSS_ORIGIN_STRATEGY.Anonymous(
    3. 'sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh',
    4. );
    5. const loadingStrategy = new StyleLoadingStrategy(
    6. 'https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css',
    7. domStrategy,
    8. crossOriginStrategy,
    9. );
    10. this.lazyLoad.load(loadingStrategy, 1, 2000);

    A common usecase is loading multiple scripts and/or styles before using a feature:

    RxJS forkJoin will load all scripts and styles in parallel and emit only when all of them are loaded. So, when <some-component> is placed, all required dependencies will be available.

    Another frequent usecase is loading dependent scripts in order:

    1. import { LazyLoadService, LOADING_STRATEGY } from '@abp/ng.core';
    2. import { concat } from 'rxjs';
    3. template: `
    4. <some-component *ngIf="scriptsLoaded$ | async"></some-component>
    5. `
    6. })
    7. class DemoComponent {
    8. scriptsLoaded$ = concat(
    9. this.lazyLoad.load(
    10. LOADING_STRATEGY.PrependAnonymousScriptToHead('/assets/library.js'),
    11. ),
    12. this.lazyLoad.load(
    13. LOADING_STRATEGY.AppendAnonymousScriptToHead('/assets/script-that-requires-library.js'),
    14. ),
    15. );
    16. constructor(private lazyLoadService: LazyLoadService) {}
    17. }

    In this example, the second file needs the first one to be loaded beforehand. RxJS concat function will let you load all scripts one-by-one in the given order and emit only when all of them are loaded.

    1. load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable<Event>
    • strategy parameter is the primary focus here and is explained above.
    • defines how many times the loading will be tried again before fail (default: 2).