Управление ресурсами в Symfony2

На этой неделе, помимо прочих задач, я занимался клиентской оптимизацией на своем рабочем проекте. И узнал кое-что новенькое, чем и спешу с Вами поделиться.
Хочу сразу оговориться, что я понимаю под словом "ресурс" (англ. asset). В данной статье под термином "ресурс" я подразумеваю HTTP ресурс, запрашиваемый браузером во время загрузки документа, т.е. это javascript файлы, css файлы, изображения и т.д.

Итак, приступим. В официальной документации по Symfony2 можно прочитать, что включать ресурсы в шаблоны нужно так:

// css
<link href="{{ asset('/css/main.css') }}" type="text/css" />


// javascript
<script src="{{ asset('/js/main.js') }}" type="text/javascript"></script>


// images
<img src="{{ asset('/images/header.png') }}"  />


Но для чего же нужна функция asset()? Почему не желательно указывать в атрибутах href и src относительный путь к файлу на сервере? Давайте разберемся.

Я взял для демонстрации несколько файлов из Blueprint CSS Framework и подключил их в шаблоне таким образом:

<link href="{{ asset('/css/blueprint/reset.css') }}" type="text/css" media="screen, projection">
<link href="{{ asset('/css/blueprint/grid.css') }}" type="text/css" media="screen,  projection">
<link href="{{ asset('/css/blueprint/forms.css') }}" type="text/css" media="screen,  projection">
<link href="{{ asset('/css/blueprint/forms.css') }}" type="text/css" media="screen,  projection">
<link href="{{ asset('/css/blueprint/typography.css') }}" type="text/css" media="print">
<!--[if lt IE 8]><link href="{{ asset('/css/blueprint/ie.css') }}" type="text/css" media="screen, projection"><![endif]-->


Если больше ничего не настраивать в конфиге, то Symfony отрендерит приведенный кусок шаблона в такой html:

<link href="/css/blueprint/reset.css" type="text/css" media="screen, projection">
<link href="/css/blueprint/grid.css" type="text/css" media="screen,  projection">
<link href="/css/blueprint/forms.css" type="text/css" media="screen,  projection">
<link href="/css/blueprint/forms.css" type="text/css" media="screen,  projection">
<link href="/css/blueprint/typography.css" type="text/css" media="print">
<!--[if lt IE 8]><link href="/css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->


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

1. Множественные домены

Symfony2 позволяет задать список доменов, а точнее список базовых URI. Т.е. в конфигурации можно прописать адреса источников из которых доступна загрузка ресурсов для нашего проекта.

Так как у меня всего один сервер, да и тот локальный, я просто прописал несколько доменов в /etc/hosts, а затем добавил эти же алиасы в конфигурации виртуального хоста. Теперь в конфигурационном файле я могу задать базовые URI для загрузки ресурсов:

framework:
    templating:
        assets_base_urls:
            - http://asset1.test.local
            - http://asset2.test.local
            - http://asset3.test.local
            - http://asset4.test.local
            - http://asset5.test.local


Тогда наш кусочек шаблона выведется как-то так:

<link href="http://asset2.test.local/css/blueprint/reset.css" type="text/css" media="screen, projection">
<link href="http://asset3.test.local/css/blueprint/grid.css" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css" type="text/css" media="screen,  projection">
<link href="http://asset5.test.local/css/blueprint/typography.css" type="text/css" media="print">
<!--[if lt IE 8]><link href="http://asset5.test.local/css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->

Т.е. Symfony добавит к каждому относительному пути указанному в функции asset() один из базовых URI из конфига. Я не разбирался с тем, в каком порядке будут подставлены URI из конфигурационного файла, могу лишь сказать, что последовательность всегда одна и та же. Т.е. если мы использовали один домен для загрузки ресурса, то этот ресурс для пользователя всегда будет загружаться с выбранного домена. В другом случае эта фича не имела бы смысла, т.к. все ресурсы кешируются браузером. И браузер понимает ресурс с другого домена как уникальный и скачивает его вместо того, чтобы использовать закешированный.

