Assets ====== An asset in Yii is a file that may be referenced in a Web page. It can be a CSS file, a JavaScript file, an image or video file, etc. Assets are located in Web-accessible folders and are directly served by Web servers. It is often preferable to manage assets programmatically. For example, when you use the [[yii\jui\DatePicker]] widget in a page, it will automatically include the required CSS and JavaScript files, instead of asking you to manually find these files and include them. And when you upgrade the widget to a new version, it will automatically use the new version of the asset files. In this tutorial, we will describe the powerful asset management capability provided in Yii. ## Asset Bundles Yii manages assets in the unit of *asset bundle*. An asset bundle is simply a collection of assets located in a directory. When you register an asset bundle in a [view](structure-views.md), it will include the CSS and JavaScript files in the bundle in the rendered Web page. ## Defining Asset Bundles Asset bundles are specified as PHP classes extending from [[yii\web\AssetBundle]]. The name of a bundle is simply its corresponding PHP class name which should be [autoloadable](concept-autoloading.md). In an asset bundle class, you would typically specify where the assets are located, what CSS and JavaScript files the bundle contains, and how the bundle depends on other bundles. The following code defines the main asset bundle used by [the basic application template](start-installation.md): ```php Assets, based on their location, can be classified as: * source assets: the asset files are located together with PHP source code which cannot be directly accessed via Web. In order to use source assets in a page, they should be copied to a Web folder and turned into the so-called published assets. This process is called *asset publishing* which will be described in detail shortly. * published assets: the asset files are located in a Web folder and can thus be directly accessed via Web. * external assets: the asset files are located on a Web server that is different from the one hosting your Web application. When defining an asset bundle class, if you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property, it means any assets listed using relative paths will be considered as source assets. If you do not specify this property, it means those assets are published assets (you should therefore specify [[yii\web\AssetBundle::basePath|basePath]] and [[yii\web\AssetBundle::baseUrl|baseUrl]] to let Yii know where they are located.) It is recommended that you place assets belonging to an application in a Web folder to avoid the unnecessary asset publishing process. This is why `AppAsset` in the prior example specifies [[yii\web\AssetBundle::basePath|basePath]] instead of [[yii\web\AssetBundle::sourcePath|sourcePath]]. For [extensions](structure-extensions.md), because their assets are located together with their source code in folders that are not Web accessible, you have to specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property when defining asset bundle classes for them. > Note: Do not use `@webroot/assets` as the [[yii\web\AssetBundle::sourcePath|source path]]. This folder is used by default by the [[yii\web\AssetManager|asset manager]] to save the asset files published from their source location. Any content in this folder are considered temporarily and may be subject to removal. ### Asset Dependencies When you include multiple CSS or JavaScript files in a Web page, they have to follow certain orders to avoid overriding issues. For example, if you are using a jQuery UI widget in a Web page, you have to make sure the jQuery JavaScript file is included before the jQuery UI JavaScript file. We call such ordering the dependencies among assets. Asset dependencies are mainly specified through the [[yii\web\AssetBundle::depends]] property. In the `AppAsset` example, the asset bundle depends on two other asset bundles: [[yii\web\YiiAsset]] and [[yii\bootstrap\BootstrapAsset]], which means the CSS and JavaScript files in `AppAsset` will be included *after* those files in the two dependent bundles. Asset dependencies are transitive. This means if bundle A depends on B which depends on C, A will depend on C, too. ### Asset Options You can specify the [[yii\web\AssetBundle::cssOptions|cssOptions]] and [[yii\web\AssetBundle::jsOptions|jsOptions]] properties to customize the way that CSS and JavaScript files are included in a page. The values of these properties will be passed to the [[yii\web\View::registerCssFile()]] and [[yii\web\View::registerJsFile()]] methods, respectively, when they are called by the [view](structure-views.md) to include CSS and JavaScript files. > Note: The options you set in a bundle class apply to *every* CSS/JavaScript file in the bundle. If you want to use different options for different files, you should create separate asset bundles, and use one set of options in each bundle. For example, to conditionally include a CSS file for browsers that are IE9 or above, you can use the following option: ```php public $cssOptions = ['condition' => 'lte IE9']; ``` This will cause a CSS file in the bundle to be included using the following HTML tags: ```html ``` To include a JavaScript file in the head section of a page (by default, JavaScript files are included at the end of the body section), use the following option: ```php public $jsOptions = ['position' => \yii\web\View::POS_HEAD]; ``` ### Bower and NPM Assets Most JavaScript/CSS package are managed by [Bower](http://bower.io/) and/or [NPM](https://www.npmjs.org/). If your application or extension is using such a package, it is recommended that you follow these steps to manage the assets in the library: 1. Modify the `composer.json` file of your application or extension and list the package in the `require` entry. You should use `bower-asset/PackageName` (for Bower packages) or `npm-asset/PackageName` (for NPM packages) to refer to the library. 2. Create an asset bundle class and list the JavaScript/CSS files that you plan to use in your application or extension. You should specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property as `@bower/PackageName` or `@npm/PackageName`. This is because Composer will install the Bower or NPM package in the folder corresponding to this alias. > Note: Some packages may put all their distributed files in a subdirectory. If this is the case, you should specify the subdirectory as the value of [[yii\web\AssetBundle::sourcePath|sourcePath]]. For example, [[yii\web\JqueryAsset]] uses `@bower/jquery/dist` instead of `@bower/jquery`. ## Using Asset Bundles To use an asset bundle, register it with a [view](structure-views.md) by calling the [[yii\web\AssetBundle::register()]] method. For example, in a view template you can register an asset bundle like the following: ```php use app\assets\AppAsset; AppAsset::register($this); // $this represents the view object ``` If you are registering an asset bundle in other places, you should provide the needed view object. For example, to register an asset bundle in a [widget](structure-widgets.md) class, you can get the view object by `$this->view`. When an asset bundle is registered with a view, behind the scene Yii will register all its dependent asset bundles. And if an asset bundle is located in a folder inaccessible through the Web, it will be published to a Web folder. Later when the view renders a page, it will generate `` and `