Кому?
- Тем кто на 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