Таким образом используя конфигурационную опцию assets_base_urls можно разнести ресурсы на несколько серверов или использовать CDN. Но даже, если у вас всего один сервер, как в моем случае. То все равно имеет смысл сконфигурировать для вашего сервера дополнительные домены и использовать их как алиасы для загрузки ресурсов. И сейчас объясню зачем.

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

 

2. Сache busting


Как я уже говорил, все ресурсы кешируются на стороне клиента (т.е. браузером). Но что делать, если вы, скажем, обновили стили и пользователям нужно загрузить новую версию стилей, а старая версия находится в кеше. Решение в данном случае простое. В запрос нужно просто добавить какое-нибудь уникальное значение. URI ресурса в этом случае поменяется и браузер загрузит новую актуальную версию. И совсем не обязательно сообщать пользователям: "Мы там стили обновили. Почистите в Вашем браузере кеш, пожалуйста!" :)

В Symfony2 можно просто указать в конфиге версию ресурсов. Например, я добавил в свой конфиг такие строки:

framework:
    templating:
        assets_version: 1.0.0


и получил такой html:

<link href="http://asset2.test.local/css/blueprint/reset.css?1.0.0" type="text/css" media="screen, projection">
<link href="http://asset3.test.local/css/blueprint/grid.css?1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css?1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css?1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset5.test.local/css/blueprint/typography.css?1.0.0" type="text/css" media="print">
<!--[if lt IE 8]><link href="http://asset5.test.local/css/blueprint/ie.css?1.0.0" type="text/css" media="screen, projection"><![endif]-->


Можно обновлять версию автоматически при каждом деплойменте, чтобы не забыть.

Но и это еще не все. Предположим, что нашему серверу нужно сохранить старые версии ресурсов в другой директории, к примеру обновления интерфейса происходит только для части пользователей. И чтобы получить актуальную версию ресурсов, нам нужно передать серверу именованный параметр. Пуcть, он будет называться "v". По этому параметру мы и будем определять какая версия файлов нужна.

Чтобы реализовать такое поведение, снова отредактируем конфиг:

framework:
    templating:
      assets_version_format  : %%s?v=%%s


И проверим, что же у нас получилось:

<link href="http://asset2.test.local/css/blueprint/reset.css?v=1.0.0" type="text/css" media="screen, projection">
<link href="http://asset3.test.local/css/blueprint/grid.css?v=1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css?v=1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset1.test.local/css/blueprint/forms.css?v=1.0.0" type="text/css" media="screen,  projection">
<link href="http://asset5.test.local/css/blueprint/typography.css?v=1.0.0" type="text/css" media="print">
<!--[if lt IE 8]><link href="http://asset5.test.local/css/blueprint/ie.css?v=1.0.0" type="text/css" media="screen, projection"><![endif]-->


Как вы поняли в параметре assets_version_format задается шаблон для sprintf(). Только знак процента нужно дважды указывать для экранирования.

На этом на сегодня все. И сделаем свои приложения лучше... с Symfony2! Источник »

Оцени публикацию:
  • 0,0
Оценили человек: 0

Похожие статьи:

Справочники и учебники:


Предложения и пожелания:
Ваше имя:
Ваш E-mail:
Сколько будет Οдин + Τри
Главная
X

Новые заметки:

Про что мы забываем когда делаем оценку задачи по времени

Список вопросов для собеседования разработчика по телефону

Symfony2 авторизация без Doctrine2 для чайника

Phpstorm7 LiveEdit

Жесткий хабр или не хабр, тогда кто?

Яндекс.Деньги мошенничество

Как узнать какие страницы в поиске яндекса или это секрет

Последние комменты:

Yapro CMS:

Здравствуйте, Гость | Войти | Регистрация | Карта сайта | RSS ленты | Ошибка в тексте? Выделите её мышкой и нажмите: Ctrl + Enter

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2018 YaPro.Ru

Главная » Веб-мастеру » PHP »