9 путей оптимизации производительности фронтенда

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



1. Используйте DocumentFragments или innerHTML вместо массовых вставок объектов (Mass Element Injection)


Несмотря на повешение производительности браузеров операции с DOM медленны. именно потому важно уменьшить количество создаваемых в DOM нод и прямых их вставок.
Например: на странице есть элемент <ul> обновляемый яваскриптом после AJAX-запроса (возвращающий список какии-то элементов). Зачастую разработчики напишут что-то вроде этого:



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

DocumentFragments - неотрисовываемое хранилище набора DOM-элементов. Рассматривая наш пример - DocumentFragment это невидимый <ul> , в который мы будем складывать элементы списка до того как они будут добавлены в дом.

Пример того же кода, но оптимизированный DocumentFragments:



Добавление дочерних элементов в DocumentFragment и последующее добавление DocumentFragment в <ul> - лишь одна операция DOM, что значительно быстрее множества вставок в DOM

Если вам не нужно работать с элементами списка, то выгоднее сформировать HTML-строку и затем внедрять ее в DOM



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

Тесты производительности и больше примеров можно увидеть по ссылке: http://jsperf.com/documentfragmenttest2/2

2. Отложение(?debouncing) часто выполняемых событий/методов


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

Вот тут и приходит debouncing. Debouncing ограничит количество запусков обработчиков в определенные промежутки времени.

Собственно функция для ограничения:



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

3. Кеширование несущественных/статических  данных в Web Storage


Web Storage API было большим прорывом после Cookie, которые разработчики используют вот уже много лет. Но у кукисов есть существенный минус - ограничение размера и они при любом запросе гоняются между сервером и клиентом. Web Storage в свою очередь хранится чисто на клиентской части. автор нижеприведенного кода использует Web Storage для хранения некоторых частей страниц на стороне пользователя, таким образом сокращая скорость загрузки страниц (кроме первой )) )

Собственно его утилита, для работы с sessionstorage:


Утилита предоставляет базовые методы get и set, а также метод isFresh для проверки свежести данных. Пример использования ниже



Посмотрите на свои сайты - есть ли у вас контент, который не меняется и можете ли вы его закешировать подобным образом?

Кстати, обратите внимание, что в представленном выше примере используется sessionStorage, но помимо него есть также: localStorage, globalStorage, "databaseStorage"
Более подробно: http://diveintohtml5.info/storage.html

4. Используйте асинхронную и отложенную загрузку


RequireJS открыла гигантскую волну асинхронной загрузки и разработки в AMD-формате. Асинхронная загрузка ресурсов стала популярна благодаря XMLHttpRequest (AJAX), позволяет неблокирующую загрузку ресурсов, что длелает вызов onload быстрее и загрузку контента без обновления страницы.

Curl - потрясный асинхронный загрузчик Джона Ханса. Curl - типичный асинхронный загрузчик, но с отличными конфигурационными опциями, полезными плагинами и многое другое. Ниже несколько примеров использования:



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

5. Используйте Array.prototype.join вместо сложения строк

Одна микрооптимизация на клиентской части это использование Array.prototype.join вместо классического сложения строк. В первом совете я использовал сложение строк, вот как выглядит код после оптимизации:



Или вот так:



Это конечно микрооптимизация, но пользователи могут это почувствовать :)

6. Используйте CSS-анимацию когда это возможно


JavaScript библиотеки, такие как jQuery и Mootools позволяют достаточно просто прикрутить анимацию. Сегодня многие разработчики до сих пор используют JavaScript для анимации на страницах, не смотря на тот факт, что современные браузеры поддерживают CSS-анимацию.

CSS-анимация более эффективна, чем анимация через JavaScript. CSS обычно также имеет дополнительное преимущество - меньше кода. Многие CSS-анимации управляются GPU и они получаются очень гладкими. Заставить анимацию работать через GPU можно при помощи простого трюка:



translate3d(0, 0, 0) как бы ничего не делает, только направляет обработку всей анимации на GPU. В случае, если CSS-анимация не поддерживается (например IE8 и ниже) вы можете условно включить JavaScript-анимацию:


Файл ie-animations.js должен содержать jQuery (или любой другой) код для замещения CSS-анимации в IE-браузерах, не поддерживающих анимацию. Это замечательное сочетание оптимизации производительности (через CSS) и глобальной поддержки (через яваскрипт)

Тут стоит отметить замечательноую библиотеку Modernizr
Она позволяет проверить поддерживаемые браузером возможности и в случае поддержки/неподдержки отреагировать загрузкой стилей, скриптов или выполнением кода. Ниже представлен пример проверки css-transitions:



7. Используйте делегирование событий


Представьте неотсортированный список, который может содержать любое количество элементов <li> и каждый <li> должен реагировать на click. Вы можете добавить обработчики индивидууально каждому элементу, но что если элементы добавляются/удаляются часто? Вы должны должны будете обновлять обработчики иакже часто. Тут и приходит делегирование событий.

Делегирование событий избавляет нас от добавления обработчиков индивидуально каждому элементу. Вместо этого обработчик вешается на родителя всех этих элементов. Когда происходит событие, event.target будет содержать ссылку на дочерний элемент, проверив который вы можете определить - куда именно пользователь кликнул. Простой пример:



8.  Использование DataURI вместо ссылки на изображение

Больший размер страницы более эффективно чем использование спрайтов и компактного кода - количество запросов при загрузке страницы также влияет на производительность. Уменьшение количества запросов увеличивает скорость загрузки страницы. Можно избавиться от загрузки изображений используя Data URI:


Конечно размер страницы будет увеличен (хотя немного, если страница гзипится), но в целом страница загрузится быстрее. Большинство браузеров поддерживает Data URI и в css-файлах (для задания фона).

9. Использование CSS @media для загрузки специфических изображений


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


Это был мой фривольный перевод статьи 9 Ways to Optimize Your Front End Performance
Скачать код можно по ссылке:

1 комментарий:

  1. Линк в тему, как я реализовал debounce - http://plutov.by/post/fn_delay

    ОтветитьУдалить

Можете оставить свой комментарий