NightBuster
@NightBuster

Как организовать ленивую загрузку внешних скриптов в Angular 2+ (CLI)?

Возникла необходимость подгрузки большой библиотеки для генерации pdf на фронтенд (over 1Mb).
Сама библиотека для nodejs, но есть собранная версия для браузера (browserify)
Если с модулями и lazy все понятно, то офф-документация говорит грузить такие скрипты в блоке scripts конфига .angular-cli, при этом они грузятся в scripts bundle
Хочется загружать эту библиотеку только когда нужно, и по завершении использования выгружать ее из памяти.
Есть ли какое то элегантное решение задачи?

P.S. С советами о генерации на стороне сервера, пожалуйста мимо, задача именно генерировать на клиенте.
  • Вопрос задан
  • 244 просмотра
Решения вопроса 1
NightBuster
@NightBuster Автор вопроса
Решил так:

Написал сервис-загрузчик для скриптов:

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;
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы