Assets

Asset (ресурсы) в Yii - это файл, на который можно ссылаться на веб-странице. Это может быть файл CSS, файл JavaScript, изображение или видеофайл и т.д. Assets расположены в каталогах, доступных через Web, и обслуживаются непосредственно веб-серверами.

Часто предпочтительнее управлять программными средствами. Например, когда вы используете виджет yii\jui\DatePicker на странице, он автоматически будет включать необходимые файлы CSS и JavaScript, вместо того, чтобы просить вас вручную найти эти файлы и включить их. И когда вы обновляете виджет до новой версии, он автоматически будет использовать новую версию файлов Asset. В этом учебном пособии мы опишем мощную возможность управления Asset, представленную в Yii.

Asset Bundles

Yii управляет ресурсами в пачке ресурсов. Ассортимент ресурсов - это просто набор ресурсов, расположенных в каталоге. Когда вы регистрируете комплект ресурсов в представлении, он будет включать в себя файлы CSS и JavaScript в комплекте на визуализированной веб-странице.

Определение Asset Bundles

Ассортимент ресурсов определяется как 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.
  • css: массив, содержащий список файлов CSS, содержащихся в этом пакете. Формат этого массива такой же, как у js.
  • depends: массива, в котором перечислены названия пакетов ресурсов, от которых зависит этот пакет.
  • jsOptions: задает параметры, которые будут переданы методу yii\web\View::registerJsFile(), когда он будет вызываться для регистрации каждого файла JavaScript в этом пакете.
  • cssOptions: задает параметры, которые будут переданы методу yii\web\View::registerCssFile(), когда он будет вызываться для регистрации каждого файла CSS в этом пакете.
  • publishOptions: задает параметры, которые будут переданы методу yii\web\AssetManager::publish(), когда он будет вызываться для публикации исходных файлов ресурсов в веб-каталоге. Это используется, только если вы укажете свойство sourcePath.

Asset Locations

Assets, основанные на их местоположении, могут быть классифицированы как:

  • Исходные ресурсы: файлы ресурсов расположены вместе с исходным кодом PHP, к которому нельзя напрямую получить доступ через Web. Чтобы использовать исходные ресурсы на странице, они должны быть скопированы в веб-каталог и превращены в так называемые опубликованные ресурсы. Этот процесс называется публикацией ресурсов, который будет описан вкратце.
  • Опубликованные assets: файлы ресурсов расположены в веб-каталоге и поэтому могут быть напрямую доступны через Интернет.
  • Внешние assets: файлы ресурсов расположены на веб-сервере, который отличается от того, который размещен на вашем веб-приложении.

При определении класса пакета ресурсов, если вы укажете свойство sourcePath, это означает, что любые ресурсы, перечисленные с использованием относительных путей, будут рассматриваться как исходные ресурсы. Если вы не укажете это свойство, это означает, что эти ресурсы являются опубликованными ресурсами (поэтому вы должны указать basePath и baseUrl, чтобы Yii знал, где они расположены).

Рекомендуется помещать ресурсы, принадлежащие приложению в веб-каталог, чтобы избежать ненужного процесса публикации ресурсов. Вот почему AppAsset в предыдущем примере указывает basePath вместо sourcePath.

Поскольку для расширений их ресурсы расположены вместе со своим исходным кодом в каталогах, которые не доступны в Интернете, вам нужно указать свойство sourcePath при определении классов пакетов ресурсов для них.

Asset Dependencies

Когда вы включаете несколько CSS- или JavaScript-файлов на веб-страницу, они должны следовать определенному порядку, чтобы избежать переопределения проблем. Например, если вы используете виджет jQuery UI на веб-странице, вы должны убедиться, что jQuery-файл JavaScript включен в jQuery UI-файл JavaScript. Мы называем такое упорядочение зависимостями между ресурсами.

Зависимости ресурсов в основном определяются с помощью свойства yii\web\AssetBundle::$depends. В примере AppAsset пакет ресурсов зависит от двух других пакетов ресурсов: yii\web\YiiAsset и yii\bootstrap\BootstrapAsset, что означает, что файлы CSS и JavaScript в AppAsset будут включены после этих файлов в двух зависимых пакетах.

Asset Options

Вы можете указать свойства cssOptions и jsOptions, чтобы настроить способ включения файлов CSS и JavaScript на страницу. Значения этих свойств будут передаваться в методы yii\web\View::registerCssFile() и yii\web\View::registerJsFile() соответственно, когда они вызываются представлением для включения файлов 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 в головной раздел страницы (по умолчанию файлы JavaScript включены в конце раздела тела), используйте следующую опцию:

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». Указав только параметр публикации, будут опубликованы только поддиректории шрифтов и css.

Bower and NPM Assets

Большинство пакетов JavaScript/CSS управляются Bower или NPM. Если ваше приложение или расширение использует такой пакет, рекомендуется выполнить следующие шаги для управления ресурсами в библиотеке:

  • Измените файл composer.json приложения или расширения и перечислите пакет в require. Для обращения к библиотеке вы должны использовать bower-asset/PackageName (для пакетов Bower) или npm-asset/PackageName (для пакетов NPM).
  • Создайте класс комплекта ресурсов и перечислите файлы JavaScript/CSS, которые вы планируете использовать в своем приложении или расширении. Вы должны указать свойство sourcePath как @bower/PackageName или @npm/PackageName. Это связано с тем, что Composer установит пакет Bower или NPM в каталог, соответствующий этому псевдониму.

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

Чтобы использовать набор ресурсов, зарегистрируйте его в представлении, вызвав метод yii\web\AssetBundle::register(). Например, в шаблоне представления вы можете зарегистрировать пул ресурсов следующим образом:

use app\assets\AppAsset;
AppAsset::register($this);  // $this подключает вид объекта

Если вы регистрируете комплект ресурсов в других местах, вы должны предоставить необходимый объект вида. Например, чтобы зарегистрировать пул ресурсов в классе виджетов, вы можете получить объект вида $this->view.

Когда пакет ресурсов регистрируется с целью, за кулисами Yii регистрирует все свои зависимые пачки ресурсов. И если пакет ресурсов находится в каталоге, недоступном через Интернет, он будет опубликован в веб-каталоге. Позже, когда представление отображает страницу, оно будет генерировать теги <link> и <script> для файлов CSS и JavaScript, перечисленных в зарегистрированных пакетах. Порядок этих тегов определяется зависимостями между зарегистрированными связями и порядком ресурсов, перечисленных в свойствах yii\web\AssetBundle::$css и yii\web\AssetBundle::$js.

Динамические Asset Bundles

Будучи обычным комплектом ресурсов класса 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' // файл, который всегда используется
    ];

    public function init()
    {
        parent::init();
        $this->js[] = 'i18n/' . Yii::$app->language . '.js'; // добавление файла динамически
    }
}

Конкретный пакет ресурсов также может быть скорректирован через экземпляр, возвращенный yii\web\AssetBundle::register(). Например:

use app\assets\SophisticatedAssetBundle;
use Yii;

$bundle = SophisticatedAssetBundle::register(Yii::$app->view);
$bundle->js[] = 'i18n/' . Yii::$app->language . '.js'; // динамическое добавление файла

Настройка Asset Bundles

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,   // не публиковать пакет
                    'js' => [
                        '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
                    ]
                ],
            ],
        ],
    ],
];

Вы можете настроить несколько наборов ресурсов аналогичным образом через пакеты yii\web\AssetManager::$bundles. Ключами массива должны быть имена классов (без обратного слеша) пакетов ресурсов, а значениями массива должны быть соответствующие массивы конфигураций.

'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. На стадии конструктора объекта. Таким образом, любые корректировки, сделанные с объектом bundle после этого, переопределяют настройку отображения на уровне yii\web\AssetManager::$bundles. В частности: корректировки, сделанные внутри yii\web\AssetBundle::init() или над зарегистрированным объектом bundle, будут иметь приоритет над конфигурацией AssetManager. Вот примеры, когда сопоставление, установленное с помощью пакетов yii\web\AssetManager::$bundles, не влияет:


//программный код:

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; // не может обрабатываться `AssetManager`!
    }
}
// ...

$bundle = \app\assets\LargeFileAssetBundle::register(Yii::$app->view);
$bundle->baseUrl = YII_DEBUG ? '@web/large-files': '@web/large-files/minified'; // не может обрабатываться `AssetManager`!


// конфигурация приложения:

return [
    // ...
    'components' => [
        'assetManager' => [
            'bundles' => [
                'app\assets\LanguageAssetBundle' => [
                    'baseUrl' => 'http://some.cdn.com/files/i18n/en' // не оказывает никакого эффекта!
                ],
                'app\assets\LargeFileAssetBundle' => [
                    'baseUrl' => 'http://some.cdn.com/files/large-files' // не оказывает никакого эффекта!
                ],
            ],
        ],
    ],
];

Asset Mapping

Иногда вам может понадобиться «исправить» неверные или  несовместимые пути к файлам ресурсов, используемые в нескольких пакетах ресурсов. Например, в пакете 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.

Публикация Asset

Как уже упоминалось, если пакет ресурсов находится в каталоге, который не доступен в Интернете, его ресурсы будут скопированы в веб-каталог, когда пакет зарегистрирован с видом. Этот процесс называется публикацией ресурсов и выполняется автоматически менеджером ресурсов.

По умолчанию ресурсы публикуются в каталоге @webroot/assets, который соответствует URL @web/assets. Вы можете настроить это местоположение, настроив свойства basePath и baseUrl.

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

return [
    // ...
    'components' => [
        'assetManager' => [
            'linkAssets' => true,
        ],
    ],
];

При указанной конфигурации диспетчер ресурсов создаст символическую ссылку на исходный путь пакета ресурсов во время публикации. Это быстрее, чем копирование файлов, а также гарантирует, что опубликованные ресурсы всегда актуальны.

Удаление кеша

Для веб-приложений, работающих в режиме разработки, широко распространена практика включения кеширования HTTP для ресурсов и других статических ресурсов. Недостатком этой практики является то, что когда вы изменяете ресурс и развертываете его в процессе производства, пользовательский клиент может по-прежнему использовать старую версию из-за кеширования HTTP. Чтобы преодолеть этот недостаток, вы можете использовать функцию устранения кеша, путем настройки 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\web\JqueryAsset: включает в себя файл jquery.js из пакета jQuery Bower.
  • yii\bootstrap\BootstrapAsset: включает в себя файл CSS из основы загрузки Twitter.
  • yii\bootstrap\BootstrapPluginAsset: включает файл JavaScript из платформы Bootstrap Twitter для поддержки плагинов JavaScript для начальной загрузки.
  • yii\jui\JuiAsset: включает в себя файлы CSS и JavaScript из библиотеки пользовательского интерфейса jQuery.

Если ваш код зависит от jQuery, jQuery UI или Bootstrap, вы должны использовать эти предопределенные пакеты ресурсов, а не создавать свои собственные версии.

Asset Conversion

Вместо того, чтобы напрямую писать 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 pre-processor.

Вы можете настроить команды предварительного процессора и поддерживаемый расширенный синтаксис, сконфигурировав 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} в командах будут заменены исходными путями к файлам ресурсов и пути к целевым файлам ресурсов.

Комбинирование и сжатие ресурсов

Веб-страница может содержать множество CSS или файлов JavaScript. Чтобы уменьшить количество HTTP-запросов и общий размер загружаемых файлов, обычно объединяют и сжимают несколько файлов CSS/JavaScript в один или несколько файлов, а затем включают эти сжатые файлы, а не оригинальные в Web Страниц.

Ниже представлен подход к объединению и сжатию файлов ресурсов без необходимости изменения существующего кода приложения.

  1. Найдите в своем приложении все комплекты ресурсов, которые вы планируете объединять и сжимать.
  2. Разделите эти связки на одну или несколько групп. Обратите внимание, что каждый пакет может принадлежать только одной группе.
  3. Комбинируйте/сжимайте файлы CSS в каждой группе в один файл. Сделайте это аналогично для файлов JavaScript.
  4. Определите новый пакет ресурсов для каждой группы:
    • Установите CSS и JS-свойства как объединенные файлы CSS и JavaScript, соответственно.
    • Настройте пакеты ресурсов в каждой группе, установив их свойства css и js пустыми, и установите их свойство depend в качестве нового набора ресурсов, созданного для этой группы.

Используя этот подход, при регистрации комплекта ресурсов в представлении он вызывает автоматическую регистрацию нового набора ресурсов для группы, к которой принадлежит исходный пакет. И, как результат, комбинированные/сжатые файлы ресурсов включаются в страницу вместо исходных.

Пример

Давайте воспользуемся примером, чтобы объяснить этот подход.

Предположим, что ваше приложение имеет две страницы: 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 во всех связках. Обратите внимание, что файлы должны объединяться в порядке, который удовлетворяет зависимостям между пакетами. Например, если Bundle 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']],
            ],
        ],
    ],
];

Приведенная выше конфигурация изменяет поведение по умолчанию для каждого пакета. В частности, Bundle A, B, C и D больше не имеют файлов ресурсов. Теперь все они зависят от всего пакета, который содержит объединенные файлы all-xyz.css и all-xyz.js. Следовательно, для страницы X вместо включения исходных файлов из Bundle A, B и C будут включены только эти два комбинированных файла; То же самое происходит со страницей Y.

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

return [
    'components' => [
        'assetManager' => [
            'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),  
        ],
    ],
];

Использование команд asset

Yii предоставляет консольную команду с именем asset для автоматизации описанного выше подхода.

Чтобы использовать эту команду, вы должны сначала создать файл конфигурации, чтобы описать, какие комплекты ресурсов должны быть объединены, и как они должны быть сгруппированы. Вы можете использовать подкоманду asset/template, чтобы сначала создать шаблон, а затем изменить его в соответствии с вашими потребностями.

yii asset/template assets.php

Команда создает файл с именем assets.php в текущем каталоге. Содержимое этого файла выглядит следующим образом:

<?php
/**
 * Файл конфигурации для консольной команды «yii asset».
 * Обратите внимание, что в среде консоли некоторые псевдонимы пути, такие как «@webroot» и «@web», могут не существовать.
 * Пожалуйста, определите эти псевдонимы отсутствующих путей.
 */
return [
    // Отрегулируйте команду/обратный вызов для сжатия файлов JavaScript:
    'jsCompressor' => 'java -jar compiler.jar --js {from} --js_output_file {to}',
    // Отрегулируйте команду/обратный вызов для сжатия файлов CSS:
    'cssCompressor' => 'java -jar yuicompressor.jar --type css {from} -o {to}',
    // Удалять ли источник ресурсов после сжатия:
    'deleteSource' => false,
    // Список пакетов Asset для сжатия:
    'bundles' => [
        // 'yii\web\YiiAsset',
        // 'yii\web\JqueryAsset',
    ],
    // Комплект Asset для сжатия:
    'targets' => [
        'all' => [
            'class' => 'yii\web\AssetBundle',
            'basePath' => '@webroot/assets',
            'baseUrl' => '@web/assets',
            'js' => 'js/all-{hash}.js',
            'css' => 'css/all-{hash}.css',
        ],
    ],
    // Конфигурация менеджера Asset:
    'assetManager' => [
    ],
];

Вы должны изменить этот файл и указать, какие пакеты вы планируете объединять в опциях bundles. В параметре targets укажите, как расслоения должны быть разбиты на группы. Вы можете указать одну или несколько групп, как указано выше.

Файлы JavaScript объединяются, сжимаются и записываются в js/all-{hash}.js, где {hash} заменяется хэшем результирующего файла.

Параметры jsCompressor и cssCompressor определяют команды консоли или обратные вызовы PHP для выполнения компиляции/сжатия JavaScript и CSS. По умолчанию Yii использует Closure Compiler для комбинирования файлов JavaScript и YUI Compressor для комбинирования файлов CSS. Вы должны установить эти инструменты вручную или настроить эти параметры, чтобы использовать ваши любимые инструменты.

С помощью файла конфигурации вы можете запустить команду актива, чтобы объединить и сжать файлы ресурсов, а затем создать новый файл конфигурации ресурсов активов-prod.php

yii asset assets.php config/assets-prod.php

Сгенерированный конфигурационный файл может быть включен в конфигурацию приложения, как описано в предыдущем подразделе.

Группирование наборов ресурсов

В предыдущем подразделе мы объяснили, как объединить все комплекты ресурсов в единое целое, чтобы минимизировать запросы HTTP для файлов ресурсов, на которые ссылается приложение. Это не всегда желательно на практике. Например, представьте себе, что ваше приложение имеет «передний конец», а также «конец», каждый из которых использует другой набор JavaScript и CSS-файлов. В этом случае объединение всех комплектов ресурсов с обоих концов в единое не имеет смысла, поскольку комплекты ресурсов для «внешнего интерфейса» не используются «задней стороной», и было бы пустой тратой пропускной способности сети для отправки «Back-end» ресурсы, когда запрашивается страница «front end».

Чтобы решить указанную выше проблему, вы можете разделить комплекты ресурсов на группы и объединить пакеты ресурсов для каждой группы. Следующая конфигурация показывает, как вы можете группировать пакеты ресурсов:

return [
    ...
    // Укажите выходные пакеты с группами:
    'targets' => [
        'allShared' => [
            'js' => 'js/all-shared-{hash}.js',
            'css' => 'css/all-shared-{hash}.css',
            'depends' => [
                // Включите все Asset, разделяемые между «backend» и «frontend»
                'yii\web\YiiAsset',
                'app\assets\SharedAsset',
            ],
        ],
        'allBackEnd' => [
            'js' => 'js/all-{hash}.js',
            'css' => 'css/all-{hash}.css',
            'depends' => [
                // Включить только «backend» Asset:
                'app\assets\AdminAsset'
            ],
        ],
        'allFrontEnd' => [
            'js' => 'js/all-{hash}.js',
            'css' => 'css/all-{hash}.css',
            'depends' => [], // Включить все оставшиеся Asset
        ],
    ],
    ...
];

Как вы можете видеть, комплекты ресурсов делятся на три группы: allShared, allBackEnd и allFrontEnd. Каждый из них зависит от соответствующего набора пакетов ресурсов. Например, allBackEnd зависит от app\assets\AdminAsset. При запуске команды ресурса с этой конфигурацией он будет комбинировать пакеты ресурсов в соответствии с приведенной выше спецификацией.