Изучаем новые для Angular функции повышение производительности с помощью updateOn


Содержание материала:

UA Blog

Blog on instersting topics

Angular 7: Как обновится и описание нововведений

Angular 7 был недавно выпущен и не смотря на отсутствия значительных нововведений, есть несколько интересных изменений в утилитах и функциях которые увеличат производительность. И как всех предыдущих релизах новых версий, обновление будет очень легким.

Нововведения

В списке ниже будут перечислены все основные новые фичи и их описания. Но если вы хотите более детально ознакомится с ними, посетите официальный сайт.

CLI Prompts

Команда Angular постоянно сосредоточена на совершенствовании средств доступных разработчикам и новые консольные команды тому доказательство. Обычно когда вы запускаете такие команды как ng new или ng add, то они запускаются единожды. И если например вы хотите добавить роутинг, то вам нужно перезапустить команду.
Теперь с новая CLI утилита запрашивает возможные настройки. Например, при выполнении команды ng new mySuperApp у вас будет спрошено не хотите ли вы добавить роутинг. Если вы хотите попробовать разные форматы CSS, не переживайте, CLI позволит вам выбрать между CSS, SCSS, SASS, LESS. Более того можно сделать еще более тонкую настройку. Добавьте файл schematic.json используя Schematic CLI и вы можете задать Ангуляру какие параметры запрашивать при выполнении команды.

Angular Material CDK
ScrollingModule

Так как много мобильных фреймворков начали двигаться в сторону динамической загрузки таких данных как изображения или большие списки, Angular последовал их примеру, добавив ScrollingModule, который позволяет реализовать виртуальную прокрутку, то есть когда элементы становятся видимыми или невидимыми, они добавляются или удаляются из DOM. Производительность резко возросла с точки зрения пользователя. В следующий раз когда вы будете иметь потенциально большой список для прокрутки, прикрепите его компоненту cdk-virtual-scroll-viewport и получите преимущество в увеличении производительности.

DragDropModule

Теперь вы можете использовать модуль Angular Material для реализации drag&drop функциональности. Поддерживаются такие функции как пересортировка списков, перемещения элементов между списков. CDK включает автоматический рендеринг, drag обработчики, drop обработчики и даже возможность перемещения данных.

Производительность приложения

Angular 7 намного быстрее предыдущих версий. Обновления до последней версии происходит быстро( как заявляют сами разработчики это займет 10 минут), сам фреймворк работает намного быстрее, модуль виртуальной прокрутки описанный выше делает приложений более плавными и производительными.

Команда Angular пытается сделать меньше не только сам фреймворк, а также приложений написанные на нем. Они исправили часто повторяемую ошибку включения полифилов reflect-metadata в продакшн сборку. Версия Angular 7 автоматически удаляет их.
Новые проекты также используют по умолчанию Budget Bundles которые сообщат вам, когда ваше приложения достигнет лимит максимального размера. По умолчанию, вы получите предупреждение на 2MB, и ошибку на 5MB. Если вам нужно изменить эти размеры, отредактируйте ваш angular.json файл.

Обновленные зависимости

Angular теперь использует Typescript 3.1, RxJS и Node.js 10.

Обновления до Angular 7

Для большинства Angular приложений которые используют Angular 6 and RxJS 6, нужно выполнить следующую команду:

Также если вы используете Angular Material, выполните следующую команду

Изучаем AngularJS на пяти практических примерах

Скачать рабочие материалы к данной статье

Вы, наверное, слышали уже о AngularJS – JS-фреймворке с открытым исходным кодом, разработанном специалистами Google, который реально меняет представление о веб-приложениях. О нем уже много было написано, но до сих пор в Сети очень трудно найти что-то действительно ориентированное на разработчиков.

Где бы лаконично и конкретно, на практических примерах были описаны принципы работы AngularJS. Цель этой статьи – изменить подобное положение вещей. Ниже приводится описание основных составляющих элементов Angular: Модели,Представления, Контроллеры, Сервисы и Фильтры, созданное на основе пяти конкретных примеров.

Если вы предпочитаете редактировать код через ваш любимый редактор, скачайте ZIP-архив по ссылке выше.

Что такое AngularJS?

По большому счету AngularJS является основой, которая связывает HTML-код (который генерируется для просмотра страницы в окне браузера) с JavaScript объектов /моделей. Когда изменяется один из объектов, автоматически обновляется и генерируемая страница. Верно и обратное — модели связаны с текстовым полем (контентом страницы). Когда изменяется контент, это вызывает изменения и в коде сайта.

AngularJS связывает коды в единую систему, и вам не нужно больше обновлять HTML вручную или инспектировать элементы, как в случае, если вы используете JQuery. В самом деле, ни в одном из примеров, приведенных здесь, даже не упоминается JQuery!

Для использования AngularJS вы должны добавить его в код своей страницы. Для этого в тэг нужно прописать соответствующие параметры. Google’s CDN для более быстрой загрузки рекомендую еще такой код:

AngularJS включает в себя большое количество директив , которые позволяют связать HTML-элементы моделей. Они представляют из себя атрибуты, начинающиеся с префикса ng-, их можно добавлять к любому элементу. Самым важным атрибутом, который, если вы хотите использовать Angular, нужно включить во все страницы сайта является ng- приложений:

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

Но довольно теории. Давайте рассмотрим непосредственно некоторые коды.

Меню навигации

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

В приведенном выше примере, используются директивы Angular для задания и считывания активной переменной. Когда она изменяется, это инициирует изменения HTML-кода элемента. В терминологии Angular эта переменная называется моделью. Она доступна для всех директив текущей области. Ее также могут обрабатывать контроллеры (подробнее об этом в следующем примере).

Если вы использовали шаблоны JavaScript раньше, то вы знакомы с синтаксисом команды <>. Когда фреймворк видит такую строку, он заменяет содержимое переменной. Эта операция повторяется каждый раз, когда изменяется переменная.

Встроенный редактор

Для второго примера, мы создадим простой встроенный редактор – при нажатии пункта меню всплывает небольшое текстовое поле с подсказкой. Мы используем контроллер, который будет инициализировать модели и задавать два разных метода отображения подсказки. Контроллеры являются стандартными функциями JavaScript, которые автоматически выполняются фреймворком Angular. Они связаны с кодом отображения страницы вашего сайта через директивы ng-controller .

Когда функция контроллера запускается на исполнение, для нее в качестве параметра задается специальный объект $scope. Он отвечает за ввод текста в текстовый редактор. Для того, чтобы вывести его на экран, нужно прописать дополнительные свойства и функции, которые описывают отображение его элементов. С помощью NG-моделей осуществляется связь кода сайта с текстом, который вводится в рабочее поле редактора. При вводе текста Angular задает соответствующие изменения переменных.

Форма заказа

В этом примере мы рассмотрим код формы заказы, в которой автоматически выводится общая сумма. Здесь использована еще одна полезная функция AngularJS — фильтры . Фильтры позволяют вносить изменения в модели, а также объединять их с помощью символа «|». В приведенном ниже примере, используется фильтр валюты , чтобы перевести числовое значение в корректный формат цены — с разделением долларов и центов. Когда вы рассмотрите пример № 4, вы сможете с легкостью задавать свои собственные фильтры.

Связка ng-repeat ( описание ) – это еще один полезный элемент Angular. Она позволяет запустить цикл обработки массива элементов, а также задать разметку для каждого из них. Она автоматически обновляет код, если один из элементов был изменен или удален.

Функция поиска

В этом примере приводится функция, позволяющая фильтровать список элементов по определенному критерию. Это еще одно направление, где с успехом может применяться AngularJS.

Фреймворк является идеальным инструментом для создания пользовательских фильтров. Для этого сперва мы должны сформировать специальный модуль для нашего приложения.

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

Для того, чтобы создать модуль приложения, нужно выполнить всего два действия:

  1. Использовать функцию angular.module(«name»,[]) при вызове JS. Это установит границы нового модуля;
  2. Задать имя модуля в качестве значения директивы ng-app.

После этого фильтр создается очень просто функцией filter(). Также просто потом вызвать его через обращение к соответствующему модулю angular.module(«name», []).

В создании различных фильтров используется подход, базирующийся на общей философии AngularJS. В соответствии с ней каждая часть кода, который вы пишете, должна быть автономной, легко тестируемой, а также иметь возможность использоваться разными элементами фреймворка. Вы можете применять созданный однажды фильтр для обработки данных в рамках других приложений. И даже объединять его в последовательности с другими фильтрами.

Функция переключения режима вывода элементов на странице

Еще одна популярная функция – переключение по выбору пользователя различных режимов вывода элементов на странице (список или плитка). Через Angular это делается очень просто.

Кроме того, в этом примере описывается еще один важный элемент фреймворка – сервисы. Это объекты, которые могут быть использованы приложениями для взаимодействия с сервером, API или другими источниками данных. В нашем случае, мы напишем сервис, который взаимодействует с Instagram’s API и выводит массив с самыми популярными на текущий момент фотографиями.

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

Для оптимизации работы с AJAX API здесь используется модуль ngResource (в коде модуля задействована переменная $resource).

Сервисы – это полностью автономные элементы, что делает возможным написание различных вариантов модулей для реализации процесса, при этом не затрагивая остальную часть кода.

Например, во время тестирования, вы можете предпочесть выводить данные из четко заданного массива фотографий (без фильтров и обработки), что ускорит отладку всей системы.

Дополнительная литература

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

Сайт AngularJS
Руководство по AngularJS
Официальное пособие по AngularJS
Список сайтов, где представлено еще много информации по теме, видео и учебники

Данная публикация представляет собой перевод статьи « Learn AngularJS With These 5 Practical Examples » , подготовленной дружной командой проекта Интернет-технологии.ру

Stepan Suvorov Blog

Release 2.0

Оптимизируем AngularJS. Подробный разбор.

Вольный перевод статьи “Improving Angular web app performance example“. Трактат довольно фундаментальный. Большая часть методик оценки производительности подойдет для любого веб-приложения (не только AngularJS).

Состоит из следующих разделов:

Как только необходимая функциональность вашего AngularJS приложения готова, следующий шаг – работа над производительностью, то есть: начальное время загрузки, отзывчивость к действиям пользователя: приложение должно работать быстро не заставляя пользователя ждать, иначе оно будет не очень удобным. Существую множество различных советов по повышению производительности, например: Steven Czerwinksi в своем посте “Optimizing AngularJS: 1200ms to 35ms” предлагает следующие шаги:

  • кеширование DOM элементов
  • сокращение количества вотчеров
  • отложенное создание элемента
  • пропускать вотчеры спрятанных элементов

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

  • Индивидуальная функциональность
    • оптимизировать очевидные узкие места на JavaScript (не AngularJS)
  • Оценить и оптимизировать холостые проходы цикла дайджеста
    • удалить ненужные фильтры (тем самым сократив количество вотчеров)
    • удалить ненужные вотчеры переходом от двунаправленого связывания к одностороннему
  • Проанализировать все места обновления DOM
    • тяжелые операции могут быть разбиты на более простые модули
    • некоторые манипуляции могут быть сделаны за чет вебворкеров
  • Минимизировать события по сборке мусора
    • Повторно использовать память вместо выделения новой

Пример не оптимизированного приложения

В примере используется AngularJS 1.2, но техники профилирования приложения и нахождения “узких мест” могут быть применимы так же и для последующих версий.

Для примера я написал небольшое AngularJS приложение( исходный код доступен тут). Весь пример помещен в index.html файл, который может быть открыт в браузере (то есть веб сервер для запуска не нужен). Задача приложения – вычислить N простых чисел. Начнем мы с крайне неэффективной реализации и шаг за шагом будем улучшать ее.

Разворачиваем приложение локально:

Откроем index.html . Страница выглядит очень просто: пользователь вводит желаемое число простых чисел и нажимает “Find”. После чего числа вычисляются и выводятся в таблицу:

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

Первый 5 простых чисел выглядят так:

Поверхностная оценка производительности

Первоначальная версия довольно быстро находит первые 10 или даже 100 простых чисел. Но если попробовать найти 1000, то обязательно приложение начнет тормозить. Откуда такие тормоза?

Код AngularJS приложения довольно простой:

метод $scope.find выполняется очень долго для большого значения $scope.n . Обычно мы начинаем профилирование JavaScript вот так:

Я предпочитаю console.time – что позволяет использовать меньше дополнительных переменных.

для 1000 у меня выдало

То есть расчет занял 13 секунд!

Профилирование в Chrome с использованием сниппетов

Вместо того, чтобы править код и вставлять метки времени, я использую ng-profile-scope-method сниппет (о сниппетах можно почитать тут). В этом методе зафиксированы id элемента и имя анализируемого метода (в нашем случае это “find“, но вы можете их легко поменять профилируя другое приложение).

Запускаем сниппет, нажимаем на “Find”, смотрим результаты:

Когда метод закончит работу, мы можем перейти во кладку Profiles и посмотреть загруженность процессора в момент выполнения метода. Начнем разбор с представления “Chart“:

Отметим, что стек вызовов тривиален: функция обработчика события выполняется всего один раз за эти 13 секунд, так же как $apply , $eval и так до $scope.find . Внутри нашего метода find мы видим множественные вызовы к функции findPrime . Давайте посмотрим является ли findPrime “узким местом” для производительности.

Переключимся из предстваления “Chart” в “Heavy“. Оно показывает функции, расположенные в порядке убывания по времени выполнения.

В топе мы видим 2 функции – isPrime и findPrime , которые выполняются дольше всех. Обратите внимание на желтый треугольничек рядом с isPrime . Если вы наведете на него мышкой, то увидите всплывающую подсказку о том, что метод не может быть оптимизирован компилятором “на лету“. В данном случае это из-за try-catch , который находится внутри функции.

В нашем случае isPrime не требует try-catch блока совсем:

Уберем его и запустим профайлер еще раз:

после чего мы видим как время выполнение isPrime с 7.2 секунд упало до 40 миллисекунд, а общее время выполнения с 13 до 5,8 секунд. Сниппет позволяет сохранять профили для разных запусков отдельно, что дает нам возможность сравнить их.

Итак, findPrime – наша новая цель для оптимизации. Давайте посмотрим на исходник:

Функция ищет N-ое простое число по средством вычисления всех предшествующих и возвращает последнее. Но при этом для нахождения следующего (N + 1) числа она проделает все сначала. Давайте попробуем использовать ранее найденые простые числа вынеся массив foundPrimes за пределы функции:


Изменения (тег step-2) приводят к серьезному скачку производительности:

Теперь весь метод $scope.find выполняется за 389 мс, то есть скорость по сравнению с первоначальным вариантом увеличилась более чем в 40 раз!

Мы можем сделать еще одну простое изменение с целью оптимизации функции isPrime : тут больше вопрос математики – проверяя N на простоту, нам не нужно проверять остаток от деления на все простые числа идущие до него – достаточно дойти до корня из N:

Обновить код можно перейдя к тегу step-3. Профайлер $scope.find показывает что мы избавились от всех явных тормозов:

Оптимизация цикла дайджеста

Теперь можем переходить к профилирования метода объекта scope . Чтобы точно выявить слабые места, сделаем оценку на более серьезном объеме входных данных. Но сначала я добавлю небольшую деталь: вывод количества простых чисел (изменение в теге step-4):

Давайте попробуем сгенерировать 100 000 простых чисел. Это займет несколько секунд ( обновления DOM). Как только 100 000 простых чисел будут выведены на экран, попробуйте поменять количество (например: удалить один ноль). Обратите внимание на существенную задержку после нажатия на кнопку и обновления данных. Мы не модифицируем данные модели, только одно число. Таблица не должна обновляться, откуда задержка?

Чтобы отдебажить эту проблему давайте используем другой сниппет – ng-idle-apply-timing (опять таки ничего не изменяя в коде). Он покажет сколько времени занимает грязная проверка (dirty checking) каждой переменной в нашем приложении. Двойное связывание, $watch выражения и фильтры – все это делает проход цикла дайджста более медленным.

Взглянем что получилось в профайле:

Мы видим, что только на цикл дайджеста уходит больше секунды (1274 мс). Хотелось бы это исправить. Самый надежный способ ускорить работу дайджеста – повыкидывать ненужные вотчеры.

Для начала посмотрим на элементы с самыми медленными вотчерами. Используем еще 2 сниппета: сначала ng-profile-local-digest.js, после чего – ng-find-expensive-digest.js (так исторически сложилось, что второй требует метод, который определяется в первом). Просто запустите их один за одним. И у нас в консоли появится вспомогательный метод findExpensiveDigest , который можем выполнить для таблицы и поля ввода:

Используем сниппет – ng-count-watchers, чтобы посчитать общее количество вотчеров. Можете убедиться, что для случая с 100 000 простыми числами в приложении появляется аж 500 003 вотчеров! Из них 3 – обслуживают ng-repeat, вводимое значение и число в шаблоне. Остальные ( 500 000) занимаются наблюдением в ячейках таблицы:

Обратим внимание, что для каждой строчки используются избыточные фильтры. Например: << "index" | lowercase >> – это статический текст, который никогда не меняется, но Ангуляр вычисляет его снова и снова, а результаты всегда одни и те же, даже когда количество строк меняется. Давайте удалим фильтры lowercase , uppercase , isPrime , которые по сути ничего не делают(можно обновиться до тега step-5):

Обновленное приложение содержит уже только 200 003 вотчеров, и соотвественно цикл дайджеста проходит в 2 раза быстрее.

Использование директивы bind-once

Производительность уже серьезно была улучшена удалением ненужных фильтров, но мы можем ускорить еще. Отметим то, что в то время, как таблица не меняется, мы продолжаем вычислять 2 вотчера на каждую строчку, каждый раз, когда мы меняем значение поля ввода( что запускает цикл дайджеста). Данные не изменяются, поэтому мы не должны вычислять выражение еще раз. Angular1.3 представляет “одноразовое связывание” следующим синтаксисом << ::prime>> . Но AngularJS 1.2 “из коробки” такого увы не предоставляет. Как вариант можно использовать модуль bindonce: изменения незначительны; фильтры также поддерживаются:

Обновленное приложение имеет только 3 вотчера (после отображения 100 000 простых чисел), и цикл дайджеста занимает в этом случае только 5мс. Ну что ж это уже похоже на отзывчивый интерфейс.

Обновить код можно по тегу step-6. И не забудьте поставить модуль bindonce:

Избавляемся от ng-repeat

Как показало профилирование: генерация таблицы занимает 10 секунд, при этом каждая строчка и ячейка порождают несколько функциональных вызовов.

Чтобы как-то улучшить эту часть, я написал свою функцию генерирования HTML и вывод его просто через innerHTML . То есть выкидываем ng-repeat вместе с содержимым (тег step-7):

Такое изменение дало увеличение производительности в 10 раз:

Конечно же это лишает вас гибкости связывания представления с моделью, которую дает ng-repeat и так можно делать только тогда, когда вы точно уверенны, что данные меняться не будут.

Ускоряем начальный рендеринг

Давайте подойдем к проблеме с другой стороны: если процесс вычисления всех результатов занимает много времени, то мы можем показать только первоначальные результаты, и сделать это довольно быстро. То есть пользователь увидит какие-то результаты, в то время как остальные все еще будут рассчитываться. Мы можем вычислить и вывести первые 100 чисел очень быстро ( $timeout сервис:

Топ-пост этого месяца:  Как заработать в Google AdSense регистрация и настройка

Главный вычислительный метод $scope.find теперь создает большую цепочку промисов, которые будут выполнятся один за одним. И на каждом шаге будет вычислено 50 простых чисел, сгенерирован HTML и добавлен в DOM:

Изменения кода доступны в теге step-9.

Посмотрим на результаты профилирования:

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

Но мы также можем заметить, что обновления постепенно замедляются. Фиолетовый столбик(отрисовка) становится все больше и больше с каждым разом.

Проблема в способе добавления новых строк в таблицу: каждый раз при добавлении браузеру приходиться перерисовывать всю таблицу!

Вместо замены всего содержимого таблицы мы можем создавать новую таблицу и просто добавлять ее в структуру документа ( Мы так же можем добавлять другой элемент tbody в ту же самую таблицу. Но этот вариант не оценивался )

Обновленния берем в теге step-10.

Ну вот мы и добились 30fps. Что означает, что мы можем прокручивать и смотреть результаты относительно без тормозов, в то время как браузер продолжает вычислять оставшиеся результаты.

Перекладываем вычисления на WebWorkers

В итоге, я решил вынести вычисление простых чисел в поток вебворкеров, чтобы выполнять параллельно с основным кодом. Перемещаем isPrime и findPrime методы в файл primes.js . Они будут общаться с основным кодом по средством сообщений:

Чтобы упростить взаимодействие с вебворкерами, я создал сервис:

Метод $scope.find должен обрабатывать вычисления асинхронно, поэтому

Код доступен по тегу step-11.

!Внимание: Для загрузки вебворкеров нам понадобится локально запустить веб-сервер. Могу порекомендовать http-server. Устанавливает и запускается очень просто(команды выполняем из директории проекта):

Профилирования процессора теперь показывает приятные узкие столбики для основного кода:

Временной график показывает, что все выполняется быстрее и почти все итерации попадают под 60fps:

Оптимизация процесса выделения памяти

Если наше приложение в процессе выполнения занимает и освобождает много памяти, то браузер должен переодически останавливаться, чтобы собрать освободившуюся память. Задержки при сборке мусора непредсказуемы и могут быть долгими. Чтобы найти этим события(сборка мусора) на временном графике включите фильтр и введите “gc” (garbage collection). В нашем случае мы видим серьезные задержки по сборке мусора: несколько мегабайт освобождаются каждый раз и это занимает более чем 100мс. (Для теста я генерировал 150 000 простых чисел порциями по 10 000). Это заметно не вооруженным взглядом, если вы включите график работы с памятью (галочка “Memory”):

Первый кандидат на освобождение памяти – массив $scope.primes . Отметим, что он растет динамически, потому что он начинается с размерности 0 и мы продолжаем добавлять новые простые числа в массив одно за одним:

Это очень не эффективно с точки зрения выделения памяти: когда новый элемент добавляется в непустой массив, среда выполнения выделяет память под новый массив (обычно выделяется в 2 раза больше памяти), скопировать числа и почистить память за исходным. Я изменил код задав массив необходимой длинны с самого начала (используя заданное количество простых чисел):

Обновляемся из тега step-12.

Теперь временной график показывает не такие серьезные скачки в памяти:

Примечание: иногда профайлер барахлит и нужно закрыть все и открыть заново.

Изоляция профиля памяти

Чтобы лучше увидеть выделение памяти давайте изолируем конкретные шаги. Для начала давайте выключим генерацию DOM – она создает много “шума” на графике при размещении элементов.

Теперь мы можем запустить профайлер выделяемой памяти, а не профайлер процессора. Включаем профайлер и затем нажимаем кнопку “Find”:

После чего мы можем увидеть выделение памяти под большие массивы с начала. (прим.: можем навести мышкой, чтобы увидеть конкретные значения). Также можно отметить что общий размер памяти 600 008 байт (при генерации 150 000 простых чисел). Движок V8 обнаружил что мы добавляем только целые числа в массив, поэтому используется только 4 байта на элемент. Массив также имеет свойство length – эти дополнительные 8 байт.

Этот профиль дает нам представление о выделении памяти из основного кода, но он не показывает выделение памяти в вебворкерах. Изучить утечки памяти в вебворкерах выберите “primes.js” перед стартом профилирования памяти

Собраный профиль веделения памяти на вебворкерах менее детален из-за браузерных ограничений. Но мы все равно можем четко увидеть растущее выделение памяти. Если посмотрим детально – обнаружим массив foundPrimes :

Для массива foundPrimes мы так же можем сразу выделить необходимое количество памяти (тем самым предотвращая постоянное изменение размера и сборку мусора).

Вычисление только по запросу

Давайте изменим способ генерации данных приложением. Вместо предвычислений тысяч простых чисел, сгенерируем небольшую часть чисел и отрисуем таблицу. Если пользователь прокрутит до конца таблицы в поисках большего количества чисел, мы сгенерируем новую партию чисел и добавим их в DOM. Можно легко привязать генерацию к прокрутке используя директиву ngInfiniteScroll. Для этой директивы нам понадобится также подключить jQuery:

Для простоты я снова использую ng-repeat . Мы запустим $scope.find метод тогда, когда границы таблицы сравняются с границами окна пользователя. Первый вызов $scope.find сделаем вручную с помощью атрибута infinite-scroll-immediate-check .

Я выкинул ручную генерацию html таблицы, оставил только вычисление числа (которое по прежнему в вебворкере).

Обновляем код в теге step-13.

Теперь страница показывает только первые 100 чисел. Если вы начнете прокручивать вниз, то новые будут вычислены новые числа и добавлены к таблице. Генерация довольно быстрая, чтобы не тормозить прокрутку. На временном графике мы можем увидеть 3 столбика для генерации первых 400 чисел (первые 100 сгенерированны до профилирования):

Минимизация наблюдаемых объектов

Еще одна не очевидная причина тормозов в AngularJS – тяжелые вотчеры, а именно вотчеры, которые наблюдают за сложным объектом, а еще хуже за результатом функции, которая возвращает такой объект. Вот эти 2 вотчера:

AngularJS делает грязную проверку – в ходе каждого цикла дайджеста каждая наблюдаемая функция вычисляется и возвращает значение, которое сравнивается с предыдущим возвращенным значением. Это означает, что последнее значение было сохранено. Если вы используете вотчер с глубоким сравнением, тогда ангуляр сохраняет полную копию возвращаемого объекта. Это может быть довольно дорого с точки зрения производительности. Например массив с объектами:

Взять код можно из тега step-14.

Изначально загрузка приложения задерживатся на 500мс из-за объекта возвращаемого из primesWatcher и копируемого для дальнейшего сравнения. Приложение понесет тоже наказание каждый раз, когда объект primes будет изменен.

Важная заметка: полная копия занимает НАМНОГО больше времени, чем полное сравнение . Отсюда и задержка, которая появляется не в момент прохода дайджеста, а только когда что-то изменено. На практике это означает медленную реакцию на ввод пользовательских данных, когда результат вотчера копируется.

Несколько предложений как победить дорогостоящее полное копирование в вотчерах:

  • стараться использовать сравнение по ссылке (но не полный перебор)
  • повторно использовать один и тот же вотчер для нескольких действий
  • использовать свою логику определения изменения состояния

Объект primes изменяется каждый раз, когда мы добавляем новое число:

Тут я использую счетчик, чтобы гарантировано запускать вотчер, когда значение изменяется. Если бы я просто возвращал true/false, цикл дайджеста бы не заметил разницы, так как только разница возвращаемых значений играет роль, а не сами значения возвращаемые функцией.

Выводы и дальнейшее исследование

Улучшение производительности любого приложения это пошаговый процесс.

  1. Профилируйте, чтобы найти проблемные места
  2. Удаляется проблемные места
  3. Повторяйте шаги 1-2

Я считаю целесообразным сначала удалить самые явные проблемные места, прежде чем погружаться в полный анализ. Во-первых, мы удаляем код, который дает основные тормоза. Во-вторых, удаление этого кода могло повлиять на другие проблемные места.

Как правило код любого JavaScript приложения имеет проблемные места. Как только клиентский код оптимизирован, я переключаюсь на профилирование и оптимизацию Ангуляра, по большей части это удаление лишней работы, которую делает фреймворк. После чего, я переключаю внимание на выполнение кода/браузерную отрисовку, в надежде разбить большие куски на сравнительно небольшие части.

Граматное решение по улучшению производительности требует знаний JavaScript, оптимизаторов среды выполнения, процесса браузерного рендеринга и специфики фреймворка вашего приложения. В первую очередь оно требует сравнение производительности приложения с ожиданиями пользователя интерфейса при различных сценариях. AngularJS имеет некоторые проблематичные места, такие как грязная проверка в ходе цикла дайджеста. Однако, это очень гибкий фреймворк, как вы могли убедиться на примерах. Я смог изменить части системы, заменить шаги, но это по прежнему Ангулар приложение. То есть мы можем улучшить производительность каких-то конкретных частей без жертвы гибкости и простоты для всего приложения.

UPD: как альтернативу ng-repeat c ngInfiniteScroll можно использовать директиву angular-vs-repeat (обрабатывать только “видимые” строчки), которая так же дает хороший прирост к производительности.

Пути улучшения производительности AngularJS даже при большом количестве элементов DOM

Я оцениваю, использовать ли AngularJS для веб-проекта или нет, и беспокоюсь о производительности функции, которую мне нужно реализовать. Я хотел бы знать, есть ли лучший способ реализовать функциональность, которую я пытаюсь использовать в AngularJS.

По сути, мне кажется, что AngularJS реагирует на событие в зависимости от количества элементов DOM на странице, даже если элементы DOM не изменяются активно и т. д. потому что функция $ digest обходит весь DOM . по крайней мере, из моих экспериментов, это похоже на случай.

Вот сценарий игры (это не совсем то, что я действительно пытаюсь сделать, но достаточно близко для целей тестирования).

Я хотел бы, чтобы angularJS выделил слово, когда я наводил курсор на него. Однако с увеличением количества слов на странице увеличивается задержка между наведением курсора на слово и его выделением.

(Фото: этот код основан на сообщении Питера Бэкона Дарвина на форуме AngularJS).

Что следует отметить: — Да, я использую jquery для манипулирования DOM. Я пошел по этому пути, потому что это был способ зарегистрировать одного наблюдателя. Если бы я делал это исключительно в angularJS, мне пришлось бы регистрировать обработчик наведения мыши для каждого диапазона, и это, казалось, также делало страницу медленной. — Я реализовал этот подход и в чистом jquery, и производительность была хорошей. Я не верю, что вызовы jquery замедляют меня здесь. — Я только сделал первые 500 слов, которые имеют идентификаторы и классы, чтобы убедиться, что в действительности у него просто больше элементов DOM, которые, кажется, замедляют их (вместо элементов DOM, на которые может повлиять операция).

6 ответов

Я думаю, что лучший способ решить проблемы с производительностью — избегать использования абстракций высокого уровня (AngularJS ng-repeat со всей соответствующей магией фона) в таких ситуациях. AngularJS не является серебряной пулей и отлично работает с библиотеками низкого уровня. Если вам нравится такая функциональность в текстовом блоке, вы можете создать директиву, которая будет контейнером для текста и инкапсулирует всю низкоуровневую логику. Пример с пользовательской директивой, которая использует плагин letteringjs jquery:

Хотя принятый ответ уже существует, я думаю, что важно понять, почему angularJS реагирует так медленно на предоставленный вами код. На самом деле angularJS не медленен с большим количеством элементов DOM, в этом случае он медленный из-за директивы ng-mouseover, которую вы регистрируете для каждого элемента в вашем списке. Директива ng-mouseover регистрирует прослушиватель события onmouseover, и каждый раз, когда функция прослушивателя запускается, запускается ng. $ Apply (), которая запускает проверку $ diggest для грязного сравнения и просматривает все наблюдения и привязки.

Одним словом: каждый раз, когда элемент попадает в ловушку, вы можете потреблять, например, 1-6 мс для внутреннего
угловая проверка грязного сравнения (в зависимости от количества привязок, которые вы установили). Не хорошо 🙂

Это связанная реализация angularJS:

На самом деле, для выделения скрытого текста вы, вероятно, просто используете CSS:

Вполне вероятно, что с более новыми версиями Angular ваш код будет работать значительно быстрее. Для угловой версии 1.3 существует оператор bind-Once . который исключит переменные с однократной привязкой из цикла дайджеста. Если исключить тысячи элементов, это значительно снизит нагрузку на дайджест.

Как и в ECMAScript 6, angular может использовать класс Observe, что сделает проверку грязного сравнения полностью устаревшей. Таким образом, одно наведение мыши внутренне приведет к обратному вызову одного события, больше не применяется или не обрабатывается. Все с оригинальным кодом. Когда Angular применит это, я не знаю. Я думаю, в 2.0.

Сейчас это старый вопрос, но я думаю, что стоит добавить к миксу, что Angular (начиная с v1.3) теперь поддерживает однократное связывание, что помогает сократить цикл дайджеста. Я работал над несколькими приложениями, в которых добавление одноразовой привязки значительно уменьшило количество часов, что привело к повышению производительности. ng-repeat часто отвечает за добавление большого количества часов, поэтому вы можете рассмотреть возможность добавления однократной привязки к ng-repeat.

Вот краткое изложение нескольких методов, которые можно использовать, чтобы избежать добавления ненужных часов

Всегда делайте профиль первым, чтобы найти настоящее узкое место. Иногда это может быть не то, что вы изначально подозреваете. Я бы заподозрил сначала ваш собственный код, а затем Angular (большое количество наблюдателей — главная особенность, приводящая к вялой производительности). Я подробно описал, как профилировать и решать различные проблемы производительности в приложении Angular, в подробном сообщении в блоге https://glebbahmutov.com/blog/improving-angular-web-app-performance-example/

Получите zone.js из btford и запустите все функции в зоне, чтобы проверить их время, затем создайте зоны для обработки ajax-кода (crud) и другие зоны для статического кода (apis).

В качестве альтернативы, ограничение ng-repeat и /или отключение двустороннего связывания для объектов имеет большое значение. Проблема, которую веб-компоненты уже покрывают, используя shadow dom, оставляя верхнюю четкость на ощупь. still zone.js — посмотрите видео по ссылке на правдоподобие.

Хорошо, я вижу, что вы используете $watch . Angular рекомендует $ watch всякий раз, когда это очень нужно. SCenarios любит обновлять переменную через ng-model

Как повысить производительность загрузки приложений Angular2?

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


Я использую Angular2, typescript с html5.

В настоящее время мое приложение занимает 4 секунды для загрузки. Я принимаю Firebase и использую cloudflare.

Вещи, которые я делаю/информация:

  • Я сжал изображения.
  • Я сокращаю css
  • Я уменьшаю js.
  • Я использую async для своих скриптов.
  • Мои сценарии находятся в моем.
  • Скрипты около 700kb
  • Я использовал тест скорости Google и получил 65%
  • Я использовал сокращенную версию libs, которую я использую, например. бутстрап и т.д.
  • Использование systemjs.
  • Это приложение для семян im, использующее: https://github.com/mgechev/angular-seed

Когда приложение загружается, отображается синий экран (это загрузочный css), а затем через 4 секунды приложение загружается и работает очень быстро. Но требуется 4 секунды для загрузки. Кажется, что файл app.js, который минимизирует systemjs, замедляет работу всего приложения, а также не показывает представления достаточно быстро.

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

Как насчет «расщепления кода».

С сайта Webpack:

«Для больших веб-приложений неэффективно помещать весь код в один файл, особенно если некоторые блоки кода нужны только при определенных обстоятельствах. В Webpack есть функция разделить вашу кодовую базу на» куски «, которые загружаются по требованию Некоторые другие связки называют их» слоями «,» накопителями «или» фрагментами «. Эта функция называется» разделение кода».

Обратите внимание, что CLI Angular использует Webpack.

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

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

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

Ленивая загрузка модуля: . Ленивые модули загрузки помогают уменьшить время запуска. При ленивой загрузке нашему приложению не нужно загружать все сразу, ему нужно только загрузить то, что пользователь ожидает увидеть, когда приложение загружается первым. Модули, которые лениво загружаются, загружаются только тогда, когда пользователь переходит к своим маршрутам. Angular2 представил модули в своем окончательном релизе RC5. См. ниже шаг за шагом.

Компиляция Aot: В AoT браузер загружает предварительно скомпилированную версию приложения. Браузер загружает исполняемый код, чтобы он мог визуализировать приложение немедленно, не ожидая, чтобы сначала скомпилировать приложение.

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

Webpack: Webpack — популярный модуль-пакет, инструмент для связывания исходного кода приложения в удобных кусках и для загрузки этого кода с сервера в браузер. Вы можете настроить веб-приложение Angular 2 с помощью webpack (см. это руководство).

Удалить скрипты, таблицу стилей из index.html: Удалить все сценарии и таблицы стилей, которые не нужны в index.html. Вы можете динамически загрузить эти script в самом компоненте, вызвав службу.

Сделайте файл script.service.ts, который может загрузить любой script по запросу для этого компонента

Это всего лишь образец кода для динамического загрузки script, вы можете настроить его и оптимизировать самостоятельно в соответствии с вашими потребностями. Для таблицы стилей вы должны загрузить ее в компоненте с помощью styleUrl.

Использовать кеширование браузера: Файлы вашей веб-страницы будут храниться в кеше браузера при использовании кеширования браузера. Ваши страницы будут загружаться намного быстрее для повторных посетителей, а также другие страницы, которые будут использовать те же ресурсы. Для получения дополнительной информации https://varvy.com/pagespeed/leverage-browser-caching.html

минимизировать код в app.component.ts: свести к минимуму код, присутствующий в app.component.ts, который всегда запускается, когда приложение загружается или перезагружается.

установить данные в приложении Инициализация: , если вы используете одни и те же вызовы api несколько раз в своем проекте или в компонентах, или вы зависите от одних и тех же данных в нескольких компонентах, вместо того, чтобы вызывать api несколько раз, что вы можете сделать, это сохранить данные как объект в службе при инициализации приложения. Эта услуга будет действовать как единое целое по всему проекту, и вы может получить доступ к этим данным без вызова api.

Постепенная загрузка модулей шаг за шагом

Модульная структура: . Мы должны разделить наше приложение на отдельные модули. Например, приложение может иметь пользовательскую сторону и административную сторону, и каждый из них будет иметь свои собственные компоненты и маршруты, поэтому мы разделим эти две стороны на модули admin.module.ts и user.module.ts.

Корневой модуль: Каждое приложение Angular имеет класс корневого модуля. По соглашению это класс под названием AppModule в файле с именем app.module.ts, этот модуль будет импортировать два вышеуказанных модуля, а также AppComponent для начальной загрузки. Вы также можете объявить несколько компонентов в соответствии с вашими потребностями. Пример кода в app.module.ts:

  1. Маршруты: Теперь на ваших маршрутах вы можете указать следующие

Теперь, когда приложение загружается, оно будет загружать только код LoginComponent и AppComponent. Эти модули будут загружаться только при посещении /admin или/пользовательских маршрутов. Следовательно, это уменьшит размер полезной нагрузки для загрузки в браузер, что приведет к быстрой загрузке.

  1. Вложенные модули: Так же, как app.module, каждый модуль имеет свой собственный набор компонентов и маршрутов. По мере того как ваш проект становится больше, вложенность модулей внутри модуля — лучший способ оптимизации, потому что мы можем лениво загружать эти модули всякий раз, когда нам нужно.

Выше код предназначен только для объяснения, пожалуйста, обратитесь к полному примеру https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html

Трудно диагностировать точную проблему, с которой вы сталкиваетесь без всякой кодовой базы и бэкэнд (как предполагали другие, проблема может вообще не быть angular).

Сказав это, я настоятельно рекомендую вам начать использовать angular-cli. Он был разработан командой angular, чтобы выполнить все, что вам нужно сделать, в удобном интерфейсе командной строки. Поэтому мой ответ основан на использовании angular -cli.

Вот основные вещи, которые вы можете сделать, чтобы оптимизировать проект ng2 для производства:

1) Вперед времени (AoT) Компиляция — Объединение/Минирование/дрожание деревьев

Посмотрите, забудьте о головной боли в настройке набора задач gulp, чтобы выполнить все эти вещи. angular -cli обрабатывает сборку Bundling/Minification/Tree-shaking/AOT за один простой шаг:

Это приведет к созданию следующих js файлов в папке «dist»:

Вы также получите gzipped-версии этих файлов для более эффективной оптимизации:

Angular Компиляция AOT автоматически сделает «дрожание дерева» на вашем коде и избавится от любых неиспользуемых ссылок. Например, вы можете использовать lodash в своем проекте, но вы, вероятно, используете только несколько функций lodash; встряхивание деревьев урезает все неиспользуемые части lodash, которые не нужны в вашей окончательной сборке. И самое главное, компиляция AOT предварительно скомпилирует весь ваш код и представления, что означает МЕНЬШЕЕ время, когда браузеру нужно будет запустить приложение ng2. Нажмите здесь для получения дополнительной информации об angular компиляции AOT.

Топ-пост этого месяца:  Вывод рубрик (таксономий) произвольных типов записей (register_post_type).

2) ленивые загрузочные части вашего приложения Если вы продолжите свое приложение в разных частях, вам не нужно загружать ВСЕ, когда ваше приложение загружается первым. Вы можете указать различные модули для своего приложения, которые затем могут быть объединены (с помощью компилятора angular -cli aot) в разные куски. Прочитайте здесь, чтобы узнать, как организовать проект в модули, которые вы можете скомпилировать в патроны, которые загружаются только как НЕОБХОДИМЫЕ. angular -cli будет управлять созданием этих кусков для вас.

3) angular Универсальный Теперь, если вы действительно хотите быстро увеличить время загрузки, вам нужно будет рассмотреть возможность использования Angular Universal, который возникает, когда вы скомпилируете свои исходный вид НА СЕРВЕРЕ. Я не использовал angular Universal, так как мне удалось достичь быстрого времени загрузки с помощью шагов 1 и 2. Но это захватывающий вариант в наборе инструментов ng2. Имейте в виду, что вы не компилируете или не запускаете приложение ng2 на сервере, вы компилируете начальное представление серверов, так что пользователь быстро получает толчок html, и, таким образом, пользователь ПЕРЕДАЕТ время загрузки очень быстро (даже при полной загрузке будет по-прежнему немного отставать). Этот шаг не устраняет необходимость в других шагах. В качестве бонуса, angular Universal также должен помочь с SEO.

Изучаем новые для Angular функции: повышение производительности с помощью updateOn

Angular Performance Checklist

В этой статье описаны полезные практики, которые помогут вам улучшить производительность ваших приложений на Angular. «Angular Performance Checklist» покрывает множество вопросов — от server-side pre-rendering и сборки приложений, до производительности в runtime и оптимизации change detection, который выполняется Angular.

Эта статья разделена на два основных блока:

  • Network performance содержит в себе список практик, следуя которым, вы ускорите загрузку ваших приложений. Он также включает в себя способы оптимизации задержек и повышает эффективность в условиях медленого интернета.
  • Runtime performance — содержит в себе практики, которые улучшат производительность ваших приложений в runtime. Они включают в себя оптимизации change detection и rendering.

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

Большинство инструментов связаны со специфичными проблемами. Эти инструменты помогут вам улучшить качество разработки за счет автоматизации процесса.

Обратите внимание, что большинство практик применимы к HTTP/1.1 и HTTP/2. В практиках, где делаются исключения, будут пометки о том, для какой версии протокола они предназначены.

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

Bundling — это стандартная практика, направленная на уменьшение количества запросов браузером, которые он должен выполнить для загрузки приложения. По сути, в качестве входных параметров, bundler получает список модулей. Таким образом, браузер может загрузить все приложение, выполнив всего несколько запросов, вместо того, чтобы по отдельности запрашивать каждый модуль.

Скорее всего, по мере разработки вашего приложения, объединение всех модулей в один станет не эффективным. Поэтому рассмотрите Code Splitting, который можно сделать с помощью Webpack.

Дополнительные http запросы не будут происходить в HTTP/2 из-за его функции server push.

Инструменты

Инструменты, которые позволяют эффективно упаковывать в модуль ваше приложение:

  • Webpack — обеспечивает эффективное объединение кода выполняя tree-shaking.
  • Webpack Code Splitting — технология для разделения вашего кода.
  • Webpack & http2 — требуется для разделения кода в HTTP/2.
  • Rollup — позволяет объединять код, применяя tree-shaking, и используя преимущество статичных импортов модулей ES2015.
  • Google Closure Compiler — выполняет множество оптимизаций и обеспечивает объединение кода. Изначально был написан на Java, но также имеет реализацию на JavaScript JavaScript, которую можете найти здесь.
  • SystemJS Builder — обеспечивает сборку приложения в один файл с помощью SystemJS и имеет поддержку зависимостей с различными версиями.
  • Browserify.
  • ngx-build-modern — плагин для Angular CLI, который может собирать приложение в двух версиях:
    1. Для современных браузеров с модулями ES2015 и основные полифиламы, что делает bundle меньше;
    2. Дополнительная легаси версия, использующая остальные полифилы и другой compiler target (по-умолчанию).

Полезные материалы

Minification and dead code elimination

В случае медленного интернет соединения эти методы позволяют нам оптимизировать загрузку приложения за счет уменьшения его веса.

Инструменты

  • Uglify — делает минификацию кода, a именно уменьшает размер переменных, удаляет комментарии и пробелы, а также мертвый код и т.д. Он написан полностью на JavaScript, и имеет плагины для всех популярных task runners.
  • Google Closure Compiler — работает аналогично uglify. В продвинутом режиме он принудительно преобразует AST вашего приложения, чтобы проводить еще более сложные оптимизации. Он так же имеет JavaScript версию, которую можно найти здесь. GCC имеет почти полную поддержку модулей ES2015, поэтому может делать tree-shaking.

Полезные материалы

Remove template whitespace

Хотя мы и не видим символ пробела (соотвествующий регулярному выражению \s ), он все еще представлен байтами, которые передаются по сети. Однако, если мы максимально уменьшим количество пустых значений в шаблонах, то мы сможем уменьшить размер итогового AoT-кода.

К счастью, нам не нужно делать это вручную. В интерфейсе ComponentMetadata есть свойство preserveWhitespaces . Так как удаление пробелов может повлиять на DOM, оно по умолчанию имеет значение false . В случае, если мы установим свойство в true , то Angular очистит код от ненужных пробелов, что приведет к дополнительному уменьшению размера модуля.

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

Пример

После tree-shaking и сборки app.js мы получим:

Это значит, что не использованный экспорт bar не будет включен в bundle.

Инструменты

  • Webpack — предоставляет эффективную сборку с использованием tree-shaking. После сборки приложения не экспортируется код, который не был использован. Таким образом код может быть помечен как dead code и удален с помощью Uglify.
  • Rollup — предоставляет сборку с использованием tree-shaking, за счет статических импортов модулей ES2015.
  • Google Closure Compiler — предлагает множество оптимизаций и предоставляет возможность сборки приложения. Изначально он был написан на Java, но с недавнего времени поддерживает и версию для JavaScript.

Обратите внимание: GCC еще не поддерживает export * . Однако функция важна для сборки Angular приложений из-за широкого использования «barrel» файлов.

Полезные материалы

Начиная с версии Angular 6, команда Angular представила новую фичу, которая позволяет делать tree-shakable сервисы. Это значит, что сервисы не будут включены в финальный бандл пока они не будут использованы другими сервисами или компонентами. Это помогает уменьшить размер итогового бандла за счет удаления неиспользуемого кода.

Используя аттрибут providedIn в декораторе @Injectable() можно определить место, где сервис должен быть инициализирован и сделать его tree-shakeable. После этого нужно удалить его из аттрибута providers в инициализации NgModule , а также из импортов в файле NgModule .

Если MyService не используется ни в одном компоненте/сервисе/директиве, то он не будет включен в итоговый bundle.

Полезные материалы

Ahead-of-Time (AoT) Compilation

Проблемой низкоуровневых инструментов (таких как GCC, Rollup и т.д.) является то, что они не анализируют HTML-подобные шаблоны Angular компонентов. Это делает менее эффективной поддержку tree-shaking, потому что они не знают, на какие директивы имеются ссылки в шаблонах. Компилятор AoT конвертирует HTML-подобные шаблоны в JavaScript или TypeScript с импортами ES2015 модулей. Таким образом, мы можем эффективно делать tree-shaking во время сборки и удалять все неиспользуемые директивы, которые могут быть определенны Angular’ом, сторонними библиотеками или нашим приложением.

Полезные материалы

Сжатие ответов является стандартной практикой уменьшения используемого трафика для загрузки приложения. Указав заголовок Accept-Encoding , браузер говорит серверу, какие алгоритмы сжатия он поддерживает на клиентском компьютере. В свою очередь сервер в заголовке ответа устанавливает значение для Content-Encoding , чтобы сообщить браузеру, какой алгоритм сжатия был применен.

Инструменты

Инструменты, приведенные здесь, не являются специфичными для Angular, и полностью зависит от используемого веб сервера. И вот основные инструменты для сжатия:

  • deflate — алгоритмы сжатия данных, связанных с конкретным форматом файла, который использует комбинацию алгоритма LZ77 и Код Хаффмана.
  • brotli — алгоритм сжатия общего назначения без потерь, который сжимает данные, используя комбинацию современного варианта алгоритма LZ77, Кода Хаффмана и моделирование контекста 2-го порядка, со степенью сжатия, сопостовимой с лучшими в настоящее время способами сжатия общего назначения. Это сравнимо по скорости с deflate, но имеет лучшее сжатие.

Полезные материалы

Предзагрузка ресурсов это отличный способ улучшить user experience. Мы можем загружать заранее как ассеты (изображения, стили, модули предназначенные для lazy load и т.д.), так и данные. Существуют различные стратегии предзагрузки, но в большинстве случаев их использование зависит от специфики вашего приложения.

Lazy-Loading of Resources

Когда приложение обладает большой кодовой базой с сотней зависимостей, подходы, описанные выше, могут оказаться бесполезными с точки зрения снижения размеров бандла (до разумных показателей 100кб или 2мб, но это полностью зависит от бизнес целей).

В таком случае разумно подгружать модули частично, лениво. Например, допустим, разрабатываемое приложение — это площадка для электронной торговли. В таком случае мы бы хотели, чтобы панель администратора загружалась независимо от интерфейса пользователя. Если, например, администратор должен добавить новый продукт, мы бы хотели обеспечить загрузку только необходимого для этого модуля. Это могла бы быть просто страница с добавлением продукта или вся панель администратора, в зависимости от бизнес логики приложения.

Инструменты

  • Webpack — обеспечивает асинхронную загрузку модулей
  • ngx-quicklink — стратегия предварительной загрузки роутера, которая обеспечивает автоматическую ленивую загрузку модулей, связанных со всеми видимыми ссылками на экране

Don’t Lazy-Load the Default Route

Предположим, имеется следующая конфигурация роутинга:

В первый раз пользователь открывает приложения, используя адрес: https://example.com/. После этого он будет перенаправлен на /dashboard , после чего будет произведена ленивая загрузка DashboardModule .

Для того, чтобы Angular отобразил начальный компонент модуля, необходимо загрузить файл dashboard.module и все его зависимости. После этого файл должен быть проанализирован виртуальной машиной JavaScript и оценен.

Запуск дополнительных HTTP-запросов и выполнение ненужных вычислений во время начальной загрузки страницы является плохой практикой, поскольку она замедляет стартовый рендеринг страницы. Поэтому рассмотрите возможность объявления страницы по умолчанию в обход ленивой загрузки модулей.

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

Для кэширования данных мы обычно используем кастомные методы. Для кэширования статических ресурсов мы можем использовать стандартные механизмы в браузере или Service Workers с CacheStorage API.

Use Application Shell


Для того, чтобы быстрее отобразить пользователю часть страницы используйте Application Shell.

Application Shell — это минимальный пользовательский интерфейс, который мы показываем пользователям, чтобы показать, что приложение будет доступно в ближайшее время. Для динамического создания оболочки приложения вы можете использовать Angular Universal с пользовательскими директивами, которые по условиям отображают элементы в зависимости от используемой платформы рендеринга (т.е. скрывают все, кроме оболочки приложения, при использовании platform-server ).

Инструменты

  • Angular Service Worker — стремится автоматизировать процесс настройки Service Workers. Он включает в себя Service Worker для кэширования статичных ресурсов и инструмент для генерации application shell.
  • Angular Universal — Universal (изоморфный) JavaScript для Angular.

Полезные материалы

Use Service Workers

Мы думаем о Service Worker, как о HTTP-прокси, который находится в браузере. Все запросы, которые отправляются клиентом, перехватываются Service Worker. Он может обработать их или передать дальше по сети.

Инструменты

  • Angular Service Worker — направлен на автоматизацию процесса управления Service Worker. Он так же содержит Service Worker для кэширования статических ресурсов и генерацию application shell.
  • Offline Plugin для Webpack — Webpack плагин добавляющий поддержку Service Worker с fall-back для AppCache.

Полезные материалы

В этом разделе приведены рекомендации, которые необходимы для обеспечания плавной работы UI со скоростью 60 кадров в секунду (fps).

В development режиме Angular вызывает дополнительные проверки изменений, чтобы убедиться, что change detection не приводит к каким-либо дополнительным изменениям. Таким образом, Angular гарантирует, что соблюден однонаправленный поток данных.

Чтобы отключить эти проверки для production, не забудьте вызвать enableProdMode :

AoT может быть не только полезен для достижения более эффективной сборки приложения, путем применения tree-shaking, но также для повышения производительности наших приложений в runtime. Альтернативой AoT является компиляция Just-in-Time (JiT), который выполняется в runtime. Поэтому AoT позволяет уменьшить количество вычислений, необходимых для рендеринга нашего приложения, выполняя компиляцию во время сборки.

Инструменты

  • angular2-seed — стартер с поддержкой AoT компиляции.
  • angular-cli — использование ng serve —prod

Полезные материалы

Проблема типичного одностраничного приложения (SPA) заключается в том, что код выполняется в одом потоке. Это означает, что если мы хотим добиться плавного UX с 60fps, то у нас есть максимум 16мс для выполнения вычислений между кадрами. В противном случае UI будет тормозить.

В сложном приложении с серьезным деревом компонентов, где change detection должно выполнять миллионы проверок ежесекундно, нетрудно потерять целые кадры. Благодаря абстрагированности платформы Angular, а именно тому, что она отделена от архитектуры DOM, можно запустить наше приложение (включая change detection) в Web Worker, оставив основной поток ответственным только за рендеринг UI.

Инструменты

  • Модуль, который позволяет запускать приложение в Web Worker, поддерживается командой Angular. Примеры использования, можно найти здесь.
  • Webpack Web Worker Loader — загрузчик Web Worker для webpack.

Полезные материалы

Большая проблема традиционных SPA заключается в том, что их содержимое не может быть отрисовано пока не загрузится весь JavaScript, потому что весь рендеринг происходит после. Отсюда мы имеем две большие проблемы:

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

Server-side rendering решает эту проблему пре-рендерингом запрашиваемой страницы на сервере и отправкой готового шаблона во время инициациализации приложения.

Инструменты

  • Angular Universal — Universal (изоморфная) JavaScript поддержка для Angular.
  • Preboot — Библиотека для управления переноса состояния страницы (т.е. events, focus, data), которые были сгенерированы на сервере, на страницу, отображаемую в браузере

Полезные материалы

При каждом асинхронном событии Angular вызывает change detection для всего дерева компонентов. Несмотря на то что код, который обнаруживает изменения, оптимизирован для inline-caching, он все равно может быть затратным для больших и сложных приложений. Способ, который поможет улучшить производительность change detection, заключается в том, что change detection не должен выполняться для поддеревьев компонента, в которых не было изменений.

ChangeDetectionStrategy.OnPush позволяет нам отключить механизм change detection для дерева компонентов. Указав для change detection strategy в компоненте значение ChangeDetectionStrategy.OnPush , изменения будут срабатывать только тогда, когда компонент получил inputs, отличающиеся от предыдущих. Angular сравнивает предыдущие и текущие inputs по ссылке, и когда результат проверки равен false , то inputs помечаются как изменившиеся. В сочетании с иммутабельными структурами данных, OnPush улучшает производительность для «чистых» компонентов.

Полезные материалы

Detaching the Change Detector

Другой реализацией кастомного механизма отслеживания изменений является открепление и прикрепления отслеживания изменений (CD) для конкретного компонента. Как только мы открепляем CD, Angular не будет делать проверки для компонента и всей его низлежащей структуры.

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

Run outside Angular

В основе механизма отслеживания изменений в Angular лежит zone.js. Zone.js патчит все асинхронные API в браузере и запускает отслеживание изменений в конце исполнения любой асинхронной функции. В редких случаях может быть необходимо исполнить код вне контекста Angular Zone и тогда механизм отслежвания изменений не будет вызван. В таких случаях мы можем использовать метод runOutsideAngular из NgZone .

Пример

В отрывке кода далее, вы можете увидеть пример компонента с использованием данной практики. Когда метод _incrementPoints вызван, компонент начнет инкрементировать свойство _points каждые 10 мс (по умолчанию). Инкрементация создаст иллюзию анимации. Т.к. в данной ситуации мы не хотим вызывать проверку изменений для всего древа компонентов каждые 10 секунд, мы можем вызвать _incrementPoints вне контекста Angular Zone и обновить DOM вручную ( points сеттер метод).

Обратите внимание: Используйте эту практику очень осторожно и только тогда, когда вы знаете, что делаете, потому что при некорректном использовании это может привести к неустойчивому состоянию DOM. Также обратите внимание, что код выше не расчитан для запуска в WebWorkers. Если это необходимо, вы можете сделать его WebWorker совместимым, для этого нужно установить label’s value используя Angular Renderer.

Аргумент декоратора @Pipe принимает объекты в следующем формате:

Свойство pure означает, что pipe не зависит от какого-либо глобального состояния и не производит сторонних эффектов. Т.е. возвращаемое значение всегда будет одинаковым для конкретного входного аргумента. Таким образом Angular может кэшировать выходы для всех входных аргументов, передаваемых в этот pipe, и переиспользовать их в дальнейшем для избежания повторных вычислений.

Значение по умолчанию свойства pure является true .

Директива *ngFor используется для отрисовки коллекции.

Use trackBy option

По умолчанию *ngFor сравнивает объекты по ссылке.

Это значит, что когда разработчик меняет ссылку на объект во время изменения содержимого элемента, Angular распознает это как удаление старого объекта и создание нового. Это способствует уничтожению старого DOM элемента из списка и добавлению нового на его место.

Разработчик может указать, как Angular будет идентифицировать уникальность объекта: кастомная индексирующая функция в виде параметра trackBy для директивы *ngFor . Данная функция принимает два параметра: index и item . Angular использует значение, возвращаемое функцией, для идентификации элементов. Очень часто используют ID определенного элемента в качестве уникального ключа.

Пример

Minimize DOM elements

Рендеринг DOM элементов обычно является самой дорогой операцией, например, при добавлении элементов в UI. Основные затраты вызваны вставкой элемента в DOM и применением стилей. Если *ngFor рендерит множество элементов, браузер (особенно старый) может тормозить, поэтому ему может потребоваться больше времени, чтобы отрендерить все элементы. Но это не относится к оптимизациям в Angular.

Чтобы снизить количество времени на рендеринг, попробуйте следующее:

  • Виртуальная прокрутка посредством CDK или ngx-virtual-scroller
  • Уменьшение количества DOM элементов, отображаемых с помощью *ngFor в шаблоне. Обычно ненужные/неиспользуемые DOM элементы возникают в результате расширения шаблона. Переосмысление структуры, скорее всего, сделает шаблон более простым.
  • Используйте ng-container , где это возможно

Полезные материалы

Optimize template expressions

Angular извлекает выражения в шаблонах после каждого срабатывания цикла change detection. Change detection срабатывает вследствие асинхронных вызовов, например, выполнение промисов, получение ответа http, нажатие клавиш и движение курсором мыши.

Такие выражения должны завершаться быстро, иначе пользователь может замечать «дергания», особенно на слабых девайсах. Поэтому, если сталкиваетесь с затратными вычислениями, стоит подумать о кэшировании.

Полезные материалы

  • quick-execution — официальная документация по выражениям в шаблонах
  • Increasing Performance — more than a pipe dream — ng-conf видеозапись на youtube. Использование pipe вместо функции для интерполяции строки

Представленный список со временем будет постепенно развиваться добавлением и обновлением текущих практик. Если вы заметили, что чего-то не хватает, или считаете, что какие-то практики можно улучшить, то не стесняйтесь создавать issue и/или PR. Для более подробной информации об этом, пожалуйста, посмотрите раздел Contributing», который находится ниже.

В случае если вы заметите недостающую, незавершенную или некорректную информацию, вы можете сделать pull request, это будет очень ценно для нас. Для обсуждения лучших практик, которые не включены в документацию, пожалуйста, создайте issue на github.

