Commit 340e2b51 by Qiang Xue

asset guide WIP [skip ci]

parent 0ea8ef71
......@@ -3,7 +3,7 @@ Assets
> Note: This section is under writing.
An asset in Yii is a file that may be referenced or linked on a Web page. It can be a CSS file, a JavaScript file,
An asset in Yii is a file that may be referenced or linked in a Web page. It can be a CSS file, a JavaScript file,
an image or video file, etc. For simple Web applications, assets may be managed manually - you place them in a Web folder
and reference them using their URLs in your Web pages. However, if an application is complicated, or if it uses
many third-party extensions, manual management of assets can soon become a headache. For example, how will you ensure
......@@ -14,32 +14,21 @@ to production? In this section, we will describe the asset management capability
all these problems.
## Asset Types <a name="asset-types"></a>
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 for source assets to be Web accessible, they should be published and turned in *published assets*.
* 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.
As aforementioned, an asset can be a CSS file, a JavaScript file, an image file, and so on, as long as it can
be referenced or linked on a Web page. However, in most cases you would mainly care about CSS files and JavaScript files.
This is because they are the essential pieces in making your Web applications truly dynamic and interactive.
## Asset Bundles <a name="asset-bundles"></a>
Assets are organized in *bundles*. An asset bundle represents a collection of asset files located
under a single directory. It lists which CSS and JavaScript files are in this collection and should be included
in a page when the bundle is registered with it.
in a page where the bundle is used.
You can register an asset bundle in a [view](structure-views.md), which will generate
`<link>` and `<script>` HTML tags on the page to include the CSS and JavaScript files listed in the bundle.
### Defining Asset Bundles <a name="defining-asset-bundles"></a>
It is specified in terms of a PHP class extending from [[yii\web\AssetBundle]]. For example,
the following code defines the asset bundle used by [the basic application template](start-installation.md):
An asset bundle is defined in terms of a PHP class extending from [[yii\web\AssetBundle]].
In this class, you use certain class properties to specify where the asset files are located, what CSS/JavaScript
files the bundle contains, and so on. The class should be namespaced and autoloadable. Its name is used
as the name of the asset bundle.
The following code defines the main asset bundle used by [the basic application template](start-installation.md):
```php
<?php
......@@ -64,19 +53,23 @@ class AppAsset extends AssetBundle
}
```
You should normally specify the values of the following properties in an asset bundle class:
The `AppAsset` class basically specifies that the asset files are located under the `@webroot` directory which
is corresponding to the URL `@web`. The bundle only contains an asset file named `css/site.css`. The bundle
depends on two other bundles: `yii\web\YiiAsset` and `yii\bootstrap\BootstrapAsset`.
The following list explains the possible properties that you can set in an asset bundle class:
* [[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, instead. [Path aliases](concept-aliases.md) can be
used here.
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 base URL that can be prepended to the relative asset
paths listed in [[yii\web\AssetBundle::js|js]] and [[yii\web\AssetBundle::css|css]]. Like [[yii\web\AssetBundle::basePath|basePath]],
* [[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::js|js]]: an array listing the JavaScript files contained in this bundle. Note that only
......@@ -90,90 +83,116 @@ You should normally specify the values of the following properties in an asset b
`//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
* [[yii\web\AssetBundle::css|css]]: an array listing the CSS files contained in this bundle. The format of this array
is the same as that of [[yii\web\AssetBundle::js|js]].
* [[yii\web\AssetBundle::depends|depends]]: an array listing the asset bundles that this bundle depends on.
* [[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 folder.
This is only used if you specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property.
When you include multiple CSS or JavaScript files on a Web page, they have to follow certain orders to avoid
unexpected overriding. In Yii, such ordering is expressed as *dependencies* among assets. For example, the jQuery UI
JavaScript files depend on jQuery. As a result, the jQuery file should be included *before* the jQuery UI JavaScript files
if they are included on a page.
#### Asset Locations <a name="asset-locations"></a>
Assets, based on their location, can be classified as:
## Asset Manager <a name="asset-manager"></a>
* source assets: the asset files are located together with PHP source code which cannot be directly accessed via Web.
In order for source assets to be Web accessible, they should be published and turned in *published assets*.
* 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.
Declaring asset bundles
-----------------------
For assets that directly belong to an application, it is recommended that you place them in a Web folder
to avoid the unnecessary asset publishing process. This is why `AppAsset` specifies [[yii\web\AssetBundle::basePath|basePath]]
without [[yii\web\AssetBundle::sourcePath|sourcePath]].
In order to define a set of assets that belong together and should be used on the website you declare a class called
an "asset bundle". The bundle defines a set of asset files and their dependencies on other asset bundles.
For assets belonging to an [extension](structure-extensions.md), as they are in a folder that is not Web accessible,
you have to specify the [[yii\web\AssetBundle::sourcePath|sourcePath]] property when declaring the corresponding
asset bundle.
Asset files can be located under the webservers accessable directory but also hidden inside of application or vendor
directories. If the latter, the asset bundle will care for publishing them to a directory accessible by the webserver
so they can be included in the website. This feature is useful for extensions so that they can ship all content in one
directory and make installation easier for you.
> 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 keep the asset files
published from their source location. Any content in this folder are considered temporarily and may be subject
to removal.
To define an asset you create a class extending from [[yii\web\AssetBundle]] and set the properties according to your needs.
Here you can see an example asset definition which is part of the basic application template, the
`AppAsset` asset bundle class. It defines assets required application wide:
```php
<?php
#### Asset Dependencies <a name="asset-dependencies"></a>
use yii\web\AssetBundle as AssetBundle;
When you include multiple CSS or JavaScript files on a Web page, they have to follow certain orders to avoid
unexpected overriding. 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 is included.
We call such ordering the dependencies among assets.
class AppAsset extends AssetBundle
Asset dependencies are mainly specified through the [[yii\web\AssetBundle::depends]] property of asset bundles.
In the `AppAsset` example, the asset bundle depends on two other asset bundles: `yii\web\YiiAsset` and
`yii\bootstrap\BootstrapAsset`. And for the jQuery UI example just described, the asset bundle is declared as follows:
```php
class JuiAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $sourcePath = '@bower/jquery-ui';
public $js = [
'jquery-ui.js',
];
public $css = [
'themes/smoothness/jquery-ui.css',
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
'yii\web\JqueryAsset',
];
}
```
In the above `$basePath` specifies web-accessible directory assets are served from. It is a base for relative
`$css` and `$js` paths i.e. `@webroot/css/site.css` for `css/site.css`. Here `@webroot` is an [alias][] that points to
application's `web` directory.
`$baseUrl` is used to specify base URL for the same relative `$css` and `$js` i.e. `@web/css/site.css` where `@web`
is an [alias][] that corresponds to your website base URL such as `http://example.com/`.
## Using Asset Bundles <a name="using-asset-bundles"></a>
In case you have asset files under a non web accessible directory, that is the case for any extension, you need
to specify `$sourcePath` instead of `$basePath` and `$baseUrl`. **All files** from the source path will be copied
or symlinked to the `web/assets` directory of your application prior to being registered.
In this case `$basePath` and `$baseUrl` are generated automatically at the time of publishing the asset bundle.
This is the way to work with assets when you want to publish the whole directory no matter what's in be it images,
webfonts etc.
To use an asset bundle, register it with a [view](structure-views.md) like the following in a view template:
```php
use app\assets\AppAsset;
AppAsset::register($this);
```
> **Note:** do not use the `web/assets` path to put your own files in it. It is meant to be used only for asset publishing.
> When you create files that are already in web accessable directory put them in folders like `web/css` or `web/js`.
where `$this` refers to the [[yii\web\View|view]] object. If you are registering an asset bundle in a PHP class,
you should provide the needed the view object. For example, to register an asset bundle in
a [widget](structure-widgets.md) class, you can obtain the view object by `$this->view`.
Dependencies on other asset bundles are specified via `$depends` property. It is an array that contains fully qualified
class names of bundle classes that should be published in order for this bundle to work properly.
Javascript and CSS files for `AppAsset` are added to the header after the files of [[yii\web\YiiAsset]] and
[[yii\bootstrap\BootstrapAsset]] in this example.
When an asset bundle is registered, behind the scene Yii will register all its dependent asset bundles. And
when a page is being rendered, `<link>` and `<script>` tags will be generated in the page for the CSS and
JavaScript files in every registered asset bundle. During this process, if an asset bundle is not in
a Web accessible folder, it will be published first.
Here [[yii\web\YiiAsset]] adds Yii's JavaScript library while [[yii\bootstrap\BootstrapAsset]] includes
[Bootstrap](http://getbootstrap.com) frontend framework.
Asset bundles are regular classes so if you need to define another one, just create alike class with unique name. This
class can be placed anywhere but the convention for it is to be under `assets` directory of the application.
## Asset Publishing <a name="asset-publishing"></a>
Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to
[[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]]
respectively during registering and publishing an asset. For more details on this see [Setting special options](#setting-special-options).
When an asset file is located in a folder that is not Web accessible, it should be copied to a Web accessible
folder before being referenced or linked in a Web page. This process is called *asset publishing*, and is done
automatically by the [[yii\web\AssetManager|asset manager]].
[alias]: basics.md#path-aliases "Yii Path alias"
### Enabling symlinks
Asset manager is able to use symlinks instead of copying files. It is turned off by default since symlinks are often
disabled on shared hosting. If your hosting environment supports symlinks you certainly should enable the feature via
application config:
### Language-specific asset bundle
```php
return [
// ...
'components' => [
'assetManager' => [
'linkAssets' => true,
],
],
];
```
There are two main benefits in enabling it. First it is faster since no copying is required and second is that assets
will always be up to date with source files.
#### Language-specific asset bundle
If you need to define an asset bundle that includes JavaScript file depending on the language you can do it the
following way:
......@@ -203,33 +222,7 @@ LanguageAsset::register($this);
```
Registering asset bundle
------------------------
Asset bundle classes are typically registered in view files or [widgets](view.md#widgets) that depend on the css or
javascript files for providing its functionality. An exception to this is the `AppAsset` class defined above which is
added in the applications main layout file to be registered on any page of the application.
Registering an asset bundle is as simple as calling the [[yii\web\AssetBundle::register()|register()]] method:
```php
use app\assets\AppAsset;
AppAsset::register($this);
```
Since we're in a view context `$this` refers to `View` class.
To register an asset inside of a widget, the view instance is available as `$this->view`:
```php
AppAsset::register($this->view);
```
> Note: If there is a need to modify third party asset bundles it is recommended to create your own bundles depending
on third party ones and use CSS and JavaScript features to modify behavior instead of editing files directly or
copying them over.
Setting special options <a name="setting-special-options"></a>
-----------------------
#### Setting special options <a name="setting-special-options"></a>
Asset bundles allow setting specific options for the files to be published.
This can be done by configuring the [[yii\web\AssetBundle::$jsOptions|$jsOptions]],
......@@ -266,8 +259,7 @@ Some of these options are described in the following:
- For further javascript options, see [[yii\helpers\Html::jsFile()]].
Overriding asset bundles
------------------------
#### Overriding asset bundles
Sometimes you need to override some asset bundles application wide. A good example is loading jQuery from CDN instead
of your own server. In order to do it we need to configure `assetManager` application component via config file. In case
......@@ -307,26 +299,6 @@ to CDN.
],
```
Enabling symlinks
-----------------
Asset manager is able to use symlinks instead of copying files. It is turned off by default since symlinks are often
disabled on shared hosting. If your hosting environment supports symlinks you certainly should enable the feature via
application config:
```php
return [
// ...
'components' => [
'assetManager' => [
'linkAssets' => true,
],
],
];
```
There are two main benefits in enabling it. First it is faster since no copying is required and second is that assets
will always be up to date with source files.
Compressing and combining assets
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment