Data URI изображения вместо спрайтов в Ruby on Rails

в 12:11, , рубрики: ruby on rails, высокая производительность, Серверная оптимизация, метки: ,

dataURI-image

Кому?

  • Тем кто на Ruby on Rails.
  • Кто не использует спрайты изображений, но собирается на них переходить — и при этом считает это «замором и гимором».
  • Кто не собирается поддерживать IE6-7 (и 8) или знает все их прелести (да это легко поправить — но реально давайте уже их похороним).

Не освещено

  • Правильность написания «data URI» vs «data URL»
  • Тесты производительности — да здесь только теория


Оптимизация web-приложения (страницы, ресурса, портала — далее для краткости просто — приложение) напрямую зависит от количества запросов к серверу. Есть замечательная презентация по этой теме. В качестве оптимизации (уменьшения количества запросов к серверу) применяются спрайты с изображениями, т.е. группа изображений объединяется в одно — и после силами css показываются лишь отдельные его части. Это в свою очередь добавляет разработчику немало усилий — в том случае, если разработчик никогда не пользовался спрайтами, а только собирается на них переводить своё детище. В любом случае изображения, которые помещаются в спрайты, маловероятно, будут когда либо изменены — если конечно, не переделывать дизайн приложения вообще, т.е. не менять основной CSS-файл приложения. Но — зачем нам отдельный файл с изображениями, если можно использовать data URI?

Итак, стратегия

  • <div> с необходимой фоновой картинкой вместо изображения (вместо <img>)
    это позволит переместить все изображения в css-файл
  • <input type=image ... /> с прозрачной основой и фоновой картинкой вместо изображения
    в качестве прозрачной основы используется однопиксельный прозрачный GIF
  • склейка всех css в один
    меньше файлов — меньше запросов ( в RoR так и есть )
  • css-файлу в конец md5-хэш
    удобно для разработки — меняется файл, меняется его имя ( в RoR так и есть )
  • css-файлу в заголовке запроса: хранить год
    если файл не меняется — то храним его у клиента в кэше

Основания

Демо

Голая теория сама по себе ничего не значит — знаю теоретиков на Хабре и так хватает — по этому запилил две демки для ознакомления первая использует вышепредложенную стратегию и вторая её не использует (спрайты вторая тоже не использует).

По данным расширения для Chrome «Live HTTP Headers» по количеству запросов:

стратегия первый запрос второй запрос
не используется 25 запросов 24 запроса, 23 из которых 304*
используется 5 запросов 4 запроса, 2 из которых 304*

* — 304 Файл не изменён

Визуально работоспособность протестирована на Chrome 32.0.1700.107, FF 27.0, Opera 12.16 (на движке Presto).

Ставим на поток

— Руками? Нет-нет-нет-нет-нет...

Добавление хелперов и манипуляции со стилями требуют глубокого понимания фреймворка (в частности добавление хелперов для FormBuilder) — поэтому весь функционал я поместил в гем

Необходимые изображения

Этот подход (стратегия) хорош только для небольших и часто повторяющихся изображений, например тот же search.png скорее всего можно встретить на каждой странице приложения. Все необходимые изображения помещаются в отдельную папку app/assets/images/uri (во избежании путаницы).

Необходимые методы-хелперы

метод эквивалент итоговый html-тэг
uri_image image_tag <div>
uri_submit_tag image_submit_tag <input type=image... />
uri_submit (для FormBuilder) submit type: 'image' <input type=image ... />

Использование

  = helper_method_name 'uri/image_filename.ext', attrs

uri/image_filename.ext — путь к файлу без использования image_path или asset_path
attrs — хэш с атрибутами html-тэга

Необходимые стили CSS

Каждое внедрённое вышеупомянутыми методами изображение имеет два класса uri и по шаблону uri_path_filename_ext*.

.uri{
  background-size: contain !important;
  background-repeat: no-repeat !important;
}

/* пример для файла app/assets/images/uri/edit/commit.png */
.uri_edit_commit_png{
  background-image: url(data:image/png;base64,*** data uri хэш ***) !important;
}

* — на самом деле класс типа uri_path_filename_ext генерируется для каждого изображения в папке app/assets/images/uri не зависимо от того — будет оно использоваться или нет.

Важно понимать, что <div> не будет вести себя как <img> и ему в любом случае нужна ширина и высота — иначе его не будет видно. Поэтому необходимо добавить соответствующие стилевые свойства элементам, например так

/* эти свойства свои для каждого разработчика, поэтому не включены в стили добавляемые по-умолчанию */
.uri{
  width: 7em;
  height: 7em;
  float: left;
  padding: .8em;
}

Уточнения

    Вот здесь конфигурации Nginx и Apache добавляющие статике «вечный заголовок».
    Помещённые в css изображения не исключаются из прекомпиляции — и соответственно, они будут лежать на сервере (занимать немножечко места) в папке public/assets/uri. Но с другой стороны — это может сыграть на руку — если Вы планируете поддерживать IE6-7 (и 8) или иным способом обращаться к оригиналам изображений. В конце концов исключить из прекомпиляции их можно — только ИМХО, не так уж много они весят, чтобы заморачиваться.
    IE8 поддерживает data URI размером не более 32 kB.
    IE8 не поддерживает используемое свойство background-size: contain;, если размер фоновой картинки такой же как и размер элемента — то проблем не будет.

Все ссылки кучей

Демо 1
Демо 2
Гем
Презентация о запросах

Автор: deep_orange

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js