Что нового появилось в Angular 6?

В этой статье я сделаю краткий обзор основных захватывающих обновлений, которые принес нам Angular 6, включая RxJS 6, Angular Elements, Ivy рендеринг и многое другое.

RxJS 6

Angular 6 теперь использует RxJS 6. В RxJS 6 несколько изменен способ импорта.

Если в RxJS 5 вы бы писали

А в RxJS 5.5 это:

В RxJS 6.0 аналогичная запись выглядела бы подобным образом:

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

Топ-пост этого месяца:  Как добавить слайдер на страницу записи

Также стоит отметить что был выпущен очень классный набор правил tslint, называемый rxjs-tslint . Он содержит 4 правила, которые при добавлении в Ваш проект автоматически переносят все импорты RxJS и код RxJS в совершенно новую версию с помощью простой консольной команды

Так же подобная операция может быть выполнена глобальной установкой rxjs-tslint с помощью команды

и запуском с консоли с указанием пути к файлу конфигов json:

Для проектов на Angular CLI подобная операция будет выглядеть так:

Angular Elements

Angular Elements дают возможность обернуть ваши компоненты Angular в виде веб-копонент и встроить их в non-Angular среду ( к примеру jQuery app или VueJS app). Angular Elements существовали уже некоторые время до этого, но ранее были доступны в экспериментальном формате. С помощью v6 эта разработка продвинулась вперед и теперь входит в состав фреймворка. Возможность создавать и публиковать веб-копоненты Angular и использовать их на любой HTML странице это революционный прорыв. Представьте себе, что теперь вы сможете использовать Angular date-picker в вашем уже готовом React app. С Angular Elements у Вас появилась такая возможность!

Я думаю, мы рассмотрим эту тему более детальней в следующих статьях – напишите в комментариях желаете ли Вы узнать больше о ‘Angular Elements’.

Регистрация сервисов при помощи providedIn

Теперь существует новый способ регистрации сервисов – непосредственно внутри декоратора @Injectable() с использованием нового атрибута providedIn вместо ранее исспользованого providers . Метод providedIn принимает в качестве значения ‘root’ или любой модуль вашего приложения. Когда вы используете ‘root’, ваш сервис будет зарегистрирован как singleton в приложении, и вам не нужно добавлять его к providers корневого модуля. Аналогичным образом, если вы используете providedIn: UsersModule , сервис регистрируется как provider модуля UsersModule без добавления его к остальным компонентам.

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

Если вы пишете сервис, вы его обычно используете, но сторонние модули иногда предлагают сервисы, которые вы не используете, и вы получаете большой набор бесполезного JavaScript. По этой причине это новшество будет особенно полезно для разработчиков библиотек.

Теперь Вы можете объявить InjectionToken и напрямую зарегистрировать его с providedIn , а так же прописать ему factory :

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

Если UserService использует providedIn: ‘root’ , то аналогичная запись будет выглядеть так:

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

ElementRef

В случае если вам нужно получится ссылку на элемент в своем шаблоне, вы можете использовать @ViewChild , или @ViewChildren, или непосредственно создать ее при помощи ElementRef.

Анимация

Больше нет необходимости устанавливать web-animations-js для создания анимации в Angular 6.0, за исключением случаев когда вы используете AnimationBuilder . Вы можете использовать API element.animate, а в случаях когда браузер не поддерживает API element.animate , Angular 6 будет использовать CSS keyframes.

preserveWhitespaces

Эта особенность введена еще в Angular 4.4, но так как ранее флаг по умолчанию имел значение true , то сейчас это false . Флаг был введен для увеличения производительности – со значением false он удаляет лишние пробелы, что может улучшить сгенерированный размер кода, а также ускорить создание компонентов.

ngModel и formControl

Ранее была возможность иметь ngModel и formControl в тех же полях ввода формы, но теперь это устарело, а поддержка будет удалена в Angular 7.0. Это было несколько запутанно и, вероятно, не выполняло именно то, что вы ожидали.

Поэтому подобное использование кода теперь выдаст предупреждение:

Вы можете настроить свое приложение для отображения подобных предупреждений always (дефолтное) / once / never таким образом:

В любом случае для дальнейшей работы с Angular и, возможно, в дальнейшей миграции на Angular 7.0 лучше использовать или ngModel , или formControl для одного элемента.

Ivy: новый render в Angular

Ivy – следующее поколение Angular рендеринга. Это изменение на написание кода никак влиять не будет и заметить его можно будет по причине того, что Ваше приложение становится все быстрее и меньше.

Для тех кто не в курсе: Angular компилировал Ваши шаблоны с помощью View Engine в версиях Angular 2-4 и Ivy это будет 3-е изменение рендеринга за историю Angular.

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


В Angular 6 способ Ivy рендеринга не включен по дефолту, а чтобы использовать его в своем приложении нужно прописать флаг:

Рассмотрим в чем же принципиальное отличие на простом примере: PonyComponent принимает PonyModel (с именем и цветом) в качестве ввода и отображает изображение в зависимости от цвета, а так же выводит имя.

Код, созданный с помощью старого средства визуализации
Средство рендеринга, введенное в Angular 4, создало класс для каждого шаблона, называемый ngfactory :

Основными частями этого кода являются:

  • структуру DOM состоящая из созданных элементов (div, img), их атрибуты и определения. Каждая часть DOM структуры в массиве представлена индексом.
  • функцию обнаружения изменений, в которой записан код, используемый для проверки того, соответствуют ли выражение, используемые в шаблоне, тем же значениями, что и раньше. Здесь он проверяет результат метода getPonyImageUrl и, если он изменяется, обновляет картинку, а так же проверяет имя и, если нужно, обновляет текстовое поле.

Код, созданный с помощью Ivy
Если для приложения на Angular 6 установить флаг enableIvy в значение true , то для подобного примера не сгенерируется ngfactory , но информация поступит непосредственно в статическое поле самого компонента (упрощенный код):

Все это теперь содержится в этом статическом поле. Атрибут template содержит эквивалент ngfactory , который мы использовали, но с немного другой структурой. Функция шаблона будет запускаться при каждом изменении, как раньше, но имеет 2 режима:

  • Статический режим выполняется когда компонент только создается и содержит статические DOM ноды
  • Динамический режим выполняется при каждом изменении (при необходимости обновить изображение или текстовое значение)

Несколько приятных плюшек и подведение итогов

Теперь все декораторы встроены непосредственно в их классы (это то же самое для @Injectable, @Pipe, @Directive) – это означает, что когда компилятор переводит ваш шаблон в JavaScript, разрешено использовать информацию, непосредственно доступную для компонента и его декоратора (он не может смотреть на dependencies). Файл metadata.json больше не требуется, что упрощает тулзам обработку вашего кода, и больше инструментов становятся совместимыми с пакетами npm. Это упрощает как создание, так и потребление пакетов! И, конечно же теперь у вашего приложения будет более быстрое время перекомпиляции – изменение одного компонента с меньшей вероятностью вызовет перекомпиляцию для всего приложения.

Теперь с легкостью можно обновить автоматически Ваши @angular зависимости в файле package.json

Если Вы создаете свои библиотеки на благо человечеству, вы можете создать схему, которая будет использовать ng update для того, что бы ваша библиотека обновлялась у пользователей. ng add – это способ легко и просто добавлять новые возможности в ваше приложение.

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

Выпущено обновление JS-фреймворка Angular 5.0.0

Представлена очередная версия JavaScript-фреймворка Angular 5.0.0 Pentagonal Donut — мажорное обновление с новым функционалом и исправлением багов. По словам разработчиков, теперь Angular стал еще компактнее, быстрее и проще в использовании.

Оптимизатор сборки

Теперь продакшн-сборка, созданная при помощи CLI, по умолчанию снабжена оптимизатором — это инструмент, встроенный в командную строку для уменьшения размера приложений с помощью семантического анализа кода.

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

Каждая из этих функций не только сокращает объем кода JavaScript, но и существенно увеличивает скорость работы приложения со стороны пользователей.

Универсальный StateTransfer API и поддержка DOM

Теперь можно легко обмениваться состоянием между серверной и клиентской версиями приложения.

«КРОК», Москва, Троицк, Санкт-Петербург, Нижний Новгород, Самара, Иркутск, Пермь, Краснодар, Воронеж, Челябинск, от 120 000 до 240 000 ₽

Angular Universal — проект, призванный помочь разработчикам осуществлять рендеринг на сервере (SSR) в Angular-приложениях. Рендеринг приложений на сервере с их последующей загрузкой в сгенерированный HTML существенно облегчает нахождение соответствующего контента поисковыми роботами, что положительно сказывается на производительности.

Наряду с SSR в пятую версию были добавлены ServerTransferStateModule и соответствующий BrowserTransferStateModule . Наличие этих модулей устраняет необходимость посылать второй HTTP-запрос клиенту со стороны приложения.

Еще одно примечательное обновление — добавление Domino к platform-server. Оно сделало доступным большее число манипуляций с DOM на стороне сервера, что улучшило поддержку сторонних сервер-не-ориентированных JS-библиотек.

Улучшенный компилятор

Разработчики реализовали поддержку инкрементной компиляции и усовершенствовали декораторы, тем самым ускорив процесс сборки с AOT.

TypeScript Transforms

Компилятор Angular стал еще быстрее, переняв все полезные функции TypeScript transform. По словам разработчиков, переосмысленние стандартного конвейера TypeScript позволило сократить время инкрементной сборки AOT на 95% (2 секунды вместо прежних 40).

Стоит попробовать, не говоря уже о том, что в новой версии CLI программисты обещают сделать это нововведение функцией по умолчанию.

Запуск обновленного компилятора:

Сохранение пробелов

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

либо применить сразу ко всему приложению через tsconfig.json :

Также планируется использование этого приема в качестве составной части useValue :

“Интернационализированные” конвейеры Date, Number и Currency

Разработчики представили обновленные и более стандартизированные конвейеры Date, Number и Currency, устранив необходимость в использовании полифиллов i18n.

В Angular 5.0.0 конвейеры опираются на CLDR, реализована поддержка широкого спектра локальных стандартов и конфигураций. Про различия в устройстве конвейеров 4 и 5 версий фреймворка можно прочитать тут.

