Управление ресурсами в 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

youtube.com/watch?v=7hFivbgIEqk

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

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