Статьи Архив статей

Перевод: Мациевский Николай aka sunnybear
Опубликована: 22 декабря 2008

Оптимизация изображений, часть 5: AlphaImageLoader

Примечание: ниже перевод очередной заметки "Image Optimization, Part 5: AlphaImageLoader" из блога YUI. Stoyan Stefanov на этот раз рассказывает о тонкостях применения фильтра AlphaImageLoader для IE. Мои комментарии далее курсивом.

Это пятая часть серии статей про оптимизацию изображений. С предыдущими частями можно ознакомиться по адресу:

Данная статья из серии, посвященной оптимизации изображений, рассказывает о технике, доступной только в IE, — CSS-фильтре AlphaImageLoader, — который используется разработчиками для решения проблем с прозрачностью для полноцветных PNG-изображений в IE. Основная проблема с AlphaImageLoader заключается в том, что он влияет на производительность страницы, и тем самым ухудшает пользовательское восприятие. Я утверждаю, что стоит избегать использования AlphaImageLoader во всех возможных случаях.

Маленький экскурс

Как было сказано в одной из предыдущих статей, PNG могут быть нескольких видов, которые могут быть разделены на 2 основных:

  • Индексированные (палитра), их также называют PNG8, можно использовать до 256 цветов.
  • Полноцветные PNG, которые также называют PNG32 или PNG24.

Оба формата поддерживают альфа (дробную) прозрачность и, хотя изображения в формате PNG8 превращаются в GIF-подобные в IE6 (недробная прозрачность, пример, исходник), полноцветные PNG в нем же вместо прозрачных пикселей получают отвратительный фон (источник W3C).

Проблема полноцветных прозрачных PNG в IE6

Проблема полноцветных прозрачных PNG в IE6

Используем AlphaImageLoader

IE6 (и более старые версии IE) обеспечивает решение описанной проблемы при помощи CSS-свойства filter (которое доступно только в IE). Следующий код позволит отобразить требуемую картинку для всех браузеров:

#some-element {
    background: url(image.png);
    _background: none;
    _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop');
}

Как можно увидеть, CSS-хак с подчеркиванием позволяет применить стили только к IE < 7, и

  1. «отменить» фон, и
  2. загрузить ту же самую картинку, используя фильтр AlphaImageLoader от Microsoft.

Мы исключили предыдущие (относительно 7) версии IE из-за того, что IE7 уже поддерживается альфа-канал для изображений, поэтому ему не нужны фильтры. (IE8 также поддерживает и уже даже изменил синтаксис фильтров.)

Самое интересное заключается в том, фильтр не изменяет саму картинку: он, скорее, меняет сам HTML-элемент, к которому применен этот стиль. Другой интересной особенностью является то, что каждый такой элемент анализируется синхронно в общем UI-потоке. Процесс применения фильтра отнимает некоторое количество ресурсов: чем больше у вас «отфильтрованных» элементов, тем медленнее протекает общий процесс. И это даже если для них для всех используется одно-единственное изображение.

Вопрос заключается в следующем: как все это влияет на общую производительность страницы?

Стоп! Первая проблема

Давайте поставим простой эксперимент: создадим страницу с CSS-фильтром и затем искусственно увеличим сетевую задержку для изображения, которое используется фильтром, в 10 секунд. Что мы получили? Не только белую страницу в течение всех этих 10 секунд, но и «заморозку» браузера: вы не можете взаимодействовать со страницей (кликать по иконкам меню, вводить адрес другого сайта и даже закрыть эту страницу), пока браузер не получит искомое изображение.

Здесь тестовый пример.

В этом примере я не использовал хак с подчеркиванием, поэтому (д)эффект проявляется и в IE7, и даже в IE8 в «режиме совместимости».

Хотя негативный эффект и сильно преувеличен с целью продемонстрировать самый неблагоприятный расклад событий. Однако сетевые задержки являются неотъемлемой частью нашей жизни. И это, возможно, самое плохое, что вы можете сделать для пользователей: «заморозить» им страницу, пока определенная картинка не будет загружена. В этой связи использование технологии DURIS (data:URI + mhtml) выступает в весьма выгодном свете: IE Будет применять фильтры с использованием той картинки, которая уже загрузилась в самом CSS-файле, никаких дополнительных задержек! Первым использовать данную технологию предложил именно посмотреть профиль bolk.

Стоит заметить, что параллельные загрузки не блокируются. Браузер по-прежнему запрашивает и доставляет другие компоненты страницы в фоновом режиме, просто не происходит последовательного обновления страницы. Можно представить это и следующим образом: IE Не показывает страницу, пока CSS-файл не загрузится полностью, до самого последнего байта (более подробная информация). А поскольку CSS-файл зависит от фильтруемой картинки, то отображение страницы блокируется, пока эта зависимость не будет удовлетворена.

Но что происходит, если на странице используется несколько фильтров AlphaImageLoader? Все они будут обработаны последовательно, поэтому проблемы умножатся. Если, к примеру, у вас на странице 5 картинок, и у каждой задержка в 2 секунды, то браузер «заморозится» на 10 секунд.

Время и память — проблемы #2 и #3

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

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

Для начала мы создадим реперную страницу: на ней будет расположено сто <div>, в каждом из которых будет находиться нефильтрованная картинка. Затем создадим вторую страницу, на которой будет применен фильтр (ко всем 100 div один и тот же). К счастью, 100 элементов с фильтром довольно сложно найти на обычной странице, однако, небольшое преувеличение в данном случае поможет уточнить наши измерения.

Время замеряется от начала страницы (в самом верху страницы, до вызова всех элементов, устанавливается метка времени) до события onload. После того как картинки закэшируются, этот промежуток времени будет корректно отображать ресурсы, затрачиваемые на применение фильтров, поскольку время на загрузку картинок и страницы тратиться уже не будет. Потребление памяти измерялось при помощи инструмента ProcessExplorer: бралась дельта процесса до загрузки страницы и после. Таким образом мы устанавливали «цену» отображения страницы.

Ниже приведены усредненные результаты после 10 запусков в IE6 на компьютере с двумя 2GHz CPU и 500 Мб оперативной памяти. На менее мощном компьютере потери при загрузке страницы будут еще больше.

Тестовые результаты для AlphaImageLoader
Тестовая страницаВремя, секундыПамять, Мб
Тест #1: никаких фильтров0,0310,6
Тест #2: фильтры0,84446,8

Как можно видеть из полученных результатов, AlphaImageLoader крайне отрицательно влияет на загрузку страницы: наша тестовая страница загружалась в 27 раз медленнее и отъедала в 78 раз больше памяти (в пересчете на одну картинку получится 8 мс задержки и 0,5 Мб памяти — с этим еще можно жить :). Полностью доверять этим результатам, естественно, нельзя: это только одна картинка, протестированная на одном компьютере (относительно мощном и незагруженном). Если у вас будет несколько различных картинок, применяемых к различным элементам на различных машинах, результаты будут очень сильно колебаться. Ос