Для возвращения к старой версии конвейеров можно импортировать DeprecatedI18NPipesModule .

Замена ReflectiveInjector на StaticInjector

Избавиться от еще большего количества полифиллов помогла замена ReflectiveInjector на StaticInjector. Новому injector’у больше не нужен полифилл Reflect, что позволило большинству разработчиков существенно сократить код.

До:

После:

Ускоренная Zone

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

Пропускать zones можно с помощью ngZone:’noop’ :

exportAs

Добавлена поддержка нескольких имен для компонентов/папок проекта. Это поможет пользователям легко переносить компоненты без необходимости вносить какие-либо изменения в код.

HttpClient

В Angular 4.3 более компактный, простой и мощный HttpClient был перенесен в @angular/common . Обновленный инструмент получил широкое признание среди разработчиков, и в новой версии фреймворка он рекомендуется к использованию во всех приложениях. Предыдущий @angular/http library считается устаревшим.

CLI v1.5

Поддержка Angular v5.0.0 добавлена во все CLI, начиная с версии 1.5. Теперь по умолчанию все проекты генерируются на пятой версии фреймворка.

Также в целях более строгого соответствия новым стандартам TypeScript были обновлены правила использования tsconfig.json .

Angular Forms и On Blur / Submit

Теперь валидацию и обновление значений можно применять только для blur или submit , а не всех событий ввода. Программисты могут определять тайминг и «зону охвата» этих важных процессов самостоятельно. Также asyncValidator теперь можно определять прямо в объекте options .

Целесообразно использовать $watch вместо привязки к функции в большом приложении angular для повышения производительности?

Первый вариант срабатывает много раз, чем второй. Первый вариант также срабатывает, когда я делал вещи, не связанные с field.isDirty.

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

Чтобы сделать эксперимент честным, вы должны использовать наблюдателя без выражения (From AngularJS docs):

If you want to be notified whenever $digest is called, you can register a watchExpression function with no listener. (Since watchExpression can execute multiple times per $digest cycle when a change is detected, be prepared for multiple calls to your listener.)

Как повысить производительность загрузки приложений Angular2?

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

Я использую Angular2, typescript с html5.

В настоящее время мое приложение занимает 4 секунды для загрузки. Я принимаю Firebase и использую cloudflare.

Вещи, которые я делаю/информация:

  • Я сжал изображения.
  • Я сокращаю css
  • Я уменьшаю js.
  • Я использую async для своих скриптов.
  • Мои сценарии находятся в моем.
  • Скрипты около 700kb
  • Я использовал тест скорости Google и получил 65%
  • Я использовал сокращенную версию libs, которую я использую, например. бутстрап и т.д.
  • Использование systemjs.
  • Это приложение для семян im, использующее: https://github.com/mgechev/angular-seed

Когда приложение загружается, отображается синий экран (это загрузочный css), а затем через 4 секунды приложение загружается и работает очень быстро. Но требуется 4 секунды для загрузки. Кажется, что файл app.js, который минимизирует systemjs, замедляет работу всего приложения, а также не показывает представления достаточно быстро.

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

Как насчет «расщепления кода».

С сайта Webpack:

«Для больших веб-приложений неэффективно помещать весь код в один файл, особенно если некоторые блоки кода нужны только при определенных обстоятельствах. В Webpack есть функция разделить вашу кодовую базу на» куски «, которые загружаются по требованию Некоторые другие связки называют их» слоями «,» накопителями «или» фрагментами «. Эта функция называется» разделение кода».

Обратите внимание, что CLI Angular использует Webpack.

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

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

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

Ленивая загрузка модуля: . Ленивые модули загрузки помогают уменьшить время запуска. При ленивой загрузке нашему приложению не нужно загружать все сразу, ему нужно только загрузить то, что пользователь ожидает увидеть, когда приложение загружается первым. Модули, которые лениво загружаются, загружаются только тогда, когда пользователь переходит к своим маршрутам. Angular2 представил модули в своем окончательном релизе RC5. См. ниже шаг за шагом.

Компиляция Aot: В AoT браузер загружает предварительно скомпилированную версию приложения. Браузер загружает исполняемый код, чтобы он мог визуализировать приложение немедленно, не ожидая, чтобы сначала скомпилировать приложение.

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

Webpack: Webpack — популярный модуль-пакет, инструмент для связывания исходного кода приложения в удобных кусках и для загрузки этого кода с сервера в браузер. Вы можете настроить веб-приложение Angular 2 с помощью webpack (см. это руководство).

Удалить скрипты, таблицу стилей из index.html: Удалить все сценарии и таблицы стилей, которые не нужны в index.html. Вы можете динамически загрузить эти script в самом компоненте, вызвав службу.

Сделайте файл script.service.ts, который может загрузить любой script по запросу для этого компонента

Это всего лишь образец кода для динамического загрузки script, вы можете настроить его и оптимизировать самостоятельно в соответствии с вашими потребностями. Для таблицы стилей вы должны загрузить ее в компоненте с помощью styleUrl.

Использовать кеширование браузера: Файлы вашей веб-страницы будут храниться в кеше браузера при использовании кеширования браузера. Ваши страницы будут загружаться намного быстрее для повторных посетителей, а также другие страницы, которые будут использовать те же ресурсы. Для получения дополнительной информации https://varvy.com/pagespeed/leverage-browser-caching.html

минимизировать код в app.component.ts: свести к минимуму код, присутствующий в app.component.ts, который всегда запускается, когда приложение загружается или перезагружается.

установить данные в приложении Инициализация: , если вы используете одни и те же вызовы api несколько раз в своем проекте или в компонентах, или вы зависите от одних и тех же данных в нескольких компонентах, вместо того, чтобы вызывать api несколько раз, что вы можете сделать, это сохранить данные как объект в службе при инициализации приложения. Эта услуга будет действовать как единое целое по всему проекту, и вы может получить доступ к этим данным без вызова api.

Постепенная загрузка модулей шаг за шагом

Модульная структура: . Мы должны разделить наше приложение на отдельные модули. Например, приложение может иметь пользовательскую сторону и административную сторону, и каждый из них будет иметь свои собственные компоненты и маршруты, поэтому мы разделим эти две стороны на модули admin.module.ts и user.module.ts.

Корневой модуль: Каждое приложение Angular имеет класс корневого модуля. По соглашению это класс под названием AppModule в файле с именем app.module.ts, этот модуль будет импортировать два вышеуказанных модуля, а также AppComponent для начальной загрузки. Вы также можете объявить несколько компонентов в соответствии с вашими потребностями. Пример кода в app.module.ts:

  1. Маршруты: Теперь на ваших маршрутах вы можете указать следующие

Теперь, когда приложение загружается, оно будет загружать только код LoginComponent и AppComponent. Эти модули будут загружаться только при посещении /admin или/пользовательских маршрутов. Следовательно, это уменьшит размер полезной нагрузки для загрузки в браузер, что приведет к быстрой загрузке.

  1. Вложенные модули: Так же, как app.module, каждый модуль имеет свой собственный набор компонентов и маршрутов. По мере того как ваш проект становится больше, вложенность модулей внутри модуля — лучший способ оптимизации, потому что мы можем лениво загружать эти модули всякий раз, когда нам нужно.

Выше код предназначен только для объяснения, пожалуйста, обратитесь к полному примеру https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html

Трудно диагностировать точную проблему, с которой вы сталкиваетесь без всякой кодовой базы и бэкэнд (как предполагали другие, проблема может вообще не быть angular).

Сказав это, я настоятельно рекомендую вам начать использовать angular-cli. Он был разработан командой angular, чтобы выполнить все, что вам нужно сделать, в удобном интерфейсе командной строки. Поэтому мой ответ основан на использовании angular -cli.

Вот основные вещи, которые вы можете сделать, чтобы оптимизировать проект ng2 для производства:

1) Вперед времени (AoT) Компиляция — Объединение/Минирование/дрожание деревьев

Посмотрите, забудьте о головной боли в настройке набора задач gulp, чтобы выполнить все эти вещи. angular -cli обрабатывает сборку Bundling/Minification/Tree-shaking/AOT за один простой шаг:

Это приведет к созданию следующих js файлов в папке «dist»:

Вы также получите gzipped-версии этих файлов для более эффективной оптимизации:

Angular Компиляция AOT автоматически сделает «дрожание дерева» на вашем коде и избавится от любых неиспользуемых ссылок. Например, вы можете использовать lodash в своем проекте, но вы, вероятно, используете только несколько функций lodash; встряхивание деревьев урезает все неиспользуемые части lodash, которые не нужны в вашей окончательной сборке. И самое главное, компиляция AOT предварительно скомпилирует весь ваш код и представления, что означает МЕНЬШЕЕ время, когда браузеру нужно будет запустить приложение ng2. Нажмите здесь для получения дополнительной информации об angular компиляции AOT.

2) ленивые загрузочные части вашего приложения Если вы продолжите свое приложение в разных частях, вам не нужно загружать ВСЕ, когда ваше приложение загружается первым. Вы можете указать различные модули для своего приложения, которые затем могут быть объединены (с помощью компилятора angular -cli aot) в разные куски. Прочитайте здесь, чтобы узнать, как организовать проект в модули, которые вы можете скомпилировать в патроны, которые загружаются только как НЕОБХОДИМЫЕ. angular -cli будет управлять созданием этих кусков для вас.

3) angular Универсальный Теперь, если вы действительно хотите быстро увеличить время загрузки, вам нужно будет рассмотреть возможность использования Angular Universal, который возникает, когда вы скомпилируете свои исходный вид НА СЕРВЕРЕ. Я не использовал angular Universal, так как мне удалось достичь быстрого времени загрузки с помощью шагов 1 и 2. Но это захватывающий вариант в наборе инструментов ng2. Имейте в виду, что вы не компилируете или не запускаете приложение ng2 на сервере, вы компилируете начальное представление серверов, так что пользователь быстро получает толчок html, и, таким образом, пользователь ПЕРЕДАЕТ время загрузки очень быстро (даже при полной загрузке будет по-прежнему немного отставать). Этот шаг не устраняет необходимость в других шагах. В качестве бонуса, angular Universal также должен помочь с SEO.

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