Активы
Активом в Yii является файл, который может быть сохранен на веб-странице. Это может быть файл CSS, файл JavaScript, файл изображения или видео и т. д. Активы расположены в доступных для веб-сервера директориях и непосредственно обслуживаются веб-серверами.
Часто предпочтительно управлять активами программно. Например, при использовании виджета yii\jui\DatePicker на странице он автоматически подключает необходимые файлы CSS и JavaScript, вместо того, чтобы просить вас вручную найти эти файлы и подключить их. И при обновлении виджета до новой версии он автоматически будет использовать новую версию файлов активов. В этом руководстве мы опишем мощные возможности управления активами, предоставляемые в Yii.
Пакеты активов
Yii управляет активами в единице пакета активов. Пакет активов — это просто коллекция активов, расположенных в каталоге. Когда вы регистрируете пакет активов в представлении, он будет включать файлы CSS и JavaScript в пакете в рендеренной веб-странице.
Определение пакетов активов
Пакеты активов определяются как классы PHP, расширяющие yii\web\AssetBundle. Название пакета — это просто соответствующее полное квалифицированное имя PHP-класса (без ведущей косой черты). Класс пакета активов должен быть автозагружаемым. Обычно он указывает, где находятся активы, какие файлы CSS и JavaScript содержит пакет и как пакет зависит от других пакетов.
Следующий код определяет основной пакет активов, используемый шаблоном базового проекта:
<?php
namespace app\assets;
use yii\web\AssetBundle;
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
Вышеупомянутый AppAsset класс указывает, что файлы активов расположены в каталоге @webroot, который соответствует URL @web; пакет содержит один файл CSS css/site.css и не содержит файлов JavaScript; пакет зависит от двух других пакетов: yii\web\YiiAsset и yii\bootstrap\BootstrapAsset. Более подробное объяснение свойств yii\web\AssetBundle можно найти по следующим ссылкам:
- sourcePath: указывает корневую директорию, содержащую файлы активов в этом пакете. Эта свойство должно быть установлено, если корневая директория не доступна по сети. В противном случае вы должны установить свойство basePath и baseUrl. Здесь можно использовать псевдонимы путей.
- basePath: указывает доступный по сети каталог, содержащий файлы активов в данном пакете. При указании свойства sourcePath менеджер активов опубликует активы в этом пакете в доступный по сети каталог и соответственно перезапишет это свойство. Вы должны установить это свойство, если ваши файлы активов уже находятся в доступном по сети каталоге и не требуют публикации активов. Здесь можно использовать псевдонимы путей.
- baseUrl: указывает URL, соответствующий каталогу basePath. Как и basePath, если вы укажете свойство sourcePath, менеджер активов опубликует активы и соответственно перезапишет это свойство. Здесь можно использовать псевдонимы путей.
-
js: массив, содержащий список файлов JavaScript, содержащихся в этом пакете. Обратите внимание, что в качестве разделителей каталогов должен использоваться только прямой слэш "/". Каждый файл JavaScript может быть задан в одном из следующих двух форматов:
- относительный путь, представляющий локальный файл JavaScript (например,
js/main.js). Фактический путь к файлу может быть определен путем добавления yii\web\AssetManager::$basePath к относительному пути, а фактический URL-адрес файла может быть определен путем добавления yii\web\AssetManager::$baseUrl к относительному пути. - абсолютный URL, представляющий внешний файл JavaScript. Например,
http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.jsили//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js.
- относительный путь, представляющий локальный файл JavaScript (например,
- css: массив, содержащий список файлов CSS, содержащихся в этом пакете. Формат этого массива такой же, как и у js.
- depends: массив, содержащий имена пакетов активов, от которых зависит данный пакет (подробнее об этом будет рассказано чуть позже).
- jsOptions: задает параметры, которые будут переданы методу yii\web\View::registerJsFile(), когда он будет вызван для регистрации каждого файла JavaScript в этом пакете.
- cssOptions: задает параметры, которые будут переданы методу yii\web\View::registerCssFile(), когда он будет вызван для регистрации каждого файла CSS в этом пакете.
- publishOptions: задает параметры, которые будут переданы методу yii\web\AssetManager::publish() при вызове для публикации исходных файлов активов в веб-каталог. Это используется только в том случае, если вы указали свойство sourcePath.
Расположение активов
Активы, в зависимости от их местоположения, можно классифицировать следующим образом:
- исходные активы: файлы активов расположены вместе с исходным кодом PHP, к которому нельзя получить прямой доступ через веб. Для использования исходных активов на странице их необходимо скопировать в веб-каталог и преобразовать в так называемые опубликованные активы. Этот процесс называется публикацией активов, который будет подробно описан чуть позже.
- опубликованные активы: файлы активов расположены в веб-каталоге и, следовательно, к ним можно получить прямой доступ через веб.
- внешние активы: файлы активов расположены на веб-сервере, отличном от веб-приложения.
При определении класса пакета активов, если вы укажете свойство sourcePath, это означает, что любые активы, указанные с помощью относительных путей, будут рассматриваться как исходные активы. Если вы не укажете это свойство, это означает, что эти активы являются опубликованными активами (поэтому вы должны указать basePath и baseUrl, чтобы Yii знал, где они находятся).
Рекомендуется размещать активы, относящиеся к приложению, в веб-каталоге, чтобы избежать ненужного процесса публикации активов. Вот почему в предыдущем примере AppAsset указывает basePath вместо sourcePath.
Для расширений, поскольку их активы расположены вместе с исходным кодом в каталогах, которые недоступны по сети, вы должны указать свойство sourcePath при определении классов пакетов активов для них.
Примечание: Не используйте
@webroot/assetsв качестве пути источника. По умолчанию этот каталог используется менеджером активов для сохранения файлов активов, опубликованных из их исходного местоположения. Любое содержимое в этом каталоге считается временным и может быть удалено.
Зависимости активов
При включении нескольких файлов CSS или JavaScript на веб-странице им необходимо соблюдать определенный порядок, чтобы избежать проблем с перезаписью. Например, если вы используете виджет jQuery UI на веб-странице, вы должны убедиться, что файл JavaScript jQuery включен перед файлом JavaScript jQuery UI. Мы называем такой порядок зависимостями между активами.
Зависимости активов в основном задаются свойством yii\web\AssetBundle::$depends. В примере AppAsset пакет активов зависит от двух других пакетов активов: yii\web\YiiAsset и yii\bootstrap\BootstrapAsset, что означает, что файлы CSS и JavaScript в AppAsset будут включены после этих файлов в двух зависимых пакетах.
Зависимости активов являются транзитивными. Это означает, что если пакет A зависит от B, который зависит от C, A также будет зависеть от C.
Параметры активов
Вы можете указать свойства cssOptions и jsOptions для настройки способа включения файлов CSS и JavaScript на странице. Значения этих свойств будут переданы методам yii\web\View::registerCssFile() и yii\web\View::registerJsFile() соответственно, когда они будут вызваны представлением для включения файлов CSS и JavaScript.
Примечание: Параметры, заданные в классе пакета, применяются к каждому файлу CSS/JavaScript в пакете. Если вы хотите использовать разные параметры для разных файлов, вы должны создать отдельные пакеты активов и использовать один набор параметров в каждом пакете.
Например, чтобы условно включить файл CSS для браузеров IE9 и ниже, можно использовать следующий параметр:
public $cssOptions = ['condition' => 'lte IE9'];
Это заставит файл CSS в пакете быть включенным с помощью следующих HTML-тегов:
<!--[if lte IE9]> <link rel="stylesheet" href="path/to/foo.css"> <![endif]-->
Чтобы поместить сгенерированные теги ссылки CSS в <noscript>, можно настроить cssOptions следующим образом:
public $cssOptions = ['noscript' => true];
Чтобы включить файл JavaScript в секцию head страницы (по умолчанию файлы JavaScript включаются в конце секции body), используйте следующий параметр:
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
По умолчанию при публикации пакета активов всё содержимое каталога, указанного в yii\web\AssetBundle::$sourcePath, будет опубликовано. Вы можете настроить это поведение, настроив свойство publishOptions. Например, чтобы опубликовать только один или несколько подкаталогов yii\web\AssetBundle::$sourcePath, можно сделать следующее в классе пакета активов:
<?php
namespace app\assets;
use yii\web\AssetBundle;
class FontAwesomeAsset extends AssetBundle
{
public $sourcePath = '@bower/font-awesome';
public $css = [
'css/font-awesome.min.css',
];
public $publishOptions = [
'only' => [
'fonts/',
'css/',
]
];
}
Приведённый выше пример определяет пакет ресурсов для пакета «fontawesome». Указав опцию публикации only, будут опубликованы только подкаталоги fonts и css.
Установка ресурсов Bower и NPM
Большинство пакетов JavaScript/CSS управляются менеджерами пакетов Bower и/или NPM. В мире PHP у нас есть Composer, который управляет зависимостями PHP, но можно загружать пакеты Bower и NPM, используя composer.json, точно так же, как пакеты PHP.
Для этого необходимо немного настроить наш Composer. Существует два варианта:
Использование репозитория asset-packagist
Этот способ удовлетворит требования большинства проектов, которым нужны пакеты NPM или Bower.
Примечание: С версии 2.0.13, шаблоны приложений Basic и Advanced по умолчанию настроены для использования asset-packagist, поэтому вы можете пропустить этот раздел.
В composer.json своего проекта добавьте следующие строки:
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
Отрегулируйте @npm и @bower псевдонимы в вашей конфигурации приложения:
$config = [
...
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
...
];
Посетите asset-packagist.org, чтобы узнать, как это работает.
Использование fxp/composer-asset-plugin
По сравнению с использованием asset-packagist, composer-asset-plugin не требует изменения конфигурации приложения. Вместо этого необходимо установить специальный плагин Composer глобально, выполнив следующую команду:
composer global require "fxp/composer-asset-plugin:^1.3.1"
Эта команда устанавливает плагин composer asset глобально, что позволяет управлять зависимостями пакетов Bower и NPM через Composer. После установки плагина каждый проект на вашем компьютере будет поддерживать пакеты Bower и NPM через composer.json.
Добавьте следующие строки в composer.json своего проекта, чтобы настроить директории, где будут размещаться установленные пакеты, если вы хотите опубликовать их с помощью Yii:
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
Примечание:
fxp/composer-asset-pluginсущественно замедляет командуcomposer updateпо сравнению с asset-packagist.
После настройки Composer для поддержки Bower и NPM:
- Измените файл
composer.jsonвашего приложения или расширения и перечислите пакет в записиrequire. Вы должны использоватьbower-asset/PackageName(для пакетов Bower) илиnpm-asset/PackageName(для пакетов NPM), чтобы сослаться на библиотеку. - Запустите
composer update - Создайте класс пакета ресурсов и перечислите файлы JavaScript/CSS, которые вы планируете использовать в своем приложении или расширении. Вы должны указать свойство sourcePath как
@bower/PackageNameили@npm/PackageName. Это связано с тем, что Composer установит пакет Bower или NPM в директорию, соответствующую этому псевдониму.
Примечание: Некоторые пакеты могут помещать все свои распределённые файлы в подкаталог. В этом случае вы должны указать подкаталог в качестве значения sourcePath. Например, yii\web\JqueryAsset использует
@bower/jquery/distвместо@bower/jquery.
Использование пакетов ресурсов
Для использования пакета ресурсов зарегистрируйте его в представлении, вызвав метод yii\web\AssetBundle::register(). Например, в шаблоне представления вы можете зарегистрировать пакет ресурсов следующим образом:
use app\assets\AppAsset; AppAsset::register($this); // $this represents the view object
Информация: Метод yii\web\AssetBundle::register() возвращает объект пакета ресурсов, содержащий информацию об опубликованных ресурсах, таких как basePath или baseUrl.
Если вы регистрируете пакет ресурсов в других местах, вы должны предоставить необходимый объект представления. Например, для регистрации пакета ресурсов в классе виджета вы можете получить объект представления, используя $this->view.
Когда пакет ресурсов зарегистрирован в представлении, Yii за кулисами зарегистрирует все его зависимые пакеты ресурсов. И если пакет ресурсов находится в каталоге, недоступном через веб, он будет опубликован в веб-каталог. Позже, при рендеринге страницы представлением, оно сгенерирует теги <link> и <script> для файлов CSS и JavaScript, перечисленных в зарегистрированных пакетах ресурсов. Порядок этих тегов определяется зависимостями между зарегистрированными пакетами ресурсов и порядком ресурсов, перечисленных в свойствах yii\web\AssetBundle::$css и yii\web\AssetBundle::$js.
Динамические пакеты ресурсов
Будучи обычным классом PHP, пакет ресурсов может содержать дополнительную логику, связанную с ним, и может динамически изменять свои внутренние параметры. Например: вы можете использовать сложную JavaScript-библиотеку, которая предоставляет некоторую локализацию, упакованную в отдельные файлы исходного кода: по одному на каждый поддерживаемый язык. Таким образом, вам необходимо добавить конкретный файл '.js' на вашу страницу, чтобы библиотека работала с переводом. Это можно сделать, переопределив метод yii\web\AssetBundle::init():
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class SophisticatedAssetBundle extends AssetBundle
{
public $sourcePath = '/path/to/sophisticated/src';
public $js = [
'sophisticated.js' // file, which is always used
];
public function init()
{
parent::init();
$this->js[] = 'i18n/' . Yii::$app->language . '.js'; // dynamic file added
}
}
Конкретный пакет ресурсов также можно настроить с помощью экземпляра, возвращенного методом yii\web\AssetBundle::register(). Например:
use app\assets\SophisticatedAssetBundle; use Yii; $bundle = SophisticatedAssetBundle::register(Yii::$app->view); $bundle->js[] = 'i18n/' . Yii::$app->language . '.js'; // dynamic file added
Примечание: хотя динамическая настройка пакетов ресурсов поддерживается, это плохая практика, которая может привести к непредвиденным побочным эффектам и должна быть избегаема, если это возможно.
Настройка пакетов ресурсов
Yii управляет пакетами ресурсов через компонент приложения с именем assetManager, реализованный в yii\web\AssetManager. Настроив свойство yii\web\AssetManager::$bundles, можно настроить поведение пакета ресурсов. Например, стандартный пакет ресурсов yii\web\JqueryAsset использует файл jquery.js из установленного пакета jQuery Bower. Для повышения доступности и производительности вы можете использовать версию, размещенную в Google. Этого можно добиться, настроив assetManager в конфигурации приложения следующим образом:
return [
// ...
'components' => [
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => [
'sourcePath' => null, // do not publish the bundle
'js' => [
'//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
]
],
],
],
],
];
Вы можете аналогично настроить несколько пакетов ресурсов через yii\web\AssetManager::$bundles. Ключи массива должны быть именами классов (без ведущей косой черты) пакетов ресурсов, а значения массива — соответствующие конфигурационные массивы.
Подсказка: Вы можете условно выбрать, какие ресурсы использовать в пакете ресурсов. Следующий пример показывает, как использовать
jquery.jsв среде разработки иjquery.min.jsв противном случае:'yii\web\JqueryAsset' => [ 'js' => [ YII_ENV_DEV ? 'jquery.js' : 'jquery.min.js' ] ],
Вы можете отключить один или несколько пакетов ресурсов, связав false с именами пакетов ресурсов, которые вы хотите отключить. При регистрации отключенного пакета ресурсов в представлении, ни один из его зависимых пакетов не будет зарегистрирован, и представление также не будет включать какие-либо ресурсы из пакета в рендеринг страницы. Например, чтобы отключить yii\web\JqueryAsset, вы можете использовать следующую конфигурацию:
return [
// ...
'components' => [
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => false,
],
],
],
];
Вы также можете отключить все пакеты ресурсов, установив yii\web\AssetManager::$bundles как false.
Помните, что настройки, сделанные через yii\web\AssetManager::$bundles, применяются при создании пакета ресурсов, например, на этапе конструктора объекта. Таким образом, любые изменения, внесённые в объект пакета после этого, перекроют настройку сопоставления на уровне yii\web\AssetManager::$bundles. В частности: корректировки, сделанные внутри метода yii\web\AssetBundle::init() или над зарегистрированным объектом пакета ресурсов, будут иметь приоритет над AssetManager конфигурацией. Вот примеры, где сопоставление, заданное через yii\web\AssetManager::$bundles, не имеет эффекта:
// Program source code:
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class LanguageAssetBundle extends AssetBundle
{
// ...
public function init()
{
parent::init();
$this->baseUrl = '@web/i18n/' . Yii::$app->language; // can NOT be handled by `AssetManager`!
}
}
// ...
$bundle = \app\assets\LargeFileAssetBundle::register(Yii::$app->view);
$bundle->baseUrl = YII_DEBUG ? '@web/large-files': '@web/large-files/minified'; // can NOT be handled by `AssetManager`!
// Application config :
return [
// ...
'components' => [
'assetManager' => [
'bundles' => [
'app\assets\LanguageAssetBundle' => [
'baseUrl' => 'http://some.cdn.com/files/i18n/en' // makes NO effect!
],
'app\assets\LargeFileAssetBundle' => [
'baseUrl' => 'http://some.cdn.com/files/large-files' // makes NO effect!
],
],
],
],
];
Сопоставление ресурсов
Иногда вы можете захотеть «исправить» неверные/несовместимые пути к файлам ресурсов, используемые в нескольких пакетах ресурсов. Например, пакет A использует jquery.min.js версии 1.11.1, а пакет B использует jquery.js версии 2.1.1. Хотя вы можете решить проблему, настроив каждый пакет, более лёгкий способ — использовать функцию карты ресурсов для сопоставления неверных ресурсов с нужными. Для этого настройте свойство yii\web\AssetManager::$assetMap следующим образом:
return [
// ...
'components' => [
'assetManager' => [
'assetMap' => [
'jquery.js' => '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
],
],
],
];
Ключи assetMap — это имена ресурсов, которые вы хотите исправить, а значения — желаемые пути к ресурсам. При регистрации пакета ресурсов с представлением каждый относительный файл ресурса в массивах css и js будет проверен на соответствие этой карте. Если какой-либо из ключей оказывается последней частью файла ресурса (который предваряется yii\web\AssetBundle::$sourcePath, если доступно), соответствующее значение заменит ресурс и будет зарегистрировано с представлением. Например, файл ресурса my/path/to/jquery.js соответствует ключу jquery.js.
Примечание: Только ресурсы, указанные с помощью относительных путей, подлежат сопоставлению ресурсов. Целевые пути к ресурсам должны быть либо абсолютными URL-адресами, либо путями, относительными к yii\web\AssetManager::$basePath.
Публикация ресурсов
Как уже упоминалось, если пакет ресурсов находится в каталоге, недоступном через веб, его ресурсы будут скопированы в веб-каталог при регистрации пакета ресурсов в представлении. Этот процесс называется публикацией ресурсов и выполняется автоматически менеджером ресурсов .
По умолчанию ресурсы публикуются в каталог @webroot/assets, что соответствует URL-адресу @web/assets. Вы можете настроить это расположение, настроив свойства basePath и baseUrl.
Вместо публикации ресурсов путём копирования файлов, вы можете рассмотреть использование символических ссылок, если это позволяет ваша ОС и веб-сервер. Эту функцию можно включить, установив linkAssets в значение true.
return [
// ...
'components' => [
'assetManager' => [
'linkAssets' => true,
],
],
];
При указанной выше конфигурации менеджер ресурсов создаст символическую ссылку на исходный путь пакета ресурсов при его публикации. Это быстрее, чем копирование файлов, и также гарантирует, что опубликованные ресурсы всегда будут актуальными.
Выборка кеша
Для веб-приложений, работающих в режиме производства, принято включать кэширование HTTP для ресурсов и других статических данных. Недостатком этого подхода является то, что при изменении и развёртывании ресурса в производство клиент пользователя может по-прежнему использовать старую версию из-за кэширования HTTP. Чтобы преодолеть этот недостаток, можно использовать функцию выбора кеша, представленную в версии 2.0.3, настроив yii\web\AssetManager следующим образом:
return [
// ...
'components' => [
'assetManager' => [
'appendTimestamp' => true,
],
],
];
В результате URL каждого опубликованного ресурса будет дополнен отметкой о последнем изменении. Например, URL к yii.js может выглядеть как /assets/5515a87c/yii.js?v=1423448645", где параметр v представляет отметку о последнем изменении файла yii.js. Теперь, если вы измените ресурс, его URL также изменится, что заставит клиента запросить последнюю версию ресурса.
Обычно используемые пакеты ресурсов
Основной код Yii определяет множество пакетов ресурсов. Среди них следующие пакеты часто используются и могут быть упомянуты в вашем приложении или расширении.
-
yii\web\YiiAsset: Он в основном включает файл
yii.js, который реализует механизм организации кода JavaScript в модулях. Он также предоставляет специальную поддержку для атрибутовdata-methodиdata-confirmи других полезных функций. Дополнительную информацию оyii.jsможно найти в разделе Клиентские скрипты. -
yii\web\JqueryAsset: Он включает файл
jquery.jsиз пакета jQuery Bower. - yii\bootstrap\BootstrapAsset: Он включает файл CSS из фреймворка Twitter Bootstrap.
- yii\bootstrap\BootstrapPluginAsset: Он включает файл JavaScript из фреймворка Twitter Bootstrap для поддержки JavaScript-плагинов Bootstrap.
- yii\jui\JuiAsset: Он включает файлы CSS и JavaScript из библиотеки jQuery UI.
Если ваш код зависит от jQuery, jQuery UI или Bootstrap, вы должны использовать эти предопределённые пакеты ресурсов, а не создавать свои версии. Если значения по умолчанию этих пакетов не удовлетворяют вашим потребностям, вы можете настроить их, как описано в разделе Настройка пакетов ресурсов.
Преобразование ресурсов
Вместо непосредственного написания кода CSS и/или JavaScript разработчики часто пишут их в расширенном синтаксисе и используют специальные инструменты для преобразования в CSS/JavaScript. Например, для кода CSS вы можете использовать LESS или SCSS; а для JavaScript вы можете использовать TypeScript.
Вы можете перечислить файлы ресурсов в расширенном синтаксисе в свойствах css и js пакета ресурсов. Например,
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.less',
];
public $js = [
'js/site.ts',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
При регистрации такого пакета ресурсов в представлении менеджер ресурсов автоматически запустит инструменты препроцессора для преобразования ресурсов в распознанном расширенном синтаксисе в CSS/JavaScript. Когда представление в конечном итоге отобразит страницу, оно будет включать файлы CSS/JavaScript на странице, а не исходные ресурсы в расширенном синтаксисе.
Yii использует расширения имён файлов для определения, в каком расширенном синтаксисе находится ресурс. По умолчанию он распознаёт следующие синтаксисы и расширения имён файлов:
-
LESS:
.less -
SCSS:
.scss -
Stylus:
.styl -
CoffeeScript:
.coffee -
TypeScript:
.ts
Yii полагается на установленные инструменты препроцессора для преобразования ресурсов. Например, чтобы использовать LESS, вы должны установить команду препроцессора lessc.
Вы можете настроить команды препроцессора и поддерживаемые расширенные синтаксисы, настроив yii\web\AssetManager::$converter следующим образом:
return [
'components' => [
'assetManager' => [
'converter' => [
'class' => 'yii\web\AssetConverter',
'commands' => [
'less' => ['css', 'lessc {from} {to} --no-color'],
'ts' => ['js', 'tsc --out {to} {from}'],
],
],
],
],
];
В приведённом выше примере мы указываем поддерживаемые расширенные синтаксисы через свойство yii\web\AssetConverter::$commands. Ключи массива — имена расширений файлов (без ведущей точки), а значения массива — имена расширений результирующих файлов ресурсов и команды для выполнения преобразования ресурсов. Токены {from} и {to} в командах будут заменены путями исходного файла ресурсов и путями целевого файла ресурсов.
Информация: Существуют и другие способы работы с ресурсами в расширенном синтаксисе помимо описанного выше. Например, вы можете использовать инструменты сборки, такие как grunt, для отслеживания и автоматического преобразования ресурсов в расширенном синтаксисе. В этом случае вы должны перечислить полученные файлы CSS/JavaScript в пакетах ресурсов, а не исходные файлы.
Объединение и сжатие ресурсов
Веб-страница может включать множество файлов CSS и/или JavaScript. Чтобы уменьшить количество запросов HTTP и общий размер загрузки этих файлов, распространённой практикой является объединение и сжатие нескольких файлов CSS/JavaScript в один или несколько файлов и затем включение этих сжатых файлов вместо оригинальных на веб-страницах.
Информация: Объединение и сжатие ресурсов обычно необходимы, когда приложение работает в режиме производства. В режиме разработки использование оригинальных файлов CSS/JavaScript часто удобнее для отладки.
В следующем мы представим подход к объединению и сжатию файлов ресурсов без необходимости изменения вашего существующего кода приложения.
- Найдите все пакеты ресурсов в вашем приложении, которые вы планируете объединять и сжимать.
- Разделите эти пакеты на одну или несколько групп. Обратите внимание, что каждый пакет может принадлежать только к одной группе.
- Объедините/сожмите файлы CSS в каждой группе в один файл. Аналогично сделайте это для файлов JavaScript.
- Определите новый пакет ресурсов для каждой группы:
Используя этот подход, при регистрации пакета ресурсов в представлении происходит автоматическая регистрация нового пакета ресурсов для группы, к которой принадлежит исходный пакет. В результате объединённые/сжатые файлы ресурсов включаются на странице вместо оригинальных.
Пример
Давайте рассмотрим пример для дальнейшего объяснения вышеуказанного подхода.
Предположим, что ваше приложение имеет две страницы, X и Y. Страница X использует пакеты ресурсов A, B и C, а страница Y использует пакеты ресурсов B, C и D.
У вас есть два способа разделить эти пакеты ресурсов. Один — использовать одну группу для включения всех пакетов ресурсов, другой — поместить A в группу X, D в группу Y и (B, C) в группу S. Какой из них лучше? Это зависит. Первый способ имеет преимущество в том, что обе страницы используют одни и те же объединённые файлы CSS и JavaScript, что делает кэширование HTTP более эффективным. С другой стороны, поскольку одиночная группа содержит все пакеты, размер объединённых файлов CSS и JavaScript будет больше, а следовательно, увеличится время начальной передачи файла. Для простоты в этом примере мы будем использовать первый способ, т.е. использовать одну группу для всех пакетов.
Информация: Разделение пакетов ресурсов на группы — это нетривиальная задача. Обычно это требует анализа реальных данных трафика различных ресурсов на разных страницах. В начале вы можете начать с одной группы для простоты.
Используйте имеющиеся инструменты (например, Closure Compiler, YUI Compressor) для объединения и сжатия файлов CSS и JavaScript во всех пакетах. Обратите внимание, что файлы должны быть объединены в порядке, удовлетворяющем зависимостям между пакетами. Например, если пакет A зависит от B, который зависит от C и D, то вы должны перечислить файлы ресурсов, начиная с C и D, затем B и, наконец, A.
После объединения и сжатия мы получим один файл CSS и один файл JavaScript. Предположим, что они называются all-xyz.css и all-xyz.js, где xyz обозначает отметку времени или хэш, используемый для уникализации имени файла, чтобы избежать проблем с кэшированием HTTP.
Мы на последнем шаге. Настройте менеджер ресурсов следующим образом в конфигурации приложения:
return [
'components' => [
'assetManager' => [
'bundles' => [
'all' => [
'class' => 'yii\web\AssetBundle',
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
'css' => ['all-xyz.css'],
'js' => ['all-xyz.js'],
],
'A' => ['css' => [], 'js' => [], 'depends' => ['all']],
'B' => ['css' => [], 'js' => [], 'depends' => ['all']],
'C' => ['css' => [], 'js' => [], 'depends' => ['all']],
'D' => ['css' => [], 'js' => [], 'depends' => ['all']],
],
],
],
];
Как объяснено в разделе Настройка пакетов ресурсов, вышеуказанная конфигурация изменяет поведение каждого пакета. В частности, пакеты A, B, C и D больше не содержат никаких файлов ресурсов. Теперь они все зависят от пакета all, который содержит объединённые файлы all-xyz.css и all-xyz.js. Соответственно, для страницы X вместо включения исходных файлов из пакетов A, B и C будут включены только эти два объединённых файла; то же самое происходит со страницей Y.
Есть один последний трюк, чтобы сделать вышеописанный подход более плавным. Вместо непосредственного изменения файла конфигурации приложения вы можете поместить массив настройки пакета в отдельный файл и условно включить этот файл в конфигурацию приложения. Например,
return [
'components' => [
'assetManager' => [
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
],
],
];
То есть массив конфигурации пакета ресурсов сохраняется в assets-prod.php для режима производства и в assets-dev.php для режима вне производства.
Примечание: этот механизм объединения ресурсов основан на возможности yii\web\AssetManager::$bundles переопределять свойства зарегистрированных пакетов ресурсов. Однако, как уже говорилось выше, эта возможность не охватывает настройки пакетов ресурсов, которые выполняются в методе yii\web\AssetBundle::init() или после регистрации пакета. Вы должны избегать использования таких динамических пакетов во время объединения ресурсов.
Использование команды asset
Yii предоставляет консольную команду asset, чтобы автоматизировать описанный нами подход.
Для использования этой команды, необходимо сначала создать файл конфигурации, описывающий, какие пакеты ресурсов должны быть объединены и как они должны быть сгруппированы. Можно использовать подкоманду asset/template, чтобы сгенерировать шаблон, а затем изменить его, чтобы он соответствовал вашим потребностям.
yii asset/template assets.php
Команда генерирует файл с именем assets.php в текущем каталоге. Содержимое этого файла выглядит следующим образом:
<?php
/**
* Configuration file for the "yii asset" console command.
* Note that in the console environment, some path aliases like '@webroot' and '@web' may not exist.
* Please define these missing path aliases.
*/
return [
// Adjust command/callback for JavaScript files compressing:
'jsCompressor' => 'java -jar compiler.jar --js {from} --js_output_file {to}',
// Adjust command/callback for CSS files compressing:
'cssCompressor' => 'java -jar yuicompressor.jar --type css {from} -o {to}',
// Whether to delete asset source after compression:
'deleteSource' => false,
// The list of asset bundles to compress:
'bundles' => [
// 'yii\web\YiiAsset',
// 'yii\web\JqueryAsset',
],
// Asset bundle for compression output:
'targets' => [
'all' => [
'class' => 'yii\web\AssetBundle',
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
'js' => 'js/all-{hash}.js',
'css' => 'css/all-{hash}.css',
],
],
// Asset manager configuration:
'assetManager' => [
],
];
Необходимо изменить этот файл и указать, какие пакеты ресурсов вы планируете объединить в опции bundles. В опции targets вы должны указать, как пакеты ресурсов должны быть разделены на группы. Как упоминалось ранее, можно указать одну или несколько групп.
Примечание: Поскольку псевдонимы
@webrootи@webнедоступны в консольном приложении, необходимо явно определить их в конфигурации.
Файлы JavaScript объединяются, сжимаются и записываются в js/all-{hash}.js, где {hash} заменяется хэшем результирующего файла.
Опции jsCompressor и cssCompressor указывают консольные команды или PHP-обработчики для выполнения объединения/сжатия JavaScript и CSS. По умолчанию Yii использует Closure Compiler для объединения файлов JavaScript и YUI Compressor для объединения файлов CSS. Необходимо установить эти инструменты вручную или настроить эти опции для использования своих инструментов.
С файлом конфигурации можно запустить команду asset для объединения и сжатия файлов ресурсов, а затем сгенерировать новый файл конфигурации пакета ресурсов assets-prod.php.
yii asset assets.php config/assets-prod.php
Сгенерированный файл конфигурации может быть включён в конфигурацию приложения, как описано в последнем подразделе.
Примечание: в случае если вы настраиваете пакеты ресурсов для своего приложения через yii\web\AssetManager::$bundles или yii\web\AssetManager::$assetMap и хотите, чтобы эта настройка применялась к исходным файлам для сжатия, необходимо включить эти опции в раздел
assetManagerвнутри файла конфигурации команды asset.
Примечание: при указании исходных файлов для сжатия следует избегать использования пакетов ресурсов, параметры которых могут быть изменены динамически (например, в методе
init()или после регистрации), так как они могут работать неправильно после сжатия.
Информация: Использование команды
asset— не единственный вариант автоматизации процесса объединения и сжатия ресурсов. Можно использовать отличный инструмент для запуска задач grunt, чтобы достичь той же цели.
Группирование пакетов ресурсов
В предыдущем подразделе мы объяснили, как объединить все пакеты ресурсов в один, чтобы свести к минимуму количество HTTP-запросов для файлов ресурсов, на которые ссылается приложение. На практике это не всегда желательно. Например, представьте, что ваше приложение имеет «передний» и «задний» интерфейсы, каждый из которых использует разные наборы файлов JavaScript и CSS. В этом случае объединение всех пакетов ресурсов с обеих сторон в один не имеет смысла, потому что пакеты ресурсов для «переднего» интерфейса не используются «задним» интерфейсом, и это было бы пустой тратой сетевой пропускной способности отправлять ресурсы «заднего» интерфейса при запросе страницы «переднего» интерфейса.
Для решения этой проблемы можно разделить пакеты ресурсов на группы и объединить пакеты ресурсов для каждой группы. Следующая конфигурация демонстрирует, как сгруппировать пакеты ресурсов:
return [
...
// Specify output bundles with groups:
'targets' => [
'allShared' => [
'js' => 'js/all-shared-{hash}.js',
'css' => 'css/all-shared-{hash}.css',
'depends' => [
// Include all assets shared between 'backend' and 'frontend'
'yii\web\YiiAsset',
'app\assets\SharedAsset',
],
],
'allBackEnd' => [
'js' => 'js/all-{hash}.js',
'css' => 'css/all-{hash}.css',
'depends' => [
// Include only 'backend' assets:
'app\assets\AdminAsset'
],
],
'allFrontEnd' => [
'js' => 'js/all-{hash}.js',
'css' => 'css/all-{hash}.css',
'depends' => [], // Include all remaining assets
],
],
...
];
Как видите, пакеты ресурсов разделены на три группы: allShared, allBackEnd и allFrontEnd. Каждая группа зависит от соответствующего набора пакетов ресурсов. Например, allBackEnd зависит от app\assets\AdminAsset. При запуске команды asset с этой конфигурацией она будет объединять пакеты ресурсов в соответствии с указанными выше настройками.
Информация: Вы можете оставить конфигурацию
dependsпустой для одного из целевых пакетов. Таким образом, этот конкретный пакет ресурсов будет зависеть от всех оставшихся пакетов ресурсов, от которых не зависят другие целевые пакеты.
© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-structure-assets.html