Статьи

Экономия пропускной способности на медленных соединениях с Saveba.js

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

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

Проблема

Когда люди говорят о производительности, обсуждение всегда заканчивается мобильностью. Безусловно, веб-сайт должен быть оптимизирован для любого устройства и соединения, но часто домашние и офисные соединения выполняются быстрее, чем мобильные. Некоторые из наиболее распространенных методов оптимизации веб-сайта сегодня — это объединение и минимизация файлов CSS и JavaScript, асинхронная загрузка файлов JavaScript, предоставление современных форматов шрифтов (WOFF и WOFF2), оптимизация для критического пути рендеринга и т. Д.

Другая важная концепция, которую необходимо учитывать, — это оптимизация изображений. На основании последнего отчета HTTPArchive изображения составляют в среднем более 60% от общего веса страницы . Чтобы решить эту проблему, многие разработчики используют инструменты, такие как Grunt или Gulp, или сервисы, такие как TinyPNG или JPEGMini , чтобы уменьшить их вес. Другой практикой является использование нового атрибута srcsetpicture Но этого недостаточно.

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

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

Я хотел выразить то, что, если у пользователя действительно очень медленное соединение, он / она, возможно, не заботится о некоторых изображениях или ресурсах в целом и хочет сосредоточиться на том, что действительно имеет значение. Рассмотрим следующие изображения, представляющие текущую версию моего веб-сайта на Samsung Galaxy S3:

A screenshot of the Aurelio De Rosa's website as seen on a Samsung Galaxy S3

На этом скриншоте я пометил красной рамкой два изображения: логотип и мое изображение. Теперь возникает вопрос: «Заботится ли пользователь с подключением 2G об этих изображениях, даже если они сильно оптимизированы?» Не удивительно, что ответ «Нет!» Так что, даже если я могу оптимизировать эти изображения для небольших устройств, что мне действительно нужно, так это полностью избежать загрузки для пользователей, имеющих данный тип соединения или набор соединений, таких как GPRS, EDGE и UMTS. С другой стороны, я хочу показать эти изображения пользователям, посещающим мой сайт на небольшом устройстве, использующем быстрое соединение. Моя попытка решить эту проблему закончилась созданием Saveba.js.

Представляем Saveba.js

Saveba.js — это библиотека JavaScript, которая, опираясь на API-интерфейс Network Information , пытается сэкономить пропускную способность для пользователей с медленным подключением, удаляя ненужные ресурсы (на данный момент только изображения). Под «удалением» я подразумеваю, что Saveba.js заменяет изображения прозрачным GIF размером 1 × 1 px, чтобы у пользователей не было поврежденных изображений при просмотре веб-сайта. Что касается того, что считается ненужным, библиотека считает любое не кэшированное изображение ненужным, если подключение пользователя медленное. Любое неконтентное изображение (изображения с пустым атрибутом alt Если у пользователя быстрое соединение, библиотека не будет выполнять никаких операций.

Для получения дополнительной информации о том, как классифицируются соединения, обратитесь к README библиотеки . Обратите внимание, что поскольку Saveba.js находится на очень ранней стадии, я настоятельно рекомендую вам не использовать его в работе. Тем не менее, вы можете следить за этим.

Ключевые моменты Saveba.js

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

 // Default values.
   // Later exposed as saveba.defaults
   var defaults = {

   // A NodeList or an Array of elements the library must ignore
   ignoredElements: [],

   // A Number specifying the maximum speed in MB/s after which
   // a connection isn't considered slow anymore
   slowMax: 0.5,

   // A Number specifying the minimum speed in MB/s after which
   // a connection is considered fast
   fastMin: 2
};

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

 var connection = window.navigator.connection    ||
                 window.navigator.mozConnection ||
                 null;

// API not supported. Can't optimize the website
if (!connection) {
   return false;
}

Третий шаг — классифицировать используемое соединение на основе текущей конфигурации и поддерживаемой версии API:

 // Test whether the API supported is compliant with the old specifications
var oldApi = 'metered' in connection;
var slowConnection = (oldApi && (connection.metered || connection.bandwidth < defaults.slowMax)) ||
   (!oldApi && (connection.type === 'bluetooth' || connection.type === 'cellular'));
var averageConnection = oldApi &&
   !connection.metered &&
   connection.bandwidth >= defaults.slowMax &&
   connection.bandwidth < defaults.fastMin;

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

 var elements;
if (slowConnection) {
   // Select all images (non-content images and content images)
   elements = document.querySelectorAll('img');
} else if (averageConnection) {
   // Select non-content images only
   elements = document.querySelectorAll('img[alt=""]');
}
elements = [].slice.call(elements);

if (!(defaults.ignoredElements instanceof Array)) {
   defaults.ignoredElements = [].slice.apply(defaults.ignoredElements);
}

// Filter the resources specified in the ignoredElements property and
// those that are in the browser's cache.
// More info: http://stackoverflow.com/questions/7844982/using-image-complete-to-find-if-image-is-cached-on-chrome
elements = elements.filter(function(element) {
   return defaults.ignoredElements.indexOf(element) === -1 ? !element.complete : false;
});

Наконец, я заменяю оставшиеся ресурсы заполнителем, сохраняя ссылку на исходный источник в атрибуте с именем data-saveba

 // Replace the targeted resources with a 1x1 px, transparent GIF
for(var i = 0; i < elements.length; i++) {
   elements[i].dataset.saveba = elements[i].src;
   elements[i].src = transparentGif;
}

Как использовать это на вашем сайте

Чтобы использовать Saveba.js , загрузите файл JavaScript, содержащийся в папке «src», и включите его в свою веб-страницу.

 <script src="path/to/saveba.js"></script>

Библиотека автоматически выполнит свою работу, поэтому вам не нужно вызывать какой-либо метод. Saveba.js также предоставляет глобальный объект savebawindowdestroy()

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

destroy()

Если вы хотите удалить изменения, выполненные Saveba.js, вы можете вызвать метод destroy()saveba Например, допустим, что на странице, на которой были внесены изменения, есть кнопка с идентификатором show-images-button Вы можете добавить прослушиватель событий к событию click, который восстанавливает все ресурсы, как показано ниже:

 <script>
document.getElementById('show-images-button').addEventListener('click', function(event) {
   saveba.destroy();
});
</script>

Поддерживаемые браузеры

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

  • Firefox 30+. До Firefox 31 браузер поддерживал самую старую версию API. В Firefox 31 API был отключен на рабочем столе
  • Chrome 38+, но он доступен только в Chrome для Android, Chrome для iOS и ChromeOS
  • Опера 25+
  • Браузер для Android 2.2+

демонстрация

Чтобы увидеть Saveba.js в действии, вы можете посмотреть живую демонстрацию .

Вывод

В этой статье я описал некоторые ограничения текущей практики оптимизации веб-сайта, которые привели меня к созданию Saveba.js. Последняя представляет собой библиотеку JavaScript, которая, опираясь на API информации о сети, пытается сэкономить пропускную способность для пользователей, имеющих медленное соединение, удаляя ненужные ресурсы. После ознакомления с ней я объяснил, как работает библиотека и как вы можете использовать ее на своем веб-сайте, хотя в настоящий момент вам действительно не следует использовать ее в производстве.

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