Оптимизация производительности вашего приложения с помощью функций Angular и не только

Оптимизация производительности вашего приложения с помощью функций Angular и не только

От автора: сегодня мы поговорим о том, как оптимизировать производительность приложения на Angular с помощью ленивой загрузки, функций TrackBy, OnPush, отключения обнаружения изменений и других способов.

Использование OnPush

По умолчанию Angular запускает механизм определения изменений на всех компонентах каждый раз при изменении чего-либо в приложении – от события click до получения данных по ajax-запросу. (пользовательские события, таймеры, xhr, promise’ы и т.д.)

Представьте, например, что у нас есть компонент select.

@Component({
  selector: 'my-select',
  template: `
  <select (change)="change()">
 <option *ngFor="let option of options" 
 [value]="option.id">
 {{option.name}}
 </option>
  </select>
  `
})
export class MySelectComponent {
  @Input() options = [];

  change() {}
}

Мы собираемся передать массив навыков в компонент select и установить свойства как getters, чтобы можно было следить за тем, когда Angular проверяет значения.

class Skill {
  constructor( private _id, private _name ) {}

  get id() {
 console.log('Checking id');
 return this._id;
  }

  get name() {
 console.log('Checking name');
 return this._name;
  }
}

@Component({
  template: `
 <my-select [options]="skills"></my-select>
 <button (click)="trigger()">Trigger change detection</button>
  `
})
export class AppComponent {
  skills = [ new Skill(1, 'JS'), new Skill(2, 'CSS'), new Skill(3, 'Angular') ]

  trigger() {}
}

При нажатии на кнопку Angular запустит цикл обнаружения изменений. Так как мы в режиме разработки, это будет происходить дважды за одно назначение. В нашем случае вычисления следующие:

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
option.id * 2
 +
option.name * 2
 * 
  3 options
 =
 12

Оптимизация производительности вашего приложения с помощью функций Angular и не только

Angular очень быстрый, однако с ростом вашего приложения Angular все сложнее отслеживать все изменения.

Что если бы мы могли помочь Angular и показать, когда нужно проверять компонент?

Мы можем задать ChangeDetectionStrategy нашего компонента в ChangeDetectionStrategy.OnPush. Это говорит Angular, что компонент зависит лишь от его Inputs и должен проверяться только в следующих случаях:

Меняется ссылка Input

В компоненте или его дочке произошло событие

Вы явно запускаете обнаружение изменений вызовом detectChanges()/tick()/markForCheck()

@Component({
  selector: 'my-select',
  template: `
 ...
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})

Оптимизация производительности вашего приложения с помощью функций Angular и не только

Так как ни одно из описанных выше условий не выполняется, Angular не будет проверять компонент в текущем цикле определения изменений.

Использование TrackBy

Мы еще не закончили. Если в какой-то момент нам нужно будет изменить данные в коллекции (this.skills), возможно, в результате API-запроса, мы столкнемся с проблемой, так как Angular не может отслеживать элементы в коллекции и не знает о том, какой из них удален или добавлен.

Angular нужно удалить все элементы DOM, связанные с этими данными, и создать их заново. А это означает большое количество манипуляций с DOM, особенно если коллекция большая. А как мы знаем, манипуляции с DOM дорого обходятся.

Давайте посмотрим все в действии.

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
export class AppComponent {
  skills = [ ... ]

  ngOnInit() {
 setTimeout(() => {
 this.skills = [ ...same skills as before, new Skill(4, 'Typescript') ]
 }, 4000);
  }
}

Оптимизация производительности вашего приложения с помощью функций Angular и не только

Есть добавить функцию trackBy, Angular сможет отслеживать, какие элементы были добавлены или удалены по их уникальному идентификатору, а также сможет создавать и уничтожать то, что подверглось изменению.

Оптимизация производительности вашего приложения с помощью функций Angular и не только

Избегайте вычисляемых значений в шаблоне

Иногда необходимо трансформировать значение с сервера во что-либо, что можно отобразить в UI. Например:

@Component({
  selector: 'skills',
  template: `
 <table>
 <tr *ngFor="let skill of skills">{{skill.calcSomething(skill)}}</tr>
 </table>
  `
})
export class SkillsComponent {
  calcSomething(skill) { ... }
}

Проблема заключается в следующем: Angular нужно перезапускать вашу функцию в каждом цикле обнаружения изменений. Если функция выполняет что-то серьезное, она может сильно повлиять на производительность.

Если значение в процессе работы динамически не меняется, лучше всего будет:

Использовать чистые пайпы – Angular выполняет чистый пайп только, когда обнаруживает чистое изменение значения.

Генерировать новое свойство и задавать его значение один раз, например:

this.skills = this.skills.map(skill => ( { ...skill, percentage: calcSomething(skill) } );

Отключение обнаружения изменений

Представьте, что у вас есть компонент, который зависит от постоянно меняющихся данных, несколько раз в секунду.

Обновлять интерфейс при изменении данных будет довольно затратно. Лучше проверять и обновлять интерфейс каждые Х секунд.

Это можно сделать, отделив детектор изменений компонента, с помощью локальной проверки каждые х секунд.

@Component({
  selector: 'giant-list',
  template: `
 <li *ngFor="let d of dataProvider.data">Data {{d}}</lig>
  `,
})
class GiantList {
  constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {
 ref.detach();
 setInterval(() => {
 this.ref.detectChanges();
 }, 5000);
  }
}

Использование ленивой загрузки

По моему мнению, ленивая загрузка – одна из мощнейших функций Angular и меньше всего используемых.

По умолчанию Webpack выводит весь код приложения в одно большую сборку. Ленивая загрузка дает возможность оптимизировать время загрузки приложения путем разбиения приложения на функциональные модули и загрузки по требованию.

Angular делает процесс почти прозрачным.

{
  path: 'admin',
  loadChildren: 'app/admin/admin.module#AdminModule',
}

Мы даже можем отказаться от загрузки целых модулей при выполнении некоторых условий. Например, можно не загружать модуль admin, если пользователь не админ. (см. canLoad). Вот и все.

Автор: Netanel Basal

Источник: https://netbasal.com/

Редакция: Команда webformyself.

Практический курс по созданию веб-приложения на Angular4

Станьте профессиональным веб-разработчиком, создавая востребованные веб-приложения на Angular4.

Узнать подробнее
Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Angular 4 с Нуля до Профи

Angular 4 - полное руководство для современной веб-разработки

Научиться

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree