N
N
NightBuster2018-02-21 09:14:52
JavaScript
NightBuster, 2018-02-21 09:14:52

How to organize lazy loading of external scripts in Angular 2+ (CLI)?

There was a need to load a large library to generate pdf on the frontend (over 1Mb).
The library itself is for nodejs, but there is a compiled version for the browser (browserify)
If everything is clear with modules and lazy, then the off-documentation says to load such scripts in the scripts block of the .angular-cli config, while they are loaded into the scripts bundle
I want to load this library only when needed, and unload it from memory when finished.
Is there any elegant solution to the problem?
PS With advice about server-side generation, please pass by, the task is to generate on the client.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
NightBuster, 2018-02-22
@NightBuster

I decided this way: I
wrote a service loader for scripts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';

@Injectable()
export class ScriptLoaderService {

  private scripts: ScriptModel [] = [];

  public load(script: ScriptModel): Observable<ScriptModel> {
    return new Observable<ScriptModel>((observer: Observer<ScriptModel>) => {
      const existingScript = this.scripts.find(s => s.name === script.name);

      // Complete if already loaded
      if (existingScript && existingScript.loaded) {
        observer.next(existingScript);
        observer.complete();
      } else {
        // Add the script
        this.scripts = [...this.scripts, script];

        // Load the script
        const scriptElement = document.createElement('script');
        scriptElement.type = 'text/javascript';
        scriptElement.src = script.src;

        scriptElement.onload = () => {
          script.loaded = true;
          observer.next(script);
          observer.complete();
        };

        scriptElement.onerror = (error: any) => {
          observer.error('Couldn\'t load script ' + script.src);
        };

        document.getElementsByTagName('body')[0].appendChild(scriptElement);
      }
    });
  }

}

export interface ScriptModel {
  name: string;
  src: string;
  loaded: boolean;
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question