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 directories 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 fully qualified PHP class name (without the leading backslash). An asset bundle class should be [autoloadable](concept-autoloading.md). It usually specifies 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 project template](start-installation.md): ```php 'print'], ]; public $js = [ ]; public $depends = [ 'yii\web\YiiAsset', 'yii\bootstrap\BootstrapAsset', ]; } ``` The above `AppAsset` class specifies that the asset files are located under the `@webroot` directory which corresponds to the URL `@web`; the bundle contains a single CSS file `css/site.css` and no JavaScript file; the bundle depends on two other bundles: [[yii\web\YiiAsset]] and [[yii\bootstrap\BootstrapAsset]]. More detailed explanation about the properties of [[yii\web\AssetBundle]] can be found in the following: * [[yii\web\AssetBundle::sourcePath|sourcePath]]: specifies the root directory that contains the asset files in this bundle. This property should be set if the root directory is not Web accessible. Otherwise, you should set the [[yii\web\AssetBundle::basePath|basePath]] property and [[yii\web\AssetBundle::baseUrl|baseUrl]], instead. [Path aliases](concept-aliases.md) can be used here. * [[yii\web\AssetBundle::basePath|basePath]]: specifies a Web-accessible directory that contains the asset files in this bundle. When you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property, the [asset manager](#asset-manager) will publish the assets in this bundle to a Web-accessible directory and overwrite this property accordingly. You should set this property if your asset files are already in a Web-accessible directory and do not need asset publishing. [Path aliases](concept-aliases.md) can be used here. * [[yii\web\AssetBundle::baseUrl|baseUrl]]: specifies the URL corresponding to the directory [[yii\web\AssetBundle::basePath|basePath]]. Like [[yii\web\AssetBundle::basePath|basePath]], if you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property, the [asset manager](#asset-manager) will publish the assets and overwrite this property accordingly. [Path aliases](concept-aliases.md) can be used here. * [[yii\web\AssetBundle::css|css]]: an array listing the CSS files contained in this bundle. Note that only forward slash "/" should be used as directory separators. Each file can be specified on its own as a string or in an array together with attribute tags and their values. * [[yii\web\AssetBundle::js|js]]: an array listing the JavaScript files contained in this bundle. The format of this array is the same as that of [[yii\web\AssetBundle::css|css]]. Each JavaScript file can be specified in one of the following two formats: - a relative path representing a local JavaScript file (e.g. `js/main.js`). The actual path of the file can be determined by prepending [[yii\web\AssetManager::basePath]] to the relative path, and the actual URL of the file can be determined by prepending [[yii\web\AssetManager::baseUrl]] to the relative path. - an absolute URL representing an external JavaScript file. For example, `http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` or `//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`. * [[yii\web\AssetBundle::depends|depends]]: an array listing the names of the asset bundles that this bundle depends on (to be explained shortly). * [[yii\web\AssetBundle::jsOptions|jsOptions]]: specifies the options that will be passed to the [[yii\web\View::registerJsFile()]] method when it is called to register *every* JavaScript file in this bundle. * [[yii\web\AssetBundle::cssOptions|cssOptions]]: specifies the options that will be passed to the [[yii\web\View::registerCssFile()]] method when it is called to register *every* CSS file in this bundle. * [[yii\web\AssetBundle::publishOptions|publishOptions]]: specifies the options that will be passed to the [[yii\web\AssetManager::publish()]] method when it is called to publish source asset files to a Web directory. This is only used if you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property. ### Asset Locations 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 directory 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 directory 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 directory 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 directories 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 directory 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 directory is 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 a certain order 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 use the format mentioned [[yii\web\AssetBundle::css|above]] or 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 below, 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 wrap the generated CSS link tags within `