Увеличиваем скорость работы сайта при помощи оптимизации JavaScript
Сайт может работать быстрее, если выполнены следующие рекомендации по оптимизации JS-кода. Если же этого не сделать, то сайт будет недостаточно быстро отображаться на стороне клиента.
Если какие-то скриптовые библиотеки не нужны на странице — их надо отключить. В процессе разработки часто подключаются те скрипты, которые потом не используются. Например, скрипты для отладки. Или те скрипты, которые собирались использовать, но потом передумали. Не надо заставлять пользователя загружать ненужный хлам.
Если без каких-то скриптов сайт функционален, то загрузку этих JS-скриптов осуществлять после отрисовки страницы (для этого надо поместить код в конец секции body). Некоторые скрипты нужны для создания эффектов, которые инициируются не сразу после загрузки страницы или их отложенная загрузка не влияет на первое впечатление от сайта. Автоматическое пролистывание слайдера или скрипт для сбора статистики посещений, например, легко могут быть инициированы уже после отрисовки страницы в браузере. Пусть лучше пользователь побыстрее увидит страницу, а не ждёт тратит при загрузке лишнее время ради того, чтобы через 5 секунд красиво перелистнулся рекламный баннер или чтобы его посчитали.
Загружайте скрипты с поддоменов, с других доменов или используйте CDN — даже у самых продвинутых браузеров файлы с одного домена загружаются в ограниченное число потоков. Если изображений, стилей и скриптов на странице достаточно много, то образуется очередь на загрузку данных. Количество используемых потоков лимитируется только для домена, поэтому если JS-файлы будут загружаться с другого домена (или поддомена), то их загрузка произойдёт быстрее за счёт параллельности.
Блокирующие скрипты не должны подгружаться с «непонятных» внешних доменов. Если внешний домен перестанет отвечать или станет отвечать с длительной задержкой, то будет «тормозить» весь ваш сайт, а пользователи будут «любоваться» белым экраном. Если используете внешние домены для скриптов, то убедитесь, что эти домены достаточно стабильны.
JS надо сжать, минимизировать и оптимизировать. Удаление пробелов, переносов строк, сокращение названий переменных и другие оптимизации значительно уменьшают размер файлов скриптов и ускоряют загрузку. При использовании сторонних библиотек — подключайте минимизированную версию в production-окружении. Для собственных скриптов используйте специальные библиотеки, сжимающие и оптимизирующие JavaScript, — UglifierJS, JSMin, Closure Compiler, YUI Compressor. При использовании агрессивных оптимизаций обязательно прочтите рекомендации для используемого компрессора и протестируйте работоспособность полученных файлов.
Совместно используемые скрипты должны быть объединены в один файл. Загрузка одного файла в 50 Kb осуществляется быстрее загрузки 10 файлов по 5 Kb, отдача таких файлов меньше грузит сервер, да и сжатие эффективнее работает на больших файлах.
Используйте GZIP для сжатия данных. Современные браузеры поддерживают обработку сжатых данных. Оптимальный способ — предварительное сжатие используемых скриптов на максимальном уровне компрессии и отдача веб-сервером предварительно сжатых файлов. Сжатие «на лету» нагружает сервер, поэтому его на нагруженных проектах лучше не использовать.
Кэшируйте скрипты на стороне клиента — не заставляйте пользователей многократно скачивать один и тот же скрипт: используйте соответствующие заголовки в ответе веб-сервера (Expires или Cache-Control max-age, Last-Modified или ETag).
Не используйте большие библиотеки без надобности — например, ради какого-то элементарного эффекта на главной странице сайта не стоит на всех страницах подключать jQuery. Если для реализации всей интерактивности сайта может хватить 30 строчек простого js-кода, то использование объёмной библиотеки просто нерационально.
Про оптимизацию javascript кода (часть 1)
Нижеследующее — размышления после профилирования нескольких скриптов, и поисков быстрого кода.
Все больше статей по клиентской оптимизации появляется. Но проблема в том, что практики из статей начинают применять молодые разработчики без понимания причин. Зачастую авторы статей рассказывают как они решили свою проблему.
Видел людей, которые всерьез спорят про быстрые и медленные циклы, и использование бинарных операторов для ускорения. На практике потребность в подобных манипуляциях встречается очень редко. Эти споры процветают, пишутся тесты. Правда ребята забывают, что самым узким местом клиентского JS является DOM.
При переписывании цикла на более быструю версию, кеширование переменных (для более быстрого поиска по областям видимости) скрипт можно ускорить на 5%, ну на 10%. При этом произойдет
потеря в читаемости исходного кода, его понимании.
// 1
for (var i = 0; i
Вторая версия чуть более многословна, но быстрее первой. Третья менее многословна, но не совсем понятна слету (проход по массиву в обратном порядке не естественен для понимания).
На практике интерпретаторы сами оптимизируют код циклов, и большой разницы в скорости отработки в современном браузере профилирование не покажет, не говоря уже о пользовательских ощущениях. Какая разница, скрипт выполнится за 10мс или 9мс.
Подобные оптимизации сработают для старых браузеров. Но тут возникает вопрос целесообразности: надо ли держать такое количество непонятного кода только для оптимизации (еще не понятно необходимой ли) работы старых браузеров. Намного лучше оставить код многословным и однозначным. Пусть оптимизируют интерпретаторы.
А вот третий конец — это DOM. Обновление одного узла в DOM-e ведет за собой каскад телодвижений со стороны браузера: обновление свойств children, parentNode, nextSibling у нод, которые «цепляются» этим изменением, обновление liveCollections, триггер repaint и reflow, очистка памяти, если использован innerHTML, то еще дополнительный парсинг текста в DOM модель.
Узких мест в DOM-е множество. Самые тяжелые — обновление: добавление и удаление узлов. При том время отработки одного и того же кода зависит от общей сложности DOM дерева, максимальной вложенности, количества таблиц стилей и количества правил. Это означает, что один и тот же способ оптимизации даст различный прирост, в зависимости от сложности страницы.
Браузерные производители понимают, и со своей стороны стараются оптимизировать код движков. И тут мы наблюдаем другую интересную ситуацию: разные подходы к оптимизации дают разный прирост в разных браузерах. Чем древнее браузер, тем вероятнее, что хитрые манипуляции дадут преимущество.
Снова повторяется история с циклами: не стоит усложнять исходны код, подстраивая его под браузер. Пусть этим занимаются браузеростроители.
Я к чему веду: смысла в особой оптимизации кода нет. Самый разумный подход — написать код как есть, структурировать и сделать его читаемым и понятным. И только если профилирование покажет необходимость оптимизаций, начать именно с оптимизации работы с DOM.
Оптимизация node.js приложения
Дано: старое http node.js приложение и возросшая нагрузка на него.Давайте попробуем пойти путем оптимизации и разобраться, как можно найти и улучшить слабые места приложения. А быть может ускориться не трогая ни строчки кода 🙂
Всех заинтересованных добро пожаловать под кат!
Для начала определимся с методикой тестирования производительности.
Нас будет интересовать количество обслуженных запросов за 1 секунду: rps.
Запускать будем приложение в режиме 1 воркера (1 процесса), замеряя производительность старого кода и кода с оптимизациями — абсолютная производительность не важна, важна сравнительная производительность.
В типичном приложении с множествами разных роутов логично сначала найти самые загруженные запросы, на обработку которых тратится большая часть времени. Утилы вида request-log-analizer или множество подобных позволят извлечь эту информацию из логов.
С другой стороны, можно взять реальный список запросов и пулять их все (например с помощью yandex-tank-а) — получим достоверный профиль нагрузки.
Но делая множество итераций оптимизации кода, куда удобнее использовать более простой и быстрый инструмент и один конкретный тип запросов (а после оптимизации одного запроса изучать следующий, и т.д.). Мой выбор — wrk. Тем более что в моем случае количество роутов не велико — проверить все по одному не сложно.
Сразу надо оговорится, что в плане блокирующих запросов, ожидания БД и т.п. приложение уже оптимизировано, все упирается в cpu: при тестах воркер потребляет 100% cpu.
На продашен серверах используется node.js версии 6 — с неё и начнем:
Requests/sec: 1210
Пробуем на 8й ноде:
Requests/sec: 2308
10я нода:
Requests/sec: 2590
Разница очевидна. Ключевую роль тут играет обновление версии v8 — множество плохо оптимизирующегося v8 кода осталось в прошлом. И чтобы не бороться с ветряными мельницами исчезнувшими в node.js v8 — лучше сразу обновиться, а потом уже заниматься оптимизацией кода.
Переходим собственно к поиску узких мест: на мой взгляд, лучший инструмент для этого — flamegraph. И с появлением проекта 0x получить flamegraph стало очень просто — запускам 0x вместо node: 0x -o ваш_скрип.js, делаем тест, останавливаем скрипт, смотрим результат в браузере.
Примерно так выглядит flamegraph тестируемого кода до оптимизаций:
Внизу фильтры, оставляем app, deps — только код приложения и сторонних модулей.
Чем шире полоска — тем больше времени потрачено на выполнения этой функции (включая вложенные вызовы).
В первую очередь подсвечиваем неоптимизированные функции. У меня в приложении таких нашлось немного.
Далее, верхние функции — типичные кандидаты на оптимизацию. Остальные же функции выстроились горкой с относительно равномерными ступеньками — каждая функция вкладывает небольшую долю задержек, явного лидера нет.
Дальше возможен простой алгогритм действий: оптимизировать самые широкие функции, переходя от одной к другой. Но я выбрал другой подход: оптимизировать начиная от точки входа в приложения (обработчик запроса в http.createServer). В конце исследуемой функции вместо вызова следующих функций я завершаю обработку запроса, отвечая ответом-пустышкой, и изучаю производительность именно этой функции. После её оптимизации ответ-пустышка перемещается дальше по стеку вызовов к следующей функции и т.д.
Итак, оставляем только стартовую функцию, получаем:
Requests/sec:
Подключая фильтры core, v8 можно увидеть, что практически вся исследуемая функция состоит из отправки ответа, логгирования и других слабо оптимизируемых вещей — едем дальше.
Переходим к следующей функции:
Requests/sec: 16111
Ничего не изменилось — погружаемся дальше:
Requests/sec: 13330
Наш клиент! Видно что задействованная функция getByUrl занимает значимую часть стартовой функции — что хорошо коррелирует с проседанием rps.
Смотрим внимательно что в ней происходит (включаем core, v8):
много чего происходит… курим код, оптимизируем:
for (var i in this.data) {
if (this[i]._options.regexp_obj.test(url)) return this[i];
}
return null;
превращаем в
let result = null;
for (let i=0; i<this.length && !result; i++) {
if (this[i]._options.regexp_obj.test(url)) result = this[i];
}
И получаем
Requests/sec: 16015
Визуально функция «сдулась» и занимает значительно меньшую долю от стартовой функции.
В детальной информации по функции так же все значительно упростилось:
Идем дальше, к следующей функции
Requests/sec: 13316
В этой функции много array функций и, несмотря на существенное ускорение в последних версиях node.
Requests/sec: 15067
И так раз за разом, для каждой следующей функции.
Еще несколько пригодившихся оптимизаций: для хешей с динамически изменяемым набором ключей new Map() может быть на 40% быстрее обычного {};
Math.round(el*100)/100 в 2 раза быстрее чем toFixed(2).
В flamegraph-е для core и v8 функций можно увидеть как и малопонятные записи, так и вполне говорящие StringPrototypeSplit или v8::internal::Runtime_StringToNumber, и, если это значимая часть выполнения кода, попытаться оптимизировать, например просто переписать код, не выполняющий эти операции.
Например, замена split на несколько вызовов indexOf и substring может давать двойной выигрыш в производительности.
Отдельная большая и сложная тема — jit оптимизация, а вернее деоптимизированные функции.
При наличии большой доли таких функций надо будет разбираться и с ними.
Тут может помочь вдумчивое изучение вывода node —trace_file_names —trace_opt_verbose —trace-deopt —trace_opt
Например, строчки вида
deoptimizing (DEOPT soft): begin 0x2bcf38b2d079 <JSFunction getTime… Insufficient type feedback for binary operation привели к строчке
return val >= 10? val: ‘0’+val;
Замена на
return (val >= 10? »: ‘0’)+val;
исправила ситуацию.
Для старого v8 движка есть достаточно много информации по причинам и способах борьбы с деоптимизацией функций:
github.com/P0lip/v8-deoptimize-reasons — список,
www.netguru.co/blog/tracing-patterns-hinder-performance — разбор типовых причин,
www.html5rocks.com/en/tutorials/speed/v8 — про оптимизации для v8, думаю справедливо и для текущего движка v8.
Но многие из проблем уже не актуальны для нового v8.
Так или иначе, после всех оптимизаций удалось получить Requests/sec: 9971, т.е. ускорится примерно в 2 раза за счет перехода на свежую версию node. js, и еще в 4 раза за счет оптимизации кода.
Надеюсь, этот опыт будет полезен кому-нибудь еще.
Оптимизация скриптов и стилей сайта
Частая проблема неоптимизированных сайтов — это множество дополнительно подключаемых файлов. Интересно, что периодически я встречал ситуацию, что эти файлы даже не использовались. Они просто впустую нагружали сайт. В этой статье поговорим о скриптах (.js) и стилях (.css).
Оптимизация js скриптов
Сразу скажу, что оптимизация не должна вредить полноценной работе сайта. Не нужно лишать себя полезных сервисов, типа веб-аналитики или онлайн-чата.
В первую очередь, нужно сделать анализ того, используются ли каждый подключаемый скрипт на сайте. Во вторую очередь, нужно проверить, используются ли скрипты на всех страницах или только на одной/нескольких. Если пара скриптов используется только на главной странице, то не нужно их загружать на всех других страницах сайта. В любой CMS можно создать несколько шаблонов раздела head, которые будут отличаться списком подключаемых файлов.
Итак, вы убедились, что скрипты только нужные, а загружаются они только на нужных страницах. Далее смотрим внутри этих файлов. Сжат ли там код? Если нет, то простое сокращение ненужных символов может сэкономить десятки килобайт. Можно это сделать вручную (например, https://jscompress.com/), а можно с помощью дополнительных сервисов, которые сжимают код всех подключенных js файлов автоматически (например, в Modx это MinifyX).
Следующий этап оптимизации — проверить место подключения js файлов. Чем выше в шаблоне сайта подключение скриптов, тем сильнее их загрузка откладывает отображение основного контента сайта. Не всем скриптам обязательно подключение в разделе head, некоторые можно перенести в самый конец документа перед закрывающим тегом body.
Ещё один приём — это использование асинхронной загрузки скриптов, которая не блокирует загрузку прочих файлов сайта. Опять же, не все скрипты могут работать в таком режиме. Каждый нужно проверять отдельно.
<script async src="/путь-к-файлу.js"></script>
Каждый отдельный скрипт загружается с помощью отдельного запроса. Мы знаем, что чем меньше запросов, тем быстрее пройдёт загрузка всех файлов. Соответственно, можно объединить все скрипты в один или несколько. Сначала разбиваем скрипты по типам: нужно ли им быть в разделе head или можно их разместить в конце документа, могут ли скрипты загружаться асинхронно или нет. После объединения у вас может остаться пара скриптов вместо пары десятков.
Важно соблюдать последовательность объединения. Если у вас jquery плагин, то его код должен идти после самого jquery. Объединить файлы можно вручную, но лучше делать это автоматически (например, в Modx это может сделать плагин MinifyX).
Оптимизация css стилей
Также сначала проверяем необходимость подключения конкретных стилей. Если вы используете библиотеки типа Bootstrap, то выбирайте только необходимые стили, не нужно загружать то, чем вы не пользуетесь.
Принципы оптимизации загрузки css файлов аналогичны js:
- Загружаем нужны стили на нужных страницах
- Сжимаем код
- Объединяем в один файл
Можно выделить самые важные стили (описание 10-100 самых базовых элементов) и встроить их (inline) в код страницы. Google рекомендует это делать для ускорения прорисовки шаблона/структуры страницы.
Все оптимизации css стилей также лучше автоматизировать с помощью плагинов.
Вышеперечисленные базовые действия могут существенно ускорить загрузку страниц. То есть вы один раз проведёте эту работу, а количество запросов, которые требуются для загрузки сайта может сократиться на несколько десятков. Общий размер всех js и css файлов можно сократить в несколько раз после сжатия.
К сожалению, многие CMS (WordPress, Битрикс) идут с шаблонами, которые изначально сделаны так, как будто они специально хотят замедлить ваш сайт. Оптимизируйте подключаемые js и css файлы — это обязательный этап работы по ускорению скорости загрузки сайта.
Автор: Александр Дергунов
Дата публикации: 29.12.2019 г.
Как оптимизировать CSS- и JS-файлы в WordPress?
👍 Научим создавать сайты на WordPress бесплатно за 11 уроков. Подробнее →Каждый современный веб-сайт для своей работы использует CSS- и JS-файлы. Первые используются для построения разметки внешнего вида, а JS – это JavaScript-скрипты, отвечающие за расширение функционала.
Для чего оптимизировать CSS- и JS-файлы?
В рамках оптимизации (увеличения скорости) работы сайта веб-мастера стараются уменьшить размер файлов обеих типов. Это имеет смысл делать, если на сайте одновременно подключаются несколько таких файлов. В процессе эволюции сайтостроения была придумана технология минификации, которая позволяет уменьшить размеры файлов скриптов за счет удаления в них комментариев, лишних пробелов, переносов строк.
В арсенале WordPress имеется множество бесплатных плагинов, поддерживающих и успешно применяющих эту технологию. Одним их таких есть AssetsMinify.
Плагин AssetsMinify
После установки и активации плагина в админ-панели WordPress появляется страница настроек плагина, на которую можно попасть, выполнив переход Настройки -> AssetsMinify.
Тут можно сделать основные настройки. Во-первых, для включения работы плагина следует отметить галочкой пункт Use Compass. Дальше для оптимизации стилей нужно отметить пункт Compress styles, а для скриптов – Compress scripts. Следующим шагом идет включение пункта Async attribute on footer’s script tag, отвечающего за асинхронную загрузку файлов, которая позволяет Вашему веб-браузеру грузить основной код страницы, не дожидаясь загрузки css- и js-скриптов.
После выставления всех настроек необходимо нажать кнопку Save. В итоге, каждый раз при обращении к страницам Вашего сайта, скрипты и стили будут загружатся в уже сжатом виде, что в итоге довольно сильно может ускорить работу сайта в целом.
Нажмите, пожалуйста, на одну из кнопок, чтобы узнать понравилась статья или нет.
Мне нравитсяНе нравитсяЕсли Вам понравилась статья — поделитесь с друзьями
Оптимизация производительности – React
React использует несколько умных подходов для минимизации количества дорогостоящих DOM-операций, необходимых для обновления пользовательского интерфейса. Для многих приложений, использование React приведёт к быстрому пользовательскому интерфейсу без особых усилий по оптимизации производительности. Тем не менее, существует несколько способов ускорить React-приложение.
Использование продакшен-сборки
Если вы испытываете проблемы с производительностью в React-приложении, убедитесь в том, что вы проводите тесты с настройками минифицированной продакшен-сборки.
По умолчанию в React есть много вспомогательных предупреждений, очень полезных при разработке. Тем не менее, они делают React больше и медленнее, поэтому вам обязательно следует использовать продакшен-версию при деплое приложения.
Если вы не уверены в том, что процесс сборки настроен правильно, вы можете проверить это, установив React Developer Tools for Chrome. Если вы посетите сайт, работающий на React в продакшен-режиме, иконка будет с чёрным фоном:
Если вы посетите сайт с React в режиме разработки, у иконки будет красный фон:
Как правило, режим разработки используется во время работы над приложением, а продакшен-режим при деплое приложения для пользователей.
Ниже вы можете найти инструкцию по сборке своего приложения для продакшена.
Create React App
Если ваш проект сделан с помощью Create React App, выполните:
Эта команда создаст продакшен-сборку вашего приложения в папке build/
вашего проекта.
Помните, что это необходимо только перед деплоем на продакшен. Для обычной разработки используйте npm start
.
Однофайловые сборки
Мы предлагаем готовые для продакшена версии React и React DOM в виде отдельных файлов:
<script src="https://unpkg. com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
Помните, что для продакшена подходят только те файлы, которые заканчиваются на .production.min.js
.
Brunch
Для наиболее эффективной продакшен-сборки с Brunch, установите плагин terser-brunch
.
# В случае использования npm
npm install --save-dev terser-brunch
# В случае использования Yarn
yarn add --dev terser-brunch
Затем, для создания продакшен сборки, добавьте флаг -p
к команде build
:
Помните, что это нужно делать только для продакшен-сборки. Вам не нужно использовать флаг -p
или применять этот плагин во время разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
Browserify
Для наиболее эффективной продакшен-сборки с Browserify, установите несколько плагинов:
# В случае использования npm
npm install --save-dev envify terser uglifyify
# В случае использования Yarn
yarn add --dev envify terser uglifyify
При создании продакшен-сборки, убедитесь, что вы добавили эти пакеты для преобразования (порядок имеет значение):
- Плагин
envify
обеспечивает правильную среду для сборки. Сделайте его глобальным (-g
). - Плагин
uglifyify
удаляет импорты, добавленные при разработке. Сделайте его глобальным (-g
). - Наконец, полученная сборка отправляется к
terser
для минификации (прочитайте, зачем это нужно).
К примеру:
browserify ./index.js \
-g [ envify --NODE_ENV production ] \
-g uglifyify \
| terser --compress --mangle > ./bundle.js
Помните, что это нужно делать только для продакшен-сборки. Вам не следует использовать эти плагины в процессе разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
Rollup
Для наиболее эффективной продакшен-сборки с Rollup, установите несколько плагинов:
npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
При создании продакшен-сборки, убедитесь, что вы добавили эти плагины (порядок имеет значение):
- Плагин
replace
обеспечивает правильную среду для сборки. - Плагин
commonjs
обеспечивает поддержку CommonJS в Rollup. - Плагин
terser
сжимает и оптимизирует финальную сборку.
plugins: [
require('rollup-plugin-replace')({
'process.env.NODE_ENV': JSON.stringify('production')
}),
require('rollup-plugin-commonjs')(),
require('rollup-plugin-terser')(),
]
Полный пример настройки можно посмотреть здесь.
Помните, что это нужно делать только для продакшен-сборки. Вам не следует использовать плагин terser
или плагин replace
со значением 'production'
в процессе разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
webpack
Примечание:
Если вы используете Create React App, пожалуйста, следуйте инструкциям выше.
Этот раздел подойдёт для тех, кто самостоятельно настраивает webpack.
Webpack 4.0 и выше по умолчанию минифицирует код в продакшен-режиме.
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'production',
optimization: {
minimizer: [new TerserPlugin({ })],
},
};
Вы можете узнать об этом больше в документации webpack.
Помните, что это нужно делать только для продакшен-сборки. Вам не стоит использовать TerserPlugin
в процессе разработки, потому что тогда скроются вспомогательные предупреждения React и замедлится процесс сборки.
Анализ производительности компонентов с помощью вкладки Chrome «Performance»
В режиме разработки вы можете видеть как компоненты монтируются, обновляются и размонтируются с помощью инструментов производительности в браузерах, которые их поддерживают. Например:
Для того, чтобы сделать это в Chrome:
- Временно отключите все расширения Chrome, особенно React DevTools. Они могут существенно исказить результаты!
- Убедитесь, что вы запускаете приложение в режиме разработки.
- Откройте в инструментах разработчика Chrome вкладку Performance и нажмите Record.
- Выполните действия, которые вы хотите проанализировать на производительность. Не записывайте более 20 секунд, иначе Chrome может зависнуть.
- Остановите запись.
- События React будут сгруппированы под меткой User Timing.
Для более детального ознакомления, посмотрите эту статью от Бена Шварца (Ben Schwarz).
Обратите внимание, что результаты являются относительными и в продакшене рендеринг компонентов будет быстрее. Всё же это должно помочь вам понять, когда какой-то пользовательский компонент обновляется по ошибке, а также как глубоко и часто обновляется пользовательский интерфейс.
В настоящее время Chrome, Edge и IE единственные браузеры, которые поддерживают данную возможность, но мы используем стандарт User Timing API, поэтому ожидайте, что больше браузеров добавят его поддержку.
Пакеты react-dom
версии 16.5+ и react-native
версии 0.57+ предоставляют расширенные возможности анализа производительности в режиме разработки с помощью инструментов разработчика React Profiler.
Обзор профайлера можно найти в посте блога «Введение в React Profiler».
Пошаговое видео-руководство также доступно на YouTube.
Если вы ещё не установили инструменты разработчика React, вы можете найти их здесь:
Примечание
Профилирование продакшен-пакета для
react-dom
также доступно какreact-dom/profiling
. Подробнее о том, как использовать этот пакет, читайте на fb.me/react-profiling
Виртуализация длинных списков
Если ваше приложение рендерит длинные списки данных (сотни или тысячи строк), мы рекомендуем использовать метод известный как «оконный доступ». Этот метод рендерит только небольшое подмножество строк в данный момент времени и может значительно сократить время, необходимое для повторного рендера компонентов, а также количество создаваемых DOM-узлов.
react-window и react-virtualized — это популярные библиотеки для оконного доступа. Они предоставляют несколько повторно используемых компонентов для отображения списков, сеток и табличных данных. Если вы хотите использовать что-то более специфическое для вашего конкретного случая, то вы можете создать собственный компонент с оконным доступом, как это сделано в Twitter.
Избежание согласования
React создаёт и поддерживает внутреннее представление отображаемого пользовательского интерфейса. Оно также включает React-элементы возвращаемые из ваших компонентов. Это представление позволяет React избегать создания DOM-узлов и не обращаться к текущим без необходимости, поскольку эти операции могут быть медленнее, чем операции с JavaScript-объектами. Иногда его называют «виртуальный DOM», но в React Native это работает точно так же.
Когда изменяются пропсы или состояние компонента, React решает нужно ли обновление DOM, сравнивая возвращённый элемент с ранее отрендеренным. Если они не равны, React обновит DOM.
Несмотря на то, что React обновляет только изменённые DOM-узлы, повторный рендеринг всё же занимает некоторое время. В большинстве случаев это не проблема, но если замедление заметно, то вы можете всё ускорить, переопределив метод жизненного цикла shouldComponentUpdate
, который вызывается перед началом процесса ререндеринга. Реализация этой функции по умолчанию возвращает true
, указывая React выполнить обновление:
shouldComponentUpdate(nextProps, nextState) {
return true;
}
Если вы знаете ситуации, в которых ваш компонент не нуждается в обновлении, вы можете вернуть false
из shouldComponentUpdate
, чтобы пропустить весь процесс рендеринга, включая вызов render()
и так далее ниже по иерархии.
В большинстве случаев вместо того, чтобы писать shouldComponentUpdate()
вручную, вы можете наследоваться от React.PureComponent
. Это эквивалентно реализации shouldComponentUpdate()
с поверхностным сравнением текущих и предыдущих пропсов и состояния.
shouldComponentUpdate в действии
Вот поддерево компонентов. Для каждого из них SCU
указывает что возвратил shouldComponentUpdate
, а vDOMEq
указывает эквивалентны ли отрендеренные React элементы. Наконец, цвет круга указывает требуется ли согласовать компонент или нет.
Поскольку shouldComponentUpdate
возвратил false
для поддерева с корнем C2, React не пытался отрендерить C2, следовательно не нужно вызывать shouldComponentUpdate
на C4 и C5.
Для C1 и C3 shouldComponentUpdate
возвратил true
, поэтому React пришлось спуститься к листьям и проверить их. Для C6 shouldComponentUpdate
вернул true
, и поскольку отображаемые элементы не были эквивалентны, React должен был обновить DOM.
Последний интересный случай — C8. React должен был отрисовать этот компонент, но поскольку возвращаемые им React-элементы были равны ранее предоставленным, ему не нужно обновлять DOM.
Обратите внимание, что React должен был делать изменения только для C6. Для C8 этого удалось избежать сравнением отрендеренных React-элементов, а для поддеревьев C2 и C7 даже не пришлось сравнивать элементы, так как нас выручил shouldComponentUpdate
и render
не был вызван.
Примеры
Если единственный случай изменения вашего компонента это когда переменная props.color
или state.count
изменяются, вы могли бы выполнить проверку в shouldComponentUpdate
следующим образом:
class CounterButton extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this. state.count !== nextState.count) {
return true;
}
return false;
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Счётчик: {this.state.count}
</button>
);
}
}
В этом коде shouldComponentUpdate
— это простая проверка на наличие каких-либо изменений в props.color
или state.count
. Если эти значения не изменяются, то компонент не обновляется. Если ваш компонент стал более сложным, вы можете использовать аналогичный паттерн «поверхностного сравнения» между всеми полями props
и state
, чтобы определить должен ли обновиться компонент. Этот механизм достаточно распространён, поэтому React предоставляет вспомогательную функцию для работы с ним — просто наследуйтесь от React.PureComponent
. Поэтому, следующий код — это более простой способ добиться того же самого эффекта:
class CounterButton extends React. PureComponent {
constructor(props) {
super(props);
this.state = {count: 1};
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Счётчик: {this.state.count}
</button>
);
}
}
В большинстве случаев вы можете использовать React.PureComponent
вместо написания собственного shouldComponentUpdate
. Но он делает только поверхностное сравнение, поэтому его нельзя использовать, если пропсы и состояние могут измениться таким образом, который не сможет быть обнаружен при поверхностном сравнении.
Это может стать проблемой для более сложных структур данных. Например, вы хотите, чтобы компонент ListOfWords
отображал список слов, разделённых через запятую, с родительским компонентом WordAdder
, который позволяет кликнуть на кнопку, чтобы добавить слово в список. Этот код работает неправильно:
class ListOfWords extends React. PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
}
class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['словцо']
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
const words = this.state.words;
words.push('словцо');
this.setState({words: words});
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}
Проблема в том, что PureComponent
сделает сравнение по ссылке между старыми и новыми значениями this.props.words
. Поскольку этот код мутирует массив words
в методе handleClick
компонента WordAdder
, старые и новые значения this.props.words
при сравнении по ссылке будут равны, даже если слова в массиве изменились. ListOfWords
не будет обновляться, даже если он содержит новые слова, которые должны быть отрендерены.
Сила иммутабельных данных
Лучший способ решения этой проблемы — избегать мутирования значений, которые вы используете как свойства или состояние. К примеру, описанный выше метод handleClick
можно переписать с помощью concat
следующим образом:
handleClick() {
this.setState(state => ({
words: state.words.concat(['словцо'])
}));
}
ES6 поддерживает синтаксис расширения для массивов, который поможет сделать это проще. Если вы используете Create React App, то этот синтаксис доступен там по умолчанию.
handleClick() {
this.setState(state => ({
words: [...state.words, 'словцо'],
}));
};
Таким же образом вы можете переписать код, который мутирует объекты. К примеру, мы имеем объект с именем colormap
и хотим написать функцию, которая изменяет colormap. right
на 'blue'
. Мы могли бы написать:
function updateColorMap(colormap) {
colormap.right = 'blue';
}
Чтобы написать это без мутирования исходного объекта, мы можем использовать метод Object.assign:
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'blue'});
}
Функция updateColorMap
теперь возвращает новый объект, вместо того, чтобы мутировать исходный. Метод Object.assign
входит в ES6 и требует полифила.
Синтаксис расширения свойств объекта упрощает обновление объектов без мутаций:
function updateColorMap(colormap) {
return {...colormap, right: 'blue'};
}
Этот синтаксис был добавлен в JavaScript в ES2018.
Если вы используете Create React App, то Object.assign
и синтаксис расширения объектов доступны вам по умолчанию.
При работе с глубоко вложенными объектами, постоянное их обновление может запутать. Если вы столкнулись с такой проблемой, обратите внимание на Immer или immutability-helper. Эти библиотеки позволяют писать хорошо читаемый код, не теряя преимуществ иммутабельности.
Оптимизация canvas — Интерфейсы веб API
Элемент <canvas>
является одним из наиболее широко используемых инструментов для рендеринга 2D-графики в Интернете. Однако когда веб-сайты и приложения используют Canvas API на пределе его возможностей, производительность начинает снижаться. В этой статье приводятся предложения по оптимизации использования элемента canvas для обеспечения хорошей работы графики.
Ниже приведён сборник советов по улучшению производительности canvas.
Предварительно отрисуйте похожие примитивы или повторяющиеся объекты на offscreen canvas
Если вы повторяете одни и те же операции рисования в каждом кадре анимации, рассмотрите возможность их выгрузки на offscreen canvas. Затем вы можете визуализировать закадровое изображение на свой основной canvas так часто, как это необходимо, без необходимости повторять шаги, необходимые для его генерации.
myCanvas.offscreenCanvas = document.createElement('canvas');
myCanvas.offscreenCanvas.width = myCanvas.width;
myCanvas.offscreenCanvas.height = myCanvas.height;
myCanvas.getContext('2d').drawImage(myCanvas.offScreenCanvas, 0, 0);
Избегайте координат с плавающей точкой и используйте вместо них целые числа
Субпиксельный рендеринг происходит при рендеринге объектов на canvas без целых значений.
ctx.drawImage(myImage, 0.3, 0.5);
Это заставляет браузер выполнять дополнительные вычисления для создания эффекта сглаживания. Чтобы избежать этого, обязательно округлите все координаты, используемые в вызовах drawImage()
, например, с помощью Math.floor()
.
Не масштабируйте изображения в
drawImage
При загрузке кешируйте изображения разных размеров на offscreen canvas, а не постоянно масштабируйте их в drawImage()
.
Используйте несколько слоёв canvas для сложных сцен
Вы можете обнаружить, что некоторые объекты в вашем приложении нужно часто перемещать или менять, в то время как другие остаются относительно статичными. Возможной оптимизацией в этой ситуации является наложение ваших элементов с использованием нескольких элементов <canvas>
.
Например, допустим, у вас есть игра с пользовательским интерфейсом наверху, геймплеем в середине и статическим фоном внизу. В этом случае вы можете разбить свою игру на три слоя <canvas>
. Пользовательский интерфейс будет меняться только при изменении пользователем, слой с игровым процессом будет меняться с каждым новым кадром, а фон останется в основном неизменным.
<div>
<canvas></canvas>
<canvas></canvas>
<canvas></canvas>
</div>
<style>
#stage {
width: 480px;
height: 320px;
position: relative;
border: 2px solid black;
}
canvas { position: absolute; }
#ui-layer { z-index: 3; }
#game-layer { z-index: 2; }
#background-layer { z-index: 1; }
</style>
Используйте простой CSS для больших фоновых изображений
Если у вас есть статическое фоновое изображение, вы можете нарисовать его на простом элементе <div>
, используя свойство CSS background
, и расположить его под canvas. Это сведёт на нет необходимость рендеринга фона на canvas на каждом тике.
Масштабирование холста с использованием CSS-преобразований
CSS-преобразования быстрее, поскольку они используют графический процессор. В идеале, не стоит не масштабировать canvas, или можно использовать меньший canvas и увеличивать его при необходимости, но не уменьшать.
var scaleX = window.innerWidth / canvas.width;
var scaleY = window.innerHeight / canvas.height;
var scaleToFit = Math.min(scaleX, scaleY);
var scaleToCover = Math.max(scaleX, scaleY);
stage.style.transformOrigin = '0 0';
stage.style.transform = 'scale(' + scaleToFit + ')';
Отключите прозрачность
Если ваше приложение использует canvas и не нуждается в прозрачном фоне, установите для параметра alpha
значение false
при создании контекста рисования с помощью HTMLCanvasElement.getContext()
. Эта информация может использоваться браузером для оптимизации рендеринга.
var ctx = canvas.getContext('2d', { alpha: false });
Другие советы
- Объединяйте запросы к canvas. Например, рисуйте одну ломанную линию вместо нескольких отдельных линий.
- Избегайте ненужных изменений состояния canvas.
- Отображайте только изменения экрана, а не заново перерисовывайте.
- По возможности избегайте свойства
shadowBlur
(en-US). - Избегайте рендеринга текста, когда это возможно.
- Попробуйте разные способы очистки canvas ((
clearRect()
, илиfillRect()
, или изменение размера canvas). - С анимациями используйте
window.requestAnimationFrame()
вместоwindow.setInterval()
(en-US). - Будьте осторожны с тяжёлыми физическими библиотеками.
Оптимизация запуска JavaScript | Основы веб-технологий
Eng Менеджер по связям с веб-разработчиками
Поскольку мы создаем сайты, в большей степени использующие JavaScript, мы иногда платим за то, что мы посылаем вниз способами, которые не всегда легко увидеть. В этой статье мы объясните, почему небольшая дисциплина может помочь, если вы хотите, чтобы ваш сайт загружался и интерактивно быстро на мобильных устройствах. Меньше JavaScript — значит меньше время передачи по сети, меньше затрат на распаковку кода и меньше времени разбор и компиляция этого JavaScript.
Сеть
Когда большинство разработчиков думают о стоимости JavaScript, они думают об этом в сроки загрузки и стоимость исполнения . Отправка большего количества байтов JavaScript по проводу занимает больше времени, чем медленнее соединение пользователя.
Это может быть проблемой даже в странах первого мира, поскольку эффективная сеть тип подключения , который имеет пользователь, на самом деле может не быть 3G, 4G или Wi-Fi. Вы можете быть на кофейня Wi-Fi, но подключена к сотовой точке доступа со скоростью 2G.
Вы можете уменьшить стоимость сетевой передачи JavaScript через:
- Только отправка кода, необходимого пользователю .
- Используйте разделение кода для взлома разберитесь в своем JavaScript в том, что критично, а что нет. Сборщики модулей как поддержка webpack расщепление кода.
- Ленивая загрузка некритичного кода.
- Минификация
- Сжатие
- Как минимум, используйте gzip для сжатия текстовых ресурсов.
- Рассмотрите возможность использования Бротли ~ q11. Бротли превосходит gzip по степени сжатия. Это помогло CertSimple сэкономить 17% от размера сжатых байтов JS и сохранения в LinkedIn 4% на время их загрузки.
- Удаление неиспользуемого кода .
- Код кэширования для минимизации сетевых отключений.
- Использовать HTTP кеширование чтобы браузеры эффективно кэшировали ответы. Определить оптимальный время жизни для скриптов (max-age) и токены проверки (ETag), чтобы избежать передача неизмененных байтов. Кэширование
- Service Worker может сделать сеть вашего приложения устойчивой и дать вам жадный доступ к таким функциям, как код V8 кеш.
- Используйте долгосрочное кэширование, чтобы избежать повторной выборки ресурсов, которые не измененный. При использовании Webpack см. Имя файла хеширование.
Синтаксический анализ / компиляция
После загрузки одна из самых больших затрат JavaScript — это время для JS engine для разобрать / скомпилировать этот код. В Chrome DevTools, синтаксический анализ и компиляция являются частью желтого Время «написания сценария» на панели «Производительность».
Вкладки Bottom-Up и Call Tree показывают точное время синтаксического анализа / компиляции:
Хром Панель DevTools «Производительность»> «Снизу вверх». При включенной статистике вызовов V8 мы можно увидеть время, затраченное на такие этапы, как Parse и Compile. Примечание. Поддержка панели производительности для статистики вызовов времени выполнения в настоящее время является экспериментальной. Чтобы включить, перейдите в chrome: // flags / # enable-devtools-tests -> перезапустите Chrome -> перейдите в DevTools -> Настройки -> Эксперименты -> нажмите Shift 6 раз -> установите флажок называется Timeline: V8 Runtime Call Stats on Timeline
и закройте, а затем снова откройте DevTools.Но какое это имеет значение?
Затраты времени на синтаксический анализ / компиляцию кода могут сильно задержать то, как скоро пользователь может взаимодействовать с вашим сайтом. Чем больше JavaScript вы отправите, тем дольше он будет возьмите, чтобы проанализировать и скомпилировать его, прежде чем ваш сайт станет интерактивным.
байтов, JavaScript дороже для обработки браузером, чем изображение аналогичного размера или веб-шрифт — Tom Dale
По сравнению с JavaScript, обработка требует значительных затрат. изображения одинакового размера (их все равно нужно декодировать!), но в среднем на мобильных устройствах аппаратного обеспечения, JS с большей вероятностью негативно повлияет на интерактивность страницы.
JavaScript и байты изображений имеют очень разные затраты. Изображения обычно не блокируют основные нить или запретить интерактивность интерфейсов во время декодирования и растеризованный. Однако JS может задерживать интерактивность из-за синтаксического анализа, компиляции и затраты на исполнение.Когда мы говорим о медленном синтаксическом анализе и компиляции; контекст важен — мы речь идет о средних мобильных телефонах здесь. У обычных пользователей могут быть телефоны с медленными процессорами и графическими процессорами, без кеша L2 / L3 и может даже быть памятью сдерживается.
Сетевые возможности и возможности устройств не всегда совпадают. Пользователь с отличным оптоволоконным соединением не обязательно иметь лучший процессор для анализировать и оценивать отправленный на их устройство JavaScript. Это также верно в обратное .. ужасное сетевое соединение, но невероятно быстрый процессор. — Кристофер Бакстер, LinkedIn
Ниже мы видим стоимость синтаксического анализа ~ 1 МБ распакованного (простого) JavaScript на низкое и высококачественное оборудование. Разница во времени синтаксического анализа / компиляции составляет 2–5 раз. код между самыми быстрыми телефонами на рынке и средними телефонами .
Этот график выделяет время синтаксического анализа для пакета JavaScript размером 1 МБ (~ 250 КБ в сжатом виде) через настольные и мобильные устройства разных классов. Если посмотреть на стоимость синтаксического анализа, следует учитывать данные в распакованном виде, например, ~ 250 КБ сжатого сжатого файла JS распаковывает до ~ 1 МБ кода.А как насчет реального сайта, такого как CNN.com?
На iPhone 8 высокого класса для синтаксического анализа / компиляции JS CNN требуется всего ~ 4 секунды. до ~ 13 с для среднего телефона (Moto G4) . Это может существенно повлиять на то, как быстро пользователь может полностью взаимодействовать с этим сайтом.
Выше мы см. время синтаксического анализа, сравнивающее производительность чипа Apple A11 Bionic с производительностью Snapdragon 617 в более среднем оборудовании Android.Это подчеркивает важность тестирования на среднем оборудовании (например, Moto G4) вместо телефона, который может быть у вас в кармане. Контекст имеет значение однако: оптимизируйте для устройств и условий сети, которые есть у ваших пользователей.
Google Аналитика может дать представление о мобильных классы устройств, с которыми ваши реальные пользователи заходят на ваш сайт.Это может дают возможность понять реальные ограничения CPU / GPU, которые они накладывают работает с.Неужели мы действительно отправляем слишком много JavaScript? Эээ, возможно 🙂
Использование HTTP-архива (~ 500 тыс. Самых популярных сайтов) для анализа состояния JavaScript на мобильный, мы можем видите, что 50% сайтов становятся интерактивными за 14 секунд. Эти сайты тратят до 4 секунд только на парсинг и компиляцию JS.
Фактор времени, необходимого для получения и обработки JS и других ресурсов, и это возможно, неудивительно, что пользователям можно немного подождать, прежде чем они почувствуют страницы готовы к использованию.Мы определенно можем добиться большего здесь.
Удаление некритического кода JavaScript со страниц может уменьшить передачу раз, разбор и компиляция с интенсивным использованием ЦП и потенциальные накладные расходы на память. Этот также помогает сделать ваши страницы более интерактивными.
Время исполнения
Это не просто синтаксический анализ и компиляция, которые могут иметь свою цену. Выполнение JavaScript (запуск кода после синтаксического анализа / компиляции) — одна из операций, которые должны произойти в основном потоке. Длительное время выполнения также может повлиять на то, как скоро пользователь сможет взаимодействовать с вашим сайтом.
Если скрипт выполняется более 50 мс, время до интерактивности задерживается на всего времени, необходимого для загрузки, компиляции и выполнения JS — Алекс Рассел
Чтобы решить эту проблему, JavaScript извлекает выгоду из небольших фрагментов , чтобы избежать блокируя основной поток. Узнайте, можно ли сократить объем выполняемой работы сделано во время исполнения.
Прочие расходы
JavaScript может влиять на производительность страницы и другими способами:
- Память.Страницы могут часто зависать или останавливаться из-за GC (мусор коллекция). Когда браузер освобождает память, выполнение JS приостанавливается, поэтому браузер, часто собирающий мусор, может приостанавливать выполнение чаще, чем нам может понравиться. Избегайте утечек памяти и частые паузы gc, чтобы страницы не зависали.
- Во время выполнения долго работающий JavaScript может блокировать основной поток, вызывая
страницы, которые не отвечают. Разделение работы на более мелкие части (используя
requestAnimationFrame ()
илиrequestIdleCallback ()
для планирования) может минимизировать проблемы с быстродействием.
Шаблоны для снижения стоимости доставки JavaScript
Когда вы пытаетесь сохранить время синтаксического анализа / компиляции и передачи по сети для JavaScript медленный, есть шаблоны, которые могут помочь, такие как разбиение на фрагменты на основе маршрута или PRPL.
ПРПЛ
PRPL (Push, Render, Pre-cache, Lazy-load) — это шаблон, который оптимизирует интерактивность за счет агрессивного разделения кода и кеширования:
Давайте представим, какое влияние это может оказать.
Мы анализируем время загрузки популярных мобильных сайтов и прогрессивных веб-приложений, используя Статистика вызовов времени выполнения V8.Как мы видим, время синтаксического анализа (показано оранжевым) — это значительная часть того, где проводят время многие из этих сайтов:
Wego, сайту, использующему PRPL, удается поддерживать низкий уровень синтаксического анализа время для их маршрутов, становясь интерактивными очень быстро. Многие другие сайты выше принятые бюджеты на разделение кода и производительность, чтобы попытаться снизить их JS расходы.
Прогрессивная начальная загрузка
Многие сайты оптимизируют видимость контента ценой интерактивности.Получить Быстрая первая отрисовка, когда у вас есть большие пакеты JavaScript, разработчики иногда используют рендеринг на стороне сервера; затем «обновите» его, чтобы прикрепить событие обработчики, когда, наконец, будет получен JavaScript.
Будьте осторожны — это имеет свои издержки. Вы 1) обычно отправляете больших HTML ответ, который может подтолкнуть нашу интерактивность, 2) может оставить пользователя в жутком долина, где половина опыта не может быть интерактивной до тех пор, пока JavaScript заканчивает обработку.
Прогрессивная загрузка может быть лучшим подходом.Отправить минимально функциональная страница (состоящая только из HTML / JS / CSS, необходимых для текущего маршрута). По мере поступления дополнительных ресурсов приложение может выполнять отложенную загрузку и разблокировать больше функций.
Прогрессивный Начальная загрузка Пола ЛьюисаЗагрузка кода, пропорциональная тому, что находится в поле зрения, — это Святой Грааль. PRPL и Прогрессивная загрузка — это шаблоны, которые могут помочь в этом.
Выводы
Размер передачи имеет решающее значение для сетей низкого уровня. Время синтаксического анализа важно для устройств с привязкой к ЦП.Держать эти мелкие вопросы.
Командыдобились успеха, установив строгие бюджеты производительности для сохранения своих Низкое время передачи и синтаксического анализа / компиляции JavaScript. См. «Can You Позволить себе это?: Реальная производительность в Интернете Бюджеты » для руководства по бюджету для мобильных устройств.
Его полезно учитывать, насколько JS «запасает» архитектурные решения, которые мы принимаем может оставить нас для логики приложения.Если вы создаете сайт, ориентированный на мобильные устройства, приложите все усилия, чтобы на типичном оборудовании сокращайте время синтаксического анализа / компиляции JavaScript и принять бюджет производительности, чтобы ваша команда могла следить за их стоимость JavaScript.
Узнать больше
optimize-js — npm
Оптимизируйте файл JavaScript для более быстрого начального выполнения и анализа, заключив в скобки все немедленно вызываемые функции или функции, которые могут быть вызваны.
Последние изменения см. В журнале изменений.
Установить
npm install -g optimize-js
Использование
optimize-js input.js> output.js
Пример ввода:
! Function () {} ()
function runIt (fun) {fun ()}
runIt (function () {})
Пример вывода:
! (Function () {}) ()
function runIt (fun) {fun ()}
runIt ((function () {}))
Обзор теста
Браузер | Типичное увеличение / уменьшение скорости с использованием optimize-js |
---|---|
Хром 55 | 20.63% |
Кромка 14 | 13,52% |
Firefox 50 | 8,26% |
Safari 10 | -1,04% |
Эти числа основаны на тесте общих библиотек JS. Подробные сведения о тестах см. В разделе тесты.
CLI
Использование: optimize-js [параметры]
Параметры:
--source-map включить исходную карту [логическое]
-h, --help Показать справку [логическое]
Примеры:
optimize-js input.js> output.js оптимизировать input.js
optimize-js output.js читается из stdin, записывается в stdout
JavaScript API
var optimizeJs = require ('optimize-js');
var input = "! Function () {console.log ('оберните меня!')}";
var output = optimizeJs (вход);
Вы также можете передать аргументы:
var optimizeJs = require ('optimize-js');
var input = "! Function () {console.log ('оберните меня!')}";
var output = optimizeJs (input, {
sourceMap: true
});
Почему?
Современные движки JavaScript, такие как V8, Chakra и SpiderMonkey, имеют эвристику, в которой они предварительно анализируют большую часть функции перед выполнением полного анализа.Этап предварительного анализа просто проверяет синтаксические ошибки, избегая затрат на полный синтаксический анализ.
Эта эвристика основана на предположении, что на средней веб-странице большинство функций JavaScript никогда не казнены или лениво казнены. Таким образом, предварительный анализ может предотвратить более медленное время запуска, проверяя только то, что браузеру абсолютно необходимо. чтобы знать о функции (т.е. правильно ли она сформирована синтаксически).
К сожалению, это предположение не работает в случае немедленно вызываемых функциональных выражений (IIFE), таких как эти:
(функция () {console.log ('выполнено!')}) ();
(функция () {console.log ('выполнено в стиле Крокфорда!')} ());
! Function () {console.log ('выполнено в стиле UglifyJS!')} ();
Хорошая новость заключается в том, что JS-движки имеют дополнительную оптимизацию , где они пытаются обнаружить такие IIFE и пропустить этап предварительного анализа. Ура!
Плохая новость в том, что эта эвристика не всегда работает.
потому что они основаны на жадном методе проверки токена '('
сразу слева от функции.(Парсер
избегает чего-либо более сложного, потому что это равносильно синтаксическому анализу всего этого, сводя на нет преимущества предварительного синтаксического анализа).
В случаях без парена (которые включают
распространенные форматы модулей, такие как UMD / Browserify / Webpack / и т. д.), браузер фактически проанализирует функцию дважды , сначала как предварительный синтаксический анализ, а второй
как полный разбор. Это означает, что код JavaScript в целом выполняется намного медленнее, поскольку на синтаксический анализ тратится больше времени, чем необходимо. См. «Стоимость небольших модулей», чтобы понять, насколько это плохо.
К счастью, поскольку оптимизация '('
для IIFE хорошо известна, мы можем использовать ее в процессе сборки,
предварительный анализ всего файла JavaScript (роскошь, которую браузер не может себе позволить) и вставка скобок в тех случаях, когда мы знаем функция будет немедленно выполнена (или если у нас есть хорошая догадка). Это то, что делает optimize-js
.
Более подробную информацию об оптимизации IIFE можно найти в этом обсуждении.Некоторые из моих мыслей о достоинствах оптимизации во время компиляции можно найти в этом посте.
Часто задаваемые вопросы
Как это работает?
Текущая реализация заключается в синтаксическом анализе синтаксического дерева и проверке функций, которые:
- Вызываются немедленно с помощью любого оператора вызова (
function () {} ()
,! Function () {} ()
и т. Д.) - Передаются напрямую в качестве аргументов другой функции
Первый способ — легкий выигрыш — эти функции выполняются немедленно.Второй метод более эвристический, но имеет тенденцию чтобы быть безопасной ставкой, учитывая распространенные шаблоны, такие как ошибки в стиле узла, цепочки обещаний и объявления модулей UMD / Browserify / Webpack.
Во всех таких случаях optimize-js
заключает функцию в круглые скобки.
Но … вы добавляете байты!
Да, optimize-js
может добавить до двух байтов (ужас!) На функцию, что практически равно нулю, если вы
учтите gzip. Чтобы доказать это, вот размеры gzip для библиотек, которые я использую в тесте:
Скрипт | Размер (байты) | Разница (байты) |
---|---|---|
тесты / create-react-app.мин. js | 160387 | |
тесты / create-react-app.min.optimized.js | 160824 | + 437 |
тесты / immutable.min.js | 56738 | |
тесты / immutable.min.optimized.js | 56933 | + 195 |
тесты / jquery.min.js | 86808 | |
тесты / jquery.min.optimized.js | 87109 | + 301 |
тестов / lodash.мин. js | 71381 | |
тесты / lodash.min.optimized.js | 71644 | + 263 |
тесты / pouchdb.min.js | 140332 | |
тесты / pouchdb.min.optimized.js | 141231 | + 899 |
тестов / three.min.js | 486996 | |
тестов / three.min.optimized.js | 487279 | + 283 |
Предназначен ли
optimize-js
для авторов библиотек? Конечно! Если вы уже отправляете объединенную миниатюрную версию своей библиотеки, то нет причин не применять optimize-js
(при условии, что вы протестируете свой код, чтобы убедиться, что он действительно помогает!).Однако обратите внимание, что optimize-js
должен запускать после Uglify, поскольку Uglify удаляет лишние круглые скобки, а также отменяет IIFE по умолчанию. Это также означает, что если ваши пользователи применяют Uglification к вашему пакету, оптимизация будет отменена.
Также обратите внимание, что поскольку optimize-js
оптимизирует некоторые шаблоны, которые основаны на эвристике, а не , известный активно вызывается
функций, в некоторых случаях это может повредить вашей производительности. (Примеры см. В тестах ниже.Обязательно проверьте, что optimize-js
— это помощь, а не помеха для вашей конкретной кодовой базы, используя что-то вроде:
Обратите внимание, что границы сценария на самом деле рекомендуются, чтобы действительно измерить полное время синтаксического анализа / компиляции.Если вы не хотите измерять накладные расходы сети, вы можете увидеть, как мы это делаем, в наших тестах.
Вы также можете проверить Марки, который позволяет вам легко устанавливать точки отметки / измерения, которые вы можете визуально проверять на шкале времени Dev Tools, чтобы убедиться, что время компиляции измеряется.
Также обязательно протестируйте в нескольких браузерах! Если вам нужна пограничная виртуальная машина, загляните на edge.ms.
Разве это не должно быть работой Углифи?
Возможно! Это бесплатная библиотека с открытым исходным кодом, поэтому я призываю всех позаимствовать код или хорошие идеи.:)
Почему бы не обернуть каждую функцию пареном?
Как описано выше, оптимизация предварительного анализа в браузерах — очень хорошая идея для подавляющего большинства веб-сайтов, где большинство функций
не выполняются немедленно. Однако, поскольку optimize-js
знает, когда ваши функции немедленно выполняются (или может сделать разумный
догадки), может быть более разумным будет применить парен-хак.
Это действительно работает для каждого движка JavaScript?
Судя по моим тестам, эта оптимизация лучше всего работает для V8 (Chrome), за которым следует Chakra (Edge), а затем SpiderMonkey (Firefox).Для JavaScriptCore (Safari) это похоже на промывку, и на самом деле может быть небольшой регресс в целом в зависимости от вашей кодовой базы. (Опять же, вот почему так важно проводить измерения на вашей собственной кодовой базе, в браузерах, на которые вы на самом деле ориентируетесь!)
В случае с Chakra IIFE в стиле Uglify на самом деле уже оптимизированы, но использование optimize-js
не повредит, потому что
функция, перед которой стоит '('
по-прежнему переходит в быстрый путь.
Ориентиры
Эти тесты были запущены с использованием нескольких популярных библиотек, рассчитанных на производительность .now ()
измерений. В каждом тесте сообщалось о среднем 251 прогоне. optimize-js
commit da51013 был протестирован. Минификация была применена с помощью uglifyjs -mc
, Uglify 2.7.0.
Вы также можете попробовать живую версию теста.
Chrome 55, Windows 10 RS1, Surfacebook i5
Скрипт | Оригинал | Оптимизировано | Улучшение | Минифицированный | мин. + Оптимизировано | Улучшение |
---|---|---|---|---|---|---|
Создать приложение React | 55.39 мс | 51,71 мс | 6,64% | 26,12 мс | 21,09 мс | 19,26% |
неизменяемый JS | 11,61 мс | 7,95 мс | 31,50% | 8,50 мс | 5,99 мс | 29,55% |
jQuery | 22,51 мс | 16,62 мс | 26,18% | 19,35 мс | 16,10 мс | 16.80% |
Лодаш | 20,88 мс | 19,30 мс | 7,57% | 20,47 мс | 19,86 мс | 3,00% |
Чехол DB | 43,75 мс | 20,36 мс | 53,45% | 36,40 мс | 18,78 мс | 48,43% |
Три JS | 71,04 мс | 72,98 мс | -2,73% | 54.99 мс | 39,59 мс | 28,00% |
Общее улучшение: 20,63%
Edge 14, Windows 10 RS1, SurfaceBook i5
Скрипт | Оригинал | Оптимизировано | Улучшение | Минифицированный | мин. + Оптимизировано | Улучшение |
---|---|---|---|---|---|---|
Создать приложение React | 32,46 мс | 24,85 мс | 23.44% | 26,49 мс | 20,39 мс | 23,03% |
неизменяемый JS | 8,94 мс | 6,19 мс | 30,74% | 7,79 мс | 5,41 мс | 30,55% |
jQuery | 22,56 мс | 14,45 мс | 35.94% | 16,62 мс | 12,99 мс | 21,81% |
Лодаш | 22.16 мс | 21,48 мс | 3,05% | 15,77 мс | 15,46 мс | 1,96% |
Чехол DB | 24,07 мс | 21,22 мс | 11,84% | 39,76 мс | 52,86 мс | -32,98% |
Три JS | 43,77 мс | 39,99 мс | 8,65% | 54,00 мс | 36,57 мс | 32.28% |
Общее улучшение: 13,52%
Firefox 50, Windows 10 RS1, Surfacebook i5
Скрипт | Оригинал | Оптимизировано | Улучшение | Минифицированный | мин. + Оптимизировано | Улучшение |
---|---|---|---|---|---|---|
Создать приложение React | 33,56 мс | 28.02 мс | 16,50% | 24,71 мс | 22.05 мс | 10,76% |
неизменяемый JS | 6,52 мс | 5,75 мс | 11.80% | 4,96 мс | 4,58 мс | 7,47% |
jQuery | 15,77 мс | 13,97 мс | 11,41% | 12,90 мс | 12,15 мс | 5,85% |
Лодаш | 17,08 мс | 16,63 мс | 2.64% | 13,11 мс | 13,22 мс | -0,80% |
Чехол DB | 19,23 мс | 16,77 мс | 12,82% | 13,77 мс | 12,89 мс | 6,42% |
Три JS | 38,33 мс | 37,36 мс | 2,53% | 33.01 мс | 30,32 мс | 8,16% |
Общее улучшение: 8.26%
Safari 10, macOS Sierra, MacBook Pro i5 2013 года выпуска
Скрипт | Оригинал | Оптимизировано | Улучшение | Минифицированный | мин. + Оптимизировано | Улучшение |
---|---|---|---|---|---|---|
Создать приложение React | 31,60 мс | 31,60 мс | 0,00% | 23,10 мс | 23,50 мс | -1,73% |
неизменяемый JS | 5.70 мс | 5,60 мс | 1,75% | 4,50 мс | 4,50 мс | 0,00% |
jQuery | 12,40 мс | 12,60 мс | -1,61% | 10,80 мс | 10,90 мс | -0,93% |
Лодаш | 14,70 мс | 14,50 мс | 1,36% | 11,10 мс | 11,30 мс | -1.80% |
Чехол DB | 14,00 мс | 14.20 мс | -1,43% | 11,70 мс | 12,10 мс | -3,42% |
Три JS | 35,60 мс | 36,30 мс | -1,97% | 27,50 мс | 27,70 мс | -0,73% |
Общее улучшение: -1,04%
Обратите внимание, что эти результаты могут отличаться в зависимости от вашей машины, нагрузки на ваш ЦП, гремлинов и т. Д.Я запускал полный пакет несколько раз во всех браузерах и обнаружил, что эти цифры примерно репрезентативны. В нашем наборе тестов мы используем среднее значение 151 запуск, чтобы уменьшить вариабельность.
Плагины
См. Также
Спасибо
Спасибо @krisselden, @bmaurer и @pleath за объяснение этих концепций в различных выпусках GitHub. Также благодарим astexplorer, acorn и magic-string за то, что они сделали реализацию такой простой.
Спасибо Саше Айкину за щедрый вклад в улучшение этой библиотеки (особенно в v1.0,3) и подталкивает меня к повышению точности тестов.
Содействие
Сборка и запуск тестов:
Запустите тесты:
Покрытие тестового кода:
История изменений
- v1.0.3
- Намного более точный тест (# 37)
- Исправления, связанные с Browserify (# 29, # 36, # 39)
- Исправления, относящиеся к Webpack (# 7, # 34)
- v1.0.2
- Используйте estree-walker для правильного анализа ES6 (# 31)
- v1.0,1:
- Не вызывать process.exit (0) в случае успеха (# 11)
- v1.0.0
Как оптимизировать доставку JavaScript для ускорения вашего сайта
JavaScript — важный аспект создания привлекательных сайтов, но он может существенно повлиять на способ загрузки страниц. Как и любой другой файл, создающий веб-страницу, JavaScript должен загрузиться, прежде чем он сможет работать. Размер файлов JavaScript, а также способ доставки этих файлов влияют на время загрузки. JavaScript также является динамическим языком и компилируется на лету, как только браузер получает его.Это делает обработку JavaScript более дорогостоящей, чем обработку файлов других типов.
Этот пост будет посвящен оптимизации доставки для JavaScript: почему вам следует заботиться, соображениям и передовым методам, а также некоторым ссылкам на соответствующие ресурсы. Оптимизация обработки JavaScript также невероятно важна для загрузки современных веб-сайтов, но я расскажу об этом в отдельной публикации.
Влияние размера файла JS
На миллионах сайтов, измеренных с помощью HTTP-архива, на JavaScript приходится 15% веса страниц для настольных компьютеров и 16% для мобильных страниц.Для пользователей настольных компьютеров это составляет около 400 КБ на каждую посещенную страницу и 360 КБ для мобильных пользователей. Если учесть, что первое соединение, открытое для загрузки страницы, передает только 14 КБ данных, становится очевидным, что уменьшение размера файла JS является важной оптимизацией.
Но 400 КБ JavaScript не равны 400 КБ загрузки изображения, отчасти потому, что обработка JavaScript происходит при несжатом файле. Байт за байтом, JavaScript дороже, чем любой другой тип файлов для обработки на странице с точки зрения ЦП и времени.Если учесть, что сжатие GZIP может уменьшить размер доставленного текстового файла на 70–90%, 400 КБ действительно превращаются в 1,3–4,0 МБ.
Снижение воздействия JS-доставки
Итак, как мы можем уменьшить время загрузки страницы, связанное с доставкой JavaScript? Есть два способа, для каждого из которых есть лучшие практики:
- Ускорьте загрузку JS в браузере.
- Уменьшите объем JS, который вы используете для создания страницы.
- Минимизируйте все ресурсы JS и используйте минимизированный сторонний JS.
- Самостоятельное размещение стороннего JS (или использование сервис-воркера).
- Сжать JS.
- Используйте push и preload для критического JS.
- Загружайте JS только тогда, когда это необходимо.
- Удалить мертвый код JS.
- Разделение файлов JS для доставки основных компонентов.
- Асинхронная загрузка некритических JS-компонентов.
- Кэш JS.
Мы рассмотрим перечисленные передовые методы для достижения обеих целей, включая рекомендации по стороннему JavaScript, над которым вы, возможно, не имеете большого контроля.
В следующих случаях важно убедиться, что ваша пользовательская база поддерживает реализованные методы браузером. Real User Monitoring позволяет вам увидеть, какие версии наиболее распространены среди ваших пользователей, и их следует считать необходимыми для тестирования любых изменений, которые вы вносите на свой сайт.
Ускорение загрузки JS в браузере
Уменьшите объем JS, который вы используете для создания страницы
Если вы предоставите меньше JavaScript, страница будет загружаться быстрее.
Не знаете, с чего начать? Мы уже знаем, что JS — это самый дорогой вид файлов, используемых для создания вашего сайта, поэтому вы также можете подумать о нем с точки зрения обработки. Для интерактивности на странице рекомендуется использовать JavaScript для функций, которые улучшают взаимодействие с пользователем — ожидаемых переходов, анимации и событий — а не для вещей, которые могут нарушить работу, например ярких, растянутых анимаций.
Существуют ли сторонние фрагменты JavaScript, которые являются избыточными или не важны для того, что вы хотите, чтобы страница делала? Подумайте об их устранении.
Разработчики Google разработали рекомендации, основанные на восприятии пользователями задержек производительности, которые вы можете использовать, чтобы судить о необходимости JS на странице в сочетании с тестированием.
Восприятие пользователем задержек производительности | |
от 0 до 16 мс | Пользователи исключительно хороши в отслеживании движения, и им не нравится, когда анимация не плавная.Они воспринимают анимацию как плавную, если каждую секунду рендерится 60 новых кадров. Это 16 мс на кадр, включая время, необходимое браузеру, чтобы отобразить новый кадр на экране, оставляя приложению около 10 мс для создания кадра. |
от 0 до 100 мс | Отвечайте на действия пользователя в пределах этого временного окна, и пользователи чувствуют, что результат будет немедленным. Если дольше, связь между действием и противодействием нарушается. |
от 100 до 300 мс | У пользователей наблюдается небольшая заметная задержка. |
от 300 до 1000 мс | В этом окне все кажется частью естественного и непрерывного выполнения задач. Для большинства пользователей Интернета загрузка страниц или изменение представлений представляет собой задачу. |
1000 мс или более | По истечении 1000 миллисекунд (1 секунда) пользователи теряют внимание к выполняемой задаче. |
10000 мс или более | При превышении 10000 миллисекунд (10 секунд) пользователи разочаровываются и, скорее всего, бросят задачи.Они могут вернуться, а могут и не вернуться позже. |
Использовать минимизированные файлы JS
Минификация удаляет ненужные знаки препинания, пробелы и символы новой строки. Истинная минификация также использует обфускацию, которая переименовывает переменные в имена, которые требуют меньшего количества байтов данных для чтения браузером, чем имена переменных, удобочитаемые человеком.
В сети есть много инструментов для минификации, не все из которых используют обфускацию. Подумайте, что лучше всего подходит для вашего сайта, и всегда используйте какую-либо форму минификации.Чем меньше байтов данных вы передаете на файл JavaScript, тем быстрее он загружается и тем быстрее браузер сможет его проанализировать.
Самостоятельное размещение стороннего JS, если применимо (или использование сервис-воркера)
Размещение стороннего JavaScript в вашем собственном домене может быть менее удобным в обслуживании — вы не получите автоматических обновлений для скрипта, а изменения в API могут произойти без предупреждения — но это все равно может быть полезно, если скрипт критически важен для рендеринга вашего страница. Сценарий будет использовать вашу сеть и протоколы безопасности, что может привести к лучшим результатам.Вы также можете включать в библиотеки только те компоненты, которые используются в вашем исходном коде (см. «Устранение мертвого кода» ниже).
Альтернативой самостоятельному размещению сторонних скриптов является использование сервис-воркера для определения того, как часто часть контента должна извлекаться из сети, хотя этот вариант может быть не таким доступным, как самостоятельный хостинг для сайтов с устаревшей архитектурой.
Сжатие JS
Сжатие текстовых файлов на стороне сервера может существенно уменьшить размер файла.Этот передаваемый размер JavaScript позволяет загружать больше несжатых данных, чем обычно, устраняя необходимость в дальнейших циклах. Сжатие JavaScript вместе с CSS и другими текстовыми файлами может снизить вес страницы вдвое.
Используйте толчок и предварительную нагрузку для критических JS
Server push и предварительная загрузка могут использоваться для доставки файлов, критически важных для рендеринга страницы, раньше при загрузке страницы, чем обычно.
Файл загружается с помощью push, если указано на стороне сервера — сервер получает запрос и ему заранее сказано, что ресурсы x, y и z должны быть загружены вместе с ним.Примечательно, что методологию push можно использовать только в HTTP / 2.
Preload немного отличается, где связанным ресурсам может быть присвоен атрибут «preload» в файле HTML. Как только страница будет доставлена и пока только начинается синтаксический анализ HTML, эти ресурсы запрашиваются с сервера. Это быстрее, чем обычный анализ HTML, потому что ресурсы затем запрашиваются не в том порядке, в котором они перечислены в HTML.
Загружать JS только тогда, когда это необходимо
Убедитесь, что в каждый файл JavaScript включен только используемый код.Кроме того, вам может не потребоваться загружать каждый файл JavaScript на каждой странице вашего сайта. Для достижения этих целей я расскажу об оптимизации, о которых вам следует знать, и предоставлю ссылки на соответствующие ресурсы.
Устранение мертвого кода при встряхивании дерева
Встряхивание дерева, или устранение мертвого кода, избавляет, как вы уже догадались, от кода, которого нет на вашей странице. Например, предположим, что вы загружаете миниатюрную библиотеку JQuery, но при создании страницы используете только несколько функций, предлагаемых JQuery, в собственном коде.Удаление мертвого кода позволит вам загружать только те части библиотеки JQuery, которые вы используете.
Термин «встряхивание дерева» популяризировал Rollup, который реализует эту функцию, но он также доступен через webpack и source-map-explorer. Примечательно, что эта функция работает только с модулями ES2015, используя синтаксис для ссылки на пакеты JS в других файлах. Если вы используете CommonJS, доступны некоторые параметры, например webpack-common-shake, но при использовании CommonJS вы, скорее всего, столкнетесь с ограничениями.В долгосрочной перспективе, если вы хотите использовать встряхивание деревьев, наиболее полезным будет ES2015 или более поздняя версия.
Доставка основных компонентов с разбиением на фрагменты на основе маршрута или разбиением кода
Блокирование на основе маршрутов, или разделение кода, применяется к веб-сайтам, которые загружают одностраничные приложения, прогрессивные веб-приложения или любую другую платформу, для которой требуется большой пакет JS для создания первой страницы, которую видит пользователь. Использование фрагментов на основе маршрутов позволяет сначала загружать на страницу только необходимые фрагменты пакета JS для первоначального рендеринга и интерактивности, что сокращает общий объем JavaScript, передаваемого для построения страницы, а также время, необходимое для визуализации значимого содержание.
То, как вы определяете, где разделить код, зависит от типа загружаемого приложения, от того, кто ваши пользователи и какова ваша серверная архитектура. Есть несколько типов разделения кода:
- Разделение на поставщика отделяет ваш JS от JS, предоставленного вашим поставщиком фреймворка, например React или Vue. Разделение по поставщику предотвращает перезагрузку более крупного пакета при изменении функции в любом из источников кода. Разделение на поставщиков должно выполняться в каждом веб-приложении.
- Разделение с помощью точек входа разделяет ваш код в зависимости от того, где в вашем коде веб-пакет начинает определять зависимости в вашем приложении.Если ваш сайт не использует маршрутизацию на стороне клиента (например, SPA использует маршрутизацию на стороне клиента), использование точек входа для разделения кода может иметь смысл. При таком разбиении использование такого инструмента, как Bundle Buddy, чтобы гарантировать, что повторяющиеся пакеты не включены в дерево зависимостей, может помочь страницам загружаться быстрее.
- Динамическое разделение кода хорошо работает с приложениями, использующими маршрутизацию на стороне клиента, например одностраничными приложениями, потому что не все пользователи будут использовать все функции на странице. Это можно сделать с помощью динамического оператора
import ()
, который возвращает обещание.По этой причине вы также можете использовать динамический импорт с помощью async / await. Parcel и webpack будут искать динамический операторimport ()
для отложенной загрузки ресурсов по мере необходимости.
Асинхронная загрузка некритических JS-компонентов
Использование атрибутов async
и defer
для внешних сценариев очень важно, особенно со сторонними сценариями. И async
, и defer
являются асинхронными для загрузки и анализа помеченных ими ресурсов.Почему это важно? Для JavaScript поведение по умолчанию для загрузки и анализа сценария является синхронным, что означает, что почти все остальные процессы на странице останавливаются, пока выполняются эти шаги.
Атрибут async
имеет приоритет над defer
в современных браузерах, поскольку современные движки браузеров лучше приспособлены для обработки JavaScript. В старых браузерах все наоборот.
Примечательно, что выполнение JavaScript происходит в одном и том же потоке браузера.JavaScript с пометкой async
всегда будет выполняться до JavaScript с пометкой defer
. Синхронный JavaScript выполняется немедленно, и его следует использовать только для кода, который отображает страницу (и, вероятно, даже не тогда).
Кэш JS
Кэширование может выполняться несколькими способами и связано с некоторыми функциями сервис-воркеров. Кэширование позволяет вам определять правила, по которым браузер должен загружать ресурс с сервера вместо того, чтобы получать его гораздо быстрее, не требуя загрузки из кеша.
Кэшированиеможет существенно сократить время загрузки и стоимость доставки на страницу, и его следует использовать для JavaScript почти в любых обстоятельствах.
Takeaways and TL; DR
Использование функций современных фреймворков делает JavaScript более удобным в обслуживании, чем когда-либо. Хотя на первый взгляд это может показаться запутанным, есть всего несколько целей, к которым стремятся лучшие практики JavaScript:
- Меньшие размеры страницы
- Быстрая доставка
- Более эффективная обработка
В этом посте мы рассмотрим первые два, которые связаны между собой.Меньшие размеры страниц возможны, если вы уменьшите объем кода, который вы доставляете своим пользователям, тем самым доставляя их быстрее.
TL; DR- Устранение ненужного JavaScript, минимизация и сжатие JavaScript, встряхивание дерева и разделение кода — все это снижает объем JavaScript, доставляемого на страницу.
- Доставка ресурсов с помощью сервис-воркера и использование кэширования может дополнительно контролировать, загружается ли JavaScript на страницу.
- Асинхронная загрузка скриптов с предварительной загрузкой и принудительной загрузкой критического JavaScript также позволяет странице загружаться быстрее.
Как всегда, не забудьте протестировать любые изменения, прежде чем внедрять их, а затем посмотрите, как они влияют на вашу пользовательскую базу с помощью реального мониторинга пользователей. И вернитесь к следующему посту, в котором будет рассказано о третьей цели производительности JavaScript — более эффективной обработке JavaScript.
<<< Часть 1: Как оптимизировать изображения для повышения производительности в Интернете
<< Часть 2: Как оптимизировать CSS для повышения производительности в Интернете
<Часть 3: Как оптимизировать HTML для повышения производительности сети
Как оптимизировать производительность JavaScript — Stackify
JavaScript — это общий язык в разработке мобильных и веб-приложений.Из-за своей популярности оптимизация JavaScript становится все более необходимой для повышения производительности приложений. Давайте узнаем о некоторых проблемах, связанных с JavaScript, и о том, как оптимизировать производительность js.
Типичные проблемы производительности js
Существует ряд проблем, которые могут повлиять на производительность JavaScript. Вот общие проблемы, связанные с производительностью js:
Обработка событий низкого качества :Правильное использование обработчиков событий может повысить производительность JavaScript за счет уменьшения глубины стека вызовов.
Важно отслеживать все обработчики событий, чтобы обработчики не работали без вашего ведома.
Неорганизованный кодJavaScript нечеткий, что является одновременно плюсом и минусом.
Мелкие подмножества лексических конструкций позволяют разработчикам добиться многого. Однако отсутствие организации в коде может привести к недостаточному распределению ресурсов.
Это может сильно снизить производительность JavaScript .Понимание ECMA важно для понимания JavaScript. .
Слишком много зависимостейИногда зависимости JavaScript плохо управляются или чрезмерны. Когда это произойдет, это отрицательно скажется на производительности приложения.
Например, мобильные пользователи с ограниченной пропускной способностью должны будут дольше ждать визуализированных объектов.
Неэффективные итерацииОбработка итераций занимает много времени. Однако это тоже полезно.Длительное время обработки создает идеальную отправную точку для оптимизации JavaScript. По мере исправления нерелевантных вызовов или циклов в коде производительность JavaScript значительно улучшится.
Советы по оптимизации производительности js Обрезка HTMLJavaScript HTML сложен и играет решающую роль во времени запросов для запросов и изменения объектов DOM.
Если вдвое сократить HTML-код приложения, можно вдвое увеличить скорость DOM.Это может быть сложно, но это возможно, если отказаться от таких тегов, как
Пакетирование преобразований DOM для предотвращения повторяющихся отображений экрана. При изменении стиля вносите все изменения сразу, а не применяйте изменения к каждому стилю по отдельности.
Изучение методов асинхронного программированияПриложениям JavaScript требуется множество внутренних вызовов многочисленных API для выборки данных.
Промежуточное ПО необходимо для каждой функции, потому что JavaScript является однопоточным.
Синхронные компоненты иногда могут блокировать все приложение. JavaScript управляет асинхронным кодом с помощью async.js.
Асинхронный код не блокирует поток. Вместо этого угроза попадает в очередь событий, которая срабатывает после выполнения других кодов.
С помощью асинхронных функций JavaScript можно непреднамеренно использовать внешнюю библиотеку для возврата к асинхронным вызовам с подавлением вызовов.
Это может снизить производительность JavaScript . Вместо этого используйте в коде асинхронные API-интерфейсы, особенно в критически важных разделах производительности.
Использование сжатия gzipФайлы JavaScript могут быть огромными. Используйте GZip для распаковки и сжатия файлов. GZip уменьшает время задержки, повышает производительность приложений и экономит полосу пропускания. С помощью GZip сервер сжимает ресурс перед его отправкой в браузер.
Использовать HTTP / 2Последней версией HTTP является HTTP / 2 с улучшениями для повышения производительности JavaScript и для повышения производительности веб-сайтов.
HTTP / 2 использует мультиплексирование и позволяет одновременно отправлять несколько ответов и запросов. Буферизация DOM
Если есть прокручиваемые DIV, можно использовать буфер, чтобы избавиться от элементов DOM, которые в настоящее время не видны в области просмотра. Эти методы позволяют сэкономить как на обходе DOM, так и на использовании памяти.
Ограничить зависимости библиотекВремя загрузки может повлиять на зависимости библиотек, поэтому важно свести использование к минимуму.
Лучший способ избавиться от зависимостей внешних библиотек — это использовать встроенные в браузер технологии.
При использовании селекторов CSS используйте Sizzle.js вместо jQuery. Когда библиотеки представляют собой одну функцию, жизненно важно добавлять селекторы CSS отдельно.
Сохранение компактности и легкости кодовСохранение компактности кода JavaScript снизит задержку и повысит производительность. При оптимизации производительности JavaScript спросите себя:
- Существует ли реальная потребность в этом модуле?
- В чем причина использования этого фреймворка?
- Стоят ли накладные расходы?
- Есть способ сделать это попроще?
Оптимизация производительности JavaScript путем преобразования нескольких файлов JS в один.
Реализация инструментов управления производительностью приложений для js Производительность:Когда дело доходит до оптимизации производительности JavaScript, важно использовать инструмент управления производительностью приложений. Инструменты управления производительностью приложений, такие как Retrace, поставляются с Real User Monitoring (RUM). RUM ускоряет веб-производительность, позволяя одновременно отслеживать внешний и внутренний код. Такой более комплексный подход упрощает выявление узких мест и позволяет лучше определить правильное решение.По мере оптимизации производительности веб-страницы веб-страницы реагируют быстрее и становятся более интерактивными. Конечные пользователи довольны, становятся более заинтересованными и, в конечном итоге, с большей вероятностью совершат покупку.
РУМ включает разбивки по ресурсам. Разбивка ресурсов помогает определить, нужно ли оптимизировать изображения, минимизировать или кэшировать таблицы стилей и скрипты. Функциональность сегментации RUM позволяет получить более глубокое понимание. Используйте сегментацию для отслеживания времени загрузки в зависимости от браузера, географии и типа устройства. Это упрощает определение возможностей для улучшения общего опыта за счет определения оптимальных местоположений для сетей CDN.Попробуйте бесплатную 14-дневную пробную версию Retrace RUM сегодня.
Как настроить автоматическую оптимизацию для вашего сайта WordPress
Autoptimize — это бесплатный плагин для оптимизации WordPress. Помимо оптимизации HTML, CSS и JavaScript, Autoptimize также включает функции оптимизации, ориентированные на другие аспекты современных сайтов WordPress.
В этом посте мы расскажем о лучших настройках плагина Autoptimize для повышения производительности и скорости страницы вашего сайта WordPress.
Зачем нужна автоматическая оптимизация?
Прежде чем мы углубимся в лучшие настройки автоматической оптимизации, давайте быстро рассмотрим три причины, по которым Autoptimize является отличным плагином для оптимизации.
- Бесплатная версия Autoptimize имеет полный набор функций для оптимизации вашего сайта WordPress.
- Autoptimize — это строго плагин оптимизации и не выполняет кэширование HTML-страниц. Это означает, что он совместим со всеми веб-хостами — даже с настраиваемыми конфигурациями кеширования страниц, такими как Kinsta.
- Autoptimize имеет более 1 миллиона активных установок в репозитории WordPress и постоянно обновляется новыми функциями и исправлениями ошибок.
Автоматическая оптимизация настроек JS, CSS и HTML
HTML, CSS и JavaScript — это хлеб с маслом для Autoptimize.Как и в случае с другими плагинами оптимизации, изучение обширного набора функций и настроек Autoptimize может оказаться непростой задачей. Чтобы упростить задачу, мы собрали лучшие настройки автоматической оптимизации для повышения производительности вашего сайта.
Параметры JavaScript
Оптимизация JavaScript в Autoptimize.
Оптимизация кода JavaScript
Мы рекомендуем включить эту опцию. Когда включена «оптимизация кода JavaScript», функция Autoptimize минимизирует ваши файлы JavaScript.
Совокупные файлы JS
ОпцияAutoptimize «агрегировать файлы JS» объединит все ваши файлы JavaScript в один файл.В прошлом объединение файлов JS и CSS было ключевым шагом в оптимизации WordPress. В Kinsta мы используем современные серверы HTTP / 2, которые поддерживают параллельную загрузку и мультиплексирование — это означает, что объединение файлов уже не так важно, как раньше, потому что HTTP / 2 позволяет загружать несколько файлов одновременно. С учетом сказанного, агрегирование файлов CSS и JS по-прежнему будет приводить к увеличению скорости для определенных типов сайтов WordPress, поэтому мы рекомендуем проверить скорость вашей страницы с включенной и отключенной этой опцией.
Также агрегатировать встроенный JS
Параметр «также агрегировать встроенный JS» извлекает встроенный JS в ваш HTML и объединяет его с оптимизированным файлом JS Autoptimize. Поскольку этот параметр может привести к быстрому увеличению размера кэша автоптимизации, мы рекомендуем оставить этот параметр отключенным, если у вас нет особых причин для его включения.
Принудительно использовать JavaScript в
В большинстве случаев мы не рекомендуем принудительно загружать файлы JavaScript в элемент HTML
вашего сайта.Принуждение к ранней загрузке JS может привести к элементам, блокирующим рендеринг, которые могут замедлить скорость вашей страницы. Если у вас есть файлы JavaScript, которые необходимо загрузить в элемент
, мы рекомендуем исключить эти сценарии из Autoptimize.
Исключить сценарии из автоматической оптимизации
Этот параметр позволяет исключить определенные каталоги и файлы JavaScript из агрегирования. По умолчанию Autoptimize исключает следующие сценарии.
- wp-включает / js / dist /
- wp-включает / js / tinymce /
- js / jquery / jquery.js
Обратите внимание, что добавление сценария для исключения влияет только на агрегирование по умолчанию. Исключенные файлы JavaScript будут по-прежнему минимизированы, если только «минимизировать исключенные файлы CSS и JS» не будет снят флажок в разделе «Разные параметры».
Добавить упаковку Try-Catch
При включении опции «добавить упаковку try-catch» ваш код JavaScript будет заключен в блоки try-catch. Эта опция полезна для отладки проблем, вызванных минификацией и агрегацией JS. Если ваш сайт работает только с включенной функцией «добавить упаковку try-catch», мы рекомендуем работать с разработчиком, чтобы просмотреть ваши файлы JavaScript, чтобы определить тот, который вызывает проблему, поскольку чрезмерное использование блоков try-catch может снизить производительность JS.
Autoptimize: бесплатный плагин для оптимизации WordPress, о котором вы не знали … но он сделает ваш сайт молниеносным ⚡️Это руководство точно объясняет, зачем вам это нужно 🚀Нажмите, чтобы твитнутьПараметры CSS
Автоматическая оптимизация CSS.
Оптимизация кода CSS
Мы рекомендуем включить эту опцию. Когда включена «оптимизация кода CSS», функция Autoptimize минимизирует ваши файлы CSS.
Совокупные файлы CSS
Параметр «агрегировать файлы CSS» вAutoptimize объединит все ваши файлы CSS в один файл.Как мы упоминали ранее, эта функция может не принести пользу сайтам, поддерживающим HTTP / 2. Мы рекомендуем A / B-тестирование этой опции на вашем сайте, чтобы определить, оказывает ли какое-либо положительное влияние на скорость страницы.
Также объединить встроенный CSS
Этот параметр переместит встроенный CSS в файл CSS автоптимизации. Хотя перемещение встроенного CSS в файл CSS с возможностью кеширования в браузере может уменьшить размер страницы, мы рекомендуем в большинстве случаев оставлять этот параметр отключенным.
Создание данных: URI для изображений
Когда эта опция включена, Autoptimize будет кодировать в base64 небольшие фоновые изображения и вставлять их в CSS.Мы рекомендуем протестировать эту опцию, чтобы оценить влияние на скорость вашей страницы. Хотя кодирование изображений в формат base64 снижает количество HTTP-запросов, файлы представлений base64 обычно на 20-30% больше, чем их двоичные аналоги.
Встроенный и отложенный CSS
Встраивание критического CSS может привести к значительному увеличению скорости для некоторых сайтов. Идея здесь в встроенных стилях, которые требуются для элементов, находящихся «над сгибом». На практике встроенный CSS обычно нацелен на такие элементы, как структурные элементы, глобальные семейства и размеры шрифтов, а также стили навигации.
Встраивая эти ключевые элементы, можно загрузить более крупный полный CSS-файл позже, не влияя на внешний вид страницы. Хотя критические стили можно извлекать вручную, мы рекомендуем использовать такой инструмент для создания стилей в качестве отправной точки.
Сгенерируйте критический CSS.
После создания критического CSS скопируйте и вставьте его в настройки автоптимизации.
Встроить и отложить CSS в Autoptimize.
Следующим шагом будет проверка интерфейса вашего сайта.Если вы заметили какие-то странные вспышки нестилизованного содержимого (FOUC), вам, вероятно, потребуется идентифицировать эти нестилированные элементы и добавить соответствующие стили в Autoptimize для встраивания.
Autoptimize предлагает «усиление», которое автоматически генерирует критический CSS для ваших страниц WordPress. По нашему опыту, эта функция может иногда замедлять работу вашего сайта, поскольку использует внешние вызовы API для генерации критически важного CSS. Таким образом, начальная критическая генерация CSS зависит от скорости отклика внешнего сервера.В большинстве случаев вышеупомянутый метод, который не требует каких-либо внешних вызовов API, является более чистым решением.
Встроить все CSS
Для большинства сайтов мы не рекомендуем встраивать весь CSS, так как это может значительно увеличить размер страницы. Кроме того, встраивание всего CSS делает невозможным кэширование CSS в веб-браузере.
Исключить CSS из автоматической оптимизации
По умолчанию Autoptimize исключает следующие каталоги и файлы CSS из агрегирования. Если вы хотите, чтобы функция Autoptimize не объединяла какие-либо из ваших файлов CSS, вы можете добавить их в этот список.Подобно исключению JavaScript, поведение этой функции по умолчанию не препятствует минификации файлов CSS, а только агрегированию.
- WP-контент / кеш /
- WP-контент / загрузки /
- админ-bar.min.css
- dashicons.min.css
Параметры HTML
Оптимизация HTMLAutoptimize может помочь уменьшить размер ваших страниц за счет удаления пробелов.
Оптимизация HTML в Autoptimize.
Оптимизировать HTML-код
Мы рекомендуем включить функцию «оптимизировать HTML», поскольку она уменьшает размер страницы за счет удаления ненужных пробелов в HTML.Хотя эта функция совместима с большинством сайтов, удаление пробелов может вызвать сбои на некоторых сайтах. Таким образом, мы рекомендуем тщательно протестировать оптимизацию HTML-кода, прежде чем использовать ее в производственной среде.
Подпишитесь на информационный бюллетень
Мы увеличили наш трафик на 1187% с помощью WordPress.
Присоединяйтесь к 20 000+ другим, кто получает нашу еженедельную рассылку с инсайдерскими советами по WordPress!
Подпишитесь сейчасСохранить комментарии HTML
Включите эту функцию, если вы хотите сохранять комментарии HTML для своих оптимизированных страниц.
Опции CDN
Если вы используете CDN, например KinstaCDN, для ускорения статических ресурсов, вам необходимо добавить URL-адрес CDN в Autoptimize. Если вы используете прокси-сервис с возможностями CDN, например Cloudflare, вам не нужно ничего настраивать в параметрах CDN Autoptimize.
Настройте параметры CDN в Autoptimize.
Информация о кэше
«Информация о кеше»Autoptimize отображает важную информацию, такую как расположение и права доступа к папке с кешем, а также общий размер кэшированных стилей и скриптов.Если вы видите «Нет» рядом с «Можем ли мы написать?», Вам нужно будет обратиться к своему хосту, чтобы исправить разрешения для папки.
Автоматическая оптимизация кеша.
Разные параметры
Autoptimize имеет несколько различных настроек оптимизации. Если у вас возникают проблемы с загрузкой оптимизированных файлов CSS и JS на ваш сайт, возможно, вам придется изменить некоторые настройки, указанные ниже.
Разные оптимизации в Autoptimize.
Сохранить агрегированные скрипты / CSS как статические файлы
Мы рекомендуем включить этот параметр, чтобы сохранять агрегированные файлы как статические файлы локально.Вам может потребоваться отключить это, если ваш сервер не настроен для обработки сжатия и истечения срока действия файлов.
Сократить исключенные файлы CSS и JS
Мы рекомендуем включить этот параметр, чтобы все файлы CSS и JS были минимизированы. Однако, если вы заметили некоторые проблемы, связанные с минимизацией, в некоторых исключенных файлах CSS и JS, вы можете отключить эту опцию.
Также оптимизировать для зарегистрированных редакторов / администраторов
Мы рекомендуем включить это, чтобы гарантировать, что ресурсы оптимизированы для авторизованных редакторов и администраторов.Это важно, если вы тестируете параметры автоматической оптимизации как зарегистрированный пользователь.
Оптимизация изображения в Autoptimize
Autoptimize имеет встроенную интеграцию с ShortPixel для оптимизации изображений. В дополнение к настройке качества изображения интеграция Autoptimize также позволяет вам создавать и обслуживать версии ваших изображений WEBP.
Для пользователей Kinsta мы не рекомендуем использовать функцию оптимизации изображения в Autoptimize. Вместо этого мы рекомендуем напрямую использовать полнофункциональные плагины от ShortPixel или Imagify.С полным плагином у вас будет более детальный контроль над настройками оптимизации, включая перезапись изображений для использования тега
, который необходим для поддержки WEBP на Kinsta.
Изображения с отложенной загрузкой с функцией автоматической оптимизации.
Autoptimize также включает функцию отложенной загрузки изображений. Мы рекомендуем включить эту функцию, чтобы повысить скорость загрузки страниц с большим количеством изображений. Когда включена отложенная загрузка, Autoptimize позволяет исключить определенные классы изображений и имена файлов из отложенной загрузки.
Параметр исключения полезен для изображений, таких как логотипы, значки социальных сетей и других важных элементов изображения, которые не следует загружать лениво. Если вы ищете решение, которое предлагает больший контроль над отложенной загрузкой, ознакомьтесь с нашим руководством по отложенной загрузке изображений и видео в WordPress.
Дополнительные оптимизации в Autoptimize
Дополнительные оптимизации в Autoptimize.
Google Шрифты
Autoptimize имеет несколько различных вариантов оптимизации шрифтов Google.Лучший вариант для вас будет зависеть от того, как ваш сайт использует шрифты Google.
- Оставить как есть.
- Удалить шрифты Google.
- Скомбинировать и связать в голове.
- Комбинирование и предварительная нагрузка в головке.
- Асинхронно комбинируйте и загружайте шрифты с webfont.js.
Не рекомендуется использовать параметр «оставить как есть», поскольку он не дает преимущества в скорости.
Если шрифты Google Fonts не являются критически важным требованием для вашего сайта, их удаление и использование вместо них системного стека шрифтов может иметь огромное положительное влияние на скорость вашей страницы.
Если вы хотите сохранить шрифты Google на своем сайте, мы рекомендуем протестировать последние три варианта, чтобы определить, какой из них лучше всего подходит для вашего сайта.
Удалить смайлы
Эта опция автоматической оптимизации удаляет CSS и JavaScript, связанные с основными смайликами WordPress. Мы рекомендуем включить этот параметр, поскольку он помогает уменьшить размер страницы. Кроме того, большинство основных операционных систем поставляются со стеками шрифтов, которые включают смайлики. Конечно, есть и другие способы отключить эмодзи на вашем сайте WordPress.
Удалить строки запроса из статических ресурсов
Если вы хотите удалить строки запроса (например,? Ver =) из статических ресурсов, вы можете включить эту опцию. Удаление строк запроса не повлияет на время загрузки, но может помочь улучшить оценку вашего сайта в GTmetrix, Google Pagespeed и других службах тестирования производительности.
Предварительное подключение к сторонним доменам
Директива preconnect позволяет вашему браузеру подключаться к указанным доменам для обработки DNS-запросов и согласования SSL-подтверждения перед отправкой полного HTTP-запроса.
Например, если на вашем сайте есть изображение логотипа, которое обслуживается с https://site.kinsta.cdn.com/logo.png
, вы можете указать Autoptimize добавить директиву preconnect для обработки начальных подключений DNS и SSL в элемент
перед выполнением HTTP-запроса в элементе
вашего HTML.
Вы можете использовать инструменты разработчика или инспектор вашего браузера, чтобы найти важные внешние домены для предварительного подключения. На приведенной ниже странице примера есть внешние запросы к следующим доменам.
-
https://cdn.brianli.com
-
https://www.google-analytics.com
-
https://www.googletagmanager.com
Эти три домена можно добавить в список предварительного подключения Autoptimize.
Найдите внешние ресурсы с помощью инструментов разработчика.
По соображениям производительности мы рекомендуем добавлять не более шести доменов в список предварительного подключения Autoptimize, поскольку указание директив предварительного подключения для слишком большого количества доменов может привести к снижению производительности.
Предварительная загрузка специальных запросов
ДирективыPreload предписывают вашему веб-браузеру как можно скорее загрузить ресурс. Эта директива полезна для загрузки ресурсов, которые необходимы в самом начале процесса загрузки страницы. На практике предварительная загрузка часто используется для ускорения загрузки пользовательских шрифтов, загружая их до того, как они будут запрошены в CSS страницы.
Мы рекомендуем проконсультироваться с разработчиком относительно того, какие активы, если таковые имеются, предварительно загрузить на ваш сайт WordPress.Как и в случае со многими другими настройками, связанными с производительностью, предварительная загрузка слишком большого количества ресурсов может замедлить загрузку вашего сайта.
Асинхронные файлы JavaScript
Функция «асинхронные файлы JavaScript» в Autoptimize позволяет указать определенные внешние файлы JavaScript для асинхронной загрузки с помощью флага async
HTML. Хотя асинхронная загрузка файлов JS может повысить скорость загрузки страниц, мы рекомендуем провести соответствующее тестирование, чтобы убедиться, что это не влияет на работу сайта.
Сводка
Если вы знаете, как настроить его параметры, плагин Autoptimize — надежный вариант для пользователей WordPress, которые хотят повысить производительность сайта.
Обладая базовыми функциями, такими как оптимизация HTML и CSS, и более продвинутыми, такими как интеграция с CDN и возможностью указывать директивы preconnect и preload, Autoptimize имеет все необходимое для оптимизации производительности внешнего интерфейса вашего сайта WordPress.
Если вы хотите узнать больше об оптимизации WordPress и о том, как оптимизировать серверную часть своего сайта, обязательно ознакомьтесь с нашим подробным руководством по производительности WordPress.
Если вам понравилась эта статья, то вам понравится хостинговая платформа Kinsta WordPress.Ускорьте свой сайт и получите круглосуточную поддержку от нашей опытной команды WordPress. Наша инфраструктура на базе Google Cloud ориентирована на автоматическое масштабирование, производительность и безопасность. Позвольте нам показать вам разницу в Kinsta! Ознакомьтесь с нашими тарифами
Основные функции: Оптимизация изображения | Next.js
ПримерыНачиная с версии 10.0.0 , Next.js имеет встроенный компонент изображения и автоматическую оптимизацию изображения.
Компонент изображения Next.js, next / image
, является расширением элемента HTML
, разработанного для современной сети.
Автоматическая оптимизация изображений позволяет изменять размер, оптимизировать и обслуживать изображения в современных форматах, таких как WebP, если браузер поддерживает это. Это позволяет избежать отправки больших изображений на устройства с меньшим окном просмотра. Он также позволяет Next.js автоматически принимать будущие форматы изображений и передавать их браузерам, поддерживающим эти форматы.
Автоматическая оптимизация изображения работает с любым источником изображения. Даже если изображение размещено во внешнем источнике данных, таком как CMS, его все равно можно оптимизировать.
Вместо оптимизации изображений во время сборки Next.js оптимизирует изображения по запросу, когда их запрашивают пользователи. В отличие от генераторов статических сайтов и статических решений, время сборки не увеличивается, независимо от того, отправлено ли 10 изображений или 10 миллионов изображений.
По умолчанию изображения загружаются лениво. Это означает, что скорость вашей страницы не снижается для изображений за пределами области просмотра. Изображения загружаются по мере их прокрутки в окне просмотра.
Изображения всегда обрабатываются таким образом, чтобы избежать кумулятивного сдвига макета, ключевого элемента сети, который Google собирается использовать для ранжирования в поиске.
Чтобы добавить изображение в приложение, импортируйте компонент next / image
:
импорт изображения из 'next / image'
function Home () {
возвращаться (
<>
Моя домашняя страница
<Изображение
src = "/ me.png"
alt = "Изображение автора"
ширина = {500}
высота = {500}
/>
Добро пожаловать на мою домашнюю страницу!
>
)
}
экспорт по умолчанию домой
Просмотр всех свойств, доступных для компонента next / image
.
В дополнение к использованию свойств, доступных для компонента next / image
, вы можете дополнительно настроить оптимизацию изображения для более сложных случаев использования через next.config.js
.
Домены
Чтобы включить оптимизацию изображений для изображений, размещенных на внешнем веб-сайте, используйте абсолютный URL-адрес для изображения src
и укажите, какой доменов
разрешено оптимизировать. Это необходимо для предотвращения злоупотреблений внешними URL-адресами. Когда загрузчик
настроен на внешний сервис изображений, этот параметр игнорируется.
module.exports = {
изображений: {
домены: ['example.com'],
},
}
Погрузчик
Если вы хотите использовать облачного провайдера для оптимизации изображений вместо использования встроенной в Next.js оптимизации изображений, вы можете настроить загрузчик и префикс пути. Это позволяет использовать относительные URL-адреса для Image src
и автоматически генерировать правильный абсолютный URL-адрес для вашего провайдера.
module.exports = {
изображений: {
загрузчик: 'imgix',
путь: 'https: // example.com / myaccount / ',
},
}
Включены следующие облачные провайдеры для оптимизации изображений:
- Vercel: работает автоматически при развертывании на Vercel, настройка не требуется. Узнать больше
- Imgix:
загрузчик: imgix
- Cloudinary:
загрузчик: cloudinary
- Akamai:
погрузчик: 'akamai'
- По умолчанию: автоматически работает с
next dev
,next start
или настраиваемым сервером
Если вам нужен другой провайдер, вы можете использовать загрузчик
prop с next / image
.
Загрузчик по умолчанию для компонента
next / image
не поддерживается при использованииnext export
. Однако подойдут и другие варианты загрузчика.
Ниже описан алгоритм кэширования для загрузчика по умолчанию. Для всех остальных загрузчиков обратитесь к документации вашего облачного провайдера.
Изображения оптимизируются динамически по запросу и сохраняются в каталоге
. Оптимизированный файл изображения будет использоваться для последующих запросов, пока не истечет срок его действия.Когда делается запрос, соответствующий кэшированному, но просроченному файлу, кешированный файл удаляется перед созданием нового оптимизированного изображения и кэшированием нового файла.
Срок действия (или, скорее, максимальный возраст) определяется заголовком Cache-Control
вышестоящего сервера.
Если s-maxage
находится в Cache-Control
, он используется. Если s-maxage
не найден, используется max-age
. Если max-age
не найден, используется 60 секунд.
Вы можете настроить deviceSizes
и imageSizes
, чтобы уменьшить общее количество возможных сгенерированных изображений.
Следующая конфигурация предназначена для расширенных вариантов использования и обычно не требуется. Если вы решите настроить указанные ниже свойства, вы переопределите любые изменения значений по умолчанию для Next.js в будущих обновлениях.
Размеры устройства
В некоторых случаях, когда вы знаете ожидаемую ширину устройства от пользователей вашего веб-сайта, вы можете указать список контрольных точек ширины устройства с помощью свойства deviceSizes
.Эти значения ширины используются, когда компонент next / image
использует layout = "responsive"
или layout = "fill"
, чтобы на устройстве, посещающем ваш веб-сайт, показывалось правильное изображение.
Если конфигурация не указана, используется значение по умолчанию, указанное ниже.
module.exports = {
изображений: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
},
}
Размеры изображения
Список ширины изображения можно указать с помощью свойства imageSizes
.Эти значения должны отличаться (обычно меньше) от значений, определенных в параметре deviceSizes
, поскольку массивы будут объединены. Эти значения ширины используются, когда компонент next / image
использует layout = "fixed"
или layout = "intrinsic"
.
Если конфигурация не указана, используется значение по умолчанию, указанное ниже.
module.exports = {
изображений: {
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
Для получения дополнительной информации о дальнейших действиях мы рекомендуем следующие разделы:
Оптимизировать · Bootstrap v5.0
Lean Sass импорт
При использовании Sass в конвейере ресурсов убедитесь, что вы оптимизировали Bootstrap, добавив только @import
необходимых вам компонентов. Ваши самые большие оптимизации, вероятно, будут происходить из раздела Layout & Components
нашего bootstrap.scss
.
// Конфигурация
@import "функции";
@import "переменные";
@import "миксины";
@import "коммунальные услуги";
// Макет и компоненты
@import "корень";
@import "перезагрузка";
@import "тип";
@import "изображения";
@import "контейнеры";
@import "сетка";
@import "таблицы";
@import "формы";
@import "кнопки";
@import "переходы";
@import "выпадающий список";
@import "группа кнопок";
@import "nav";
@import "навигационная панель";
@import "карта";
@import "аккордеон";
@import "хлебные крошки";
@import "разбивка на страницы";
@import "значок";
@import "предупреждение";
@import "прогресс";
@import "список-группа";
@import "закрыть";
@import "тосты";
@import "модальный";
@import "подсказка";
@import "всплывающее окно";
@import "карусель";
@import "блесны";
@import "offcanvas";
// Помощники
@import "помощники";
// Утилиты
@import "утилиты / api";
Если вы не используете компонент, закомментируйте его или удалите полностью.Например, если вы не используете карусель, удалите этот импорт, чтобы сохранить некоторый размер файла в скомпилированном CSS. Имейте в виду, что между импортом Sass есть некоторые зависимости, которые могут затруднить пропуск файла.
Lean JavaScript
JavaScript Bootstrap включает все компоненты в наших основных файлах dist ( bootstrap.js
и bootstrap.min.js
) и даже нашу основную зависимость (Popper) с нашими файлами пакетов ( bootstrap.bundle.js
и bootstrap. .bundle.min.js
). Пока вы настраиваете с помощью Sass, не забудьте удалить связанный JavaScript.
Например, если вы используете собственный пакет JavaScript, такой как Webpack или Rollup, вы должны импортировать только тот JavaScript, который планируете использовать. В приведенном ниже примере мы показываем, как просто включить наш модальный JavaScript:
// Импортируйте именно то, что нам нужно
// импортируем 'bootstrap / js / dist / alert';
// импортируем 'bootstrap / js / dist / button';
// импортируем 'bootstrap / js / dist / carousel';
// импортируем 'bootstrap / js / dist / collapse';
// импортируем 'bootstrap / js / dist / dropdown';
импортировать 'bootstrap / js / dist / modal';
// импортируем 'bootstrap / js / dist / popover';
// импортируем 'bootstrap / js / dist / scrollspy';
// импортируем 'bootstrap / js / dist / tab';
// импортируем 'bootstrap / js / dist / toast';
// импортируем 'bootstrap / js / dist / tooltip';
Таким образом, вы не включаете JavaScript, который не собираетесь использовать для таких компонентов, как кнопки, карусели и всплывающие подсказки.Если вы импортируете раскрывающиеся списки, всплывающие подсказки или всплывающие окна, обязательно укажите зависимость Popper в файле package.json
.
Экспорт по умолчанию
Файлы в bootstrap / js / dist
используют экспорт по умолчанию , поэтому, если вы хотите использовать один из них, вам нужно сделать следующее:
импорт модального окна из bootstrap / js / dist / modal
const modal = новый модальный (document.getElementById ('myModal'))
Автопрефиксатор .browserslistrc
Bootstrap зависит от Autoprefixer для автоматического добавления префиксов браузера к определенным свойствам CSS.Префиксы продиктованы нашим файлом .browserslistrc
, который находится в корне репозитория Bootstrap. Настройка этого списка браузеров и перекомпиляция Sass автоматически удалит часть CSS из вашего скомпилированного CSS, если есть префиксы поставщика, уникальные для этого браузера или версии.
Неиспользуемый CSS
Требуется помощь с этим разделом, рассмотрите возможность открытия PR. Спасибо!
Хотя у нас нет готового примера использования PurgeCSS с Bootstrap, есть несколько полезных статей и пошаговых руководств, написанных сообществом.Вот несколько вариантов:
Наконец, в этой статье CSS Tricks о неиспользуемом CSS показано, как использовать PurgeCSS и другие подобные инструменты.
Minify и gzip
По возможности обязательно сжимайте весь код, который вы показываете своим посетителям. Если вы используете файлы дистрибутива Bootstrap, постарайтесь придерживаться минимизированных версий (обозначенных расширениями .min.css
и .min.js
). Если вы собираете Bootstrap из исходного кода с помощью собственной системы сборки, обязательно реализуйте собственные минификаторы для HTML, CSS и JS.
Неблокирующие файлы
Хотя минимизация и использование сжатия может показаться достаточным, создание неблокирующих файлов для ваших файлов также является большим шагом к тому, чтобы ваш сайт был хорошо оптимизирован и достаточно быстрым.
Если вы используете плагин Lighthouse в Google Chrome, возможно, вы наткнулись на FCP. Метрика First Contentful Paint измеряет время с момента начала загрузки страницы до отображения на экране любой части содержимого страницы.
Вы можете улучшить FCP, отложив некритичный JavaScript или CSS.Что это обозначает? Просто JavaScript или таблицы стилей, которые не должны присутствовать при первом отрисовке вашей страницы, должны быть помечены атрибутами async
или defer
.
Это гарантирует, что менее важные ресурсы загружаются позже и не блокируют первую отрисовку. С другой стороны, критически важные ресурсы могут быть включены в виде встроенных скриптов или стилей.
Если вы хотите узнать об этом больше, об этом уже есть много отличных статей:
Всегда использовать HTTPS
Ваш веб-сайт должен быть доступен только через HTTPS-соединения в рабочей среде.HTTPS улучшает безопасность, конфиденциальность и доступность всех сайтов, и нет такой вещи, как нечувствительный веб-трафик. Шаги по настройке вашего веб-сайта для обслуживания исключительно через HTTPS сильно различаются в зависимости от вашей архитектуры и провайдера веб-хостинга и, таким образом, выходят за рамки этих документов.
Сайты, обслуживаемые по HTTPS, также должны иметь доступ ко всем таблицам стилей, скриптам и другим ресурсам через HTTPS-соединения. В противном случае вы отправите пользователям смешанный активный контент, что приведет к потенциальным уязвимостям, при которых сайт может быть взломан путем изменения зависимости.Это может привести к проблемам с безопасностью и отображению предупреждений в браузере для пользователей. Независимо от того, получаете ли вы Bootstrap из CDN или обслуживаете его самостоятельно, убедитесь, что вы получаете доступ к нему только через HTTPS-соединения.
.