Производительность в Angular
Производительность в Angular

Производительность в Angular

Front-end 13.10.2020

Измерение производительности

Когда речь заходит о производительности Single Page Applications, мы можем говорить о сетевой производительности и о RunTime Performance.

Инструменты для измерения RunTime производительности:

  • Benchmark.js – библиотека для замеров производительности и сбора статистики.
  • Chrome Dev Tools
  • @angular/benchpress – фреймворк для тестов производительности

Способы увеличения производительности

Разделение кода с помощью Angular

Есть два основных подхода к разделению кода:

  • Разделение кода на уровне компонентов
  • Разделение кода на уровне маршрута

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

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

Для разделения кода на уровне компонентов используют пакеты:

  • ngx-loadable
  • @herodevs/hero-loader

Для разделения модулей на уровне маршрутов используют lazyLoading стратегию загрузки модулей. Чтобы создать lazyLoading маршрут вручную, нам необходимо:

  • Создайте новый модуль
  • С помощью loadChildren объявите ленивый маршрут в родительском модуле
  • Создайте новый компонент в ленивом загружаемом модуле
  • Добавьте объявление активного маршрута в ленивом модуле
const routes: Routes = [
  {
    path: 'items',
    loadChildren: () => import('./items/items.module').then(m => m.ItemsModule)
  }
];

В модуле маршрутизации ленивого модуля добавьте маршрут для компонента.

const routes: Routes = [
  {
    path: '',
    component: ItemsComponent
  }
];

Preloading модулей

Есть встроенная стратегия, которая предварительно загружает все модули в приложении. Вы можете использовать его, настроив роутер Angular:

import { PreloadAllModules } from '@angular/router';

// ...

RouteModule.forRoot(ROUTES, { preloadingStrategy: PreloadAllModules })

// ...

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

  • Quicklink — предварительно загружать только модули, связанные с видимыми ссылками в области просмотра
  • Predictive prefetching — предварительно загружайте только те модули, которые могут понадобиться в следующий раз

Реализовать Quicklink вам поможет пакет ngx-quicklink.

Предварительный рендеринг приложения Angular

Предварительная отрисовка (Prerendering) – это запуск клиентского приложения во время сборки для записи его начального состояния в виде статического HTML.

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

В случае рендеринга на стороне сервера (Server Side Rendering), когда пользователь переходит по URL-адресу, сервер компилирует приложение (визуализирует на сервере) и отправляет сгенерированную HTML-страницу обратно клиенту.

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

Angular Universal – это набор инструментов, который позволяет нам выполнять рендеринг на стороне сервера (SSR) и предварительный рендеринг для наших приложений Angular.

Для установки Angular Universal используйте команду:

ng add @nguniversal/express-engine 

Для регистрации FCP (First Contentful Paint – первая загрузка страницы) в браузере мы добавляем скрипт в index.html.

<script>
    const po = new PerformanceObserver((list) => {
      for (const entry of list.getEntriesByName('first-contentful-paint')) {
        console.log('FCP: ', entry.startTime);
        po.disconnect();
      }
    });
    po.observe({type: 'paint', buffered: true});
  </script>

Настройка для предварительной загрузки находится в angular.json и представляет собой список маршрутов, которые вы хотите предварительно обработать.

"prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
        "browserTarget": "universal-app:build:production",
        "serverTarget": "universal-app:server:production",
        "routes": [
            "/", 
            "/about-us",
            "/contact-us"
        ]
    },
    "configurations": {
        "production": {}
    }
}

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

"prerender": {
    "builder": "@nguniversal/builders:prerender",
    "options": {
        "browserTarget": "universal-app:build:production",
        "serverTarget": "universal-app:server:production",
        "routesFile": "./pre-render-routes.txt"
    },
    "configurations": {
        "production": {}
    }
}

Файл pre-render-routes.txt будет выглядеть следующим образом:

/
/about-us
/contact-us

После запускаем команду:

npm run prerender

Изменение Change Detection Strategy

По умолчанию цикл обнаружений изменений в приложении Angular запускается практически при каждом взаимодействии с пользователем, но при настройке ChangeDetectionStrategy в OnPush – компонент будет проверяться только при изменении входных параметров @Inputs(), ивентах внутри самого компонента или же при ручном запуске обнаружения изменений.

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})

Более детально описано в статье Angular 2+: Стратегия обнаружения изменений.

Источники: blog.angular.io, ngdevelop.tech, slideshare.net, medium.com

Поделиться

Отправить ответ

avatar
  Получать новые комментарии  
Уведомлять о новых комментариях