You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
366 lines
14 KiB
366 lines
14 KiB
11 years ago
|
Managing assets
|
||
|
===============
|
||
|
|
||
11 years ago
|
> Note: This section is under development.
|
||
11 years ago
|
|
||
11 years ago
|
An asset in Yii is a file that is included into the page. It could be CSS, JavaScript or
|
||
11 years ago
|
any other file. The framework provides many ways to work with assets from basics such as adding `<script src="...">` tags
|
||
|
for a file which is covered by the [View section](view.md), to advanced usage such as publishing files that are not
|
||
|
under the webservers document root, resolving JavaScript dependencies or minifying CSS, which we will cover in the following.
|
||
11 years ago
|
|
||
|
|
||
11 years ago
|
Declaring asset bundles
|
||
|
-----------------------
|
||
11 years ago
|
|
||
11 years ago
|
In order to define a set of assets the 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.
|
||
11 years ago
|
|
||
11 years ago
|
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.
|
||
|
|
||
|
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:
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
<?php
|
||
|
|
||
|
use yii\web\AssetBundle as AssetBundle;
|
||
|
|
||
11 years ago
|
class AppAsset extends AssetBundle
|
||
|
{
|
||
11 years ago
|
public $basePath = '@webroot';
|
||
|
public $baseUrl = '@web';
|
||
|
public $css = [
|
||
|
'css/site.css',
|
||
|
];
|
||
|
public $js = [
|
||
|
];
|
||
|
public $depends = [
|
||
|
'yii\web\YiiAsset',
|
||
|
'yii\bootstrap\BootstrapAsset',
|
||
|
];
|
||
11 years ago
|
}
|
||
|
```
|
||
|
|
||
|
In the above `$basePath` specifies web-accessible directory assets are served from. It is a base for relative
|
||
11 years ago
|
`$css` and `$js` paths i.e. `@webroot/css/site.css` for `css/site.css`. Here `@webroot` is an [alias][] that points to
|
||
11 years ago
|
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`
|
||
11 years ago
|
is an [alias][] that corresponds to your website base URL such as `http://example.com/`.
|
||
11 years ago
|
|
||
11 years ago
|
In case you have asset files under a non web accessible directory, that is the case for any extension, you need
|
||
11 years ago
|
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.
|
||
11 years ago
|
In this case `$basePath` and `$baseUrl` are generated automatically at the time of publishing the asset bundle.
|
||
11 years ago
|
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.
|
||
11 years ago
|
|
||
11 years ago
|
|
||
|
> **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`.
|
||
11 years ago
|
|
||
11 years ago
|
Dependencies on other asset bundles are specified via `$depends` property. It is an array that contains fully qualified
|
||
11 years ago
|
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.
|
||
11 years ago
|
|
||
11 years ago
|
Here [[yii\web\YiiAsset]] adds Yii's JavaScript library while [[yii\bootstrap\BootstrapAsset]] includes
|
||
11 years ago
|
[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
|
||
11 years ago
|
class can be placed anywhere but the convention for it is to be under `assets` directory of the application.
|
||
11 years ago
|
|
||
11 years ago
|
Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to
|
||
11 years ago
|
[[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]]
|
||
11 years ago
|
respectively during registering and publising an asset.
|
||
|
|
||
11 years ago
|
[alias]: basics.md#path-aliases "Yii Path alias"
|
||
|
|
||
|
|
||
11 years ago
|
### 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:
|
||
|
|
||
|
```php
|
||
|
class LanguageAsset extends AssetBundle
|
||
|
{
|
||
11 years ago
|
public $language;
|
||
|
public $sourcePath = '@app/assets/language';
|
||
|
public $js = [
|
||
|
];
|
||
|
|
||
|
public function registerAssetFiles($view)
|
||
|
{
|
||
|
$language = $this->language ? $this->language : Yii::$app->language;
|
||
|
$this->js[] = 'language-' . $language . '.js';
|
||
|
parent::registerAssetFiles($view);
|
||
|
}
|
||
11 years ago
|
}
|
||
|
```
|
||
|
|
||
11 years ago
|
In order to set language use the following code when registering an asset bundle in a view:
|
||
|
|
||
|
```php
|
||
|
LanguageAsset::register($this)->language = $language;
|
||
|
```
|
||
|
|
||
11 years ago
|
|
||
11 years ago
|
Registering asset bundle
|
||
|
------------------------
|
||
|
|
||
11 years ago
|
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:
|
||
11 years ago
|
|
||
|
```php
|
||
|
use app\assets\AppAsset;
|
||
|
AppAsset::register($this);
|
||
|
```
|
||
|
|
||
|
Since we're in a view context `$this` refers to `View` class.
|
||
11 years ago
|
To register an asset inside of a widget, the view instance is available as `$this->view`:
|
||
|
|
||
|
```php
|
||
|
AppAsset::register($this->view);
|
||
|
```
|
||
|
|
||
11 years ago
|
> 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.
|
||
|
|
||
11 years ago
|
|
||
|
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
|
||
|
of basic application it is `config/web.php`:
|
||
|
|
||
|
```php
|
||
|
return [
|
||
|
// ...
|
||
|
'components' => [
|
||
|
'assetManager' => [
|
||
|
'bundles' => [
|
||
|
'yii\web\JqueryAsset' => [
|
||
|
'sourcePath' => null,
|
||
|
'js' => ['//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js']
|
||
|
],
|
||
|
],
|
||
|
],
|
||
|
],
|
||
|
];
|
||
|
```
|
||
|
|
||
11 years ago
|
In the above we're adding asset bundle definitions to the [[yii\web\AssetManager::bundles|bundles]] property of asset manager. Keys are fully
|
||
|
qualified class names to asset bundle classes we want to override while values are key-value arrays of class properties
|
||
11 years ago
|
and corresponding values to set.
|
||
|
|
||
|
Setting `sourcePath` to `null` tells asset manager not to copy anything while `js` overrides local files with a link
|
||
|
to CDN.
|
||
|
|
||
11 years ago
|
|
||
11 years ago
|
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
|
||
11 years ago
|
will always be up to date with source files.
|
||
|
|
||
11 years ago
|
|
||
11 years ago
|
Compressing and combining assets
|
||
|
--------------------------------
|
||
|
|
||
|
To improve application performance you can compress and then combine several CSS or JS files into lesser number of files
|
||
|
therefore reducing number of HTTP requests and overall download size needed to load a web page. Yii provides a console
|
||
|
command that allows you to do both.
|
||
|
|
||
|
### Preparing configuration
|
||
|
|
||
|
In order to use `asset` command you should prepare a configuration first. A template for it can be generated using
|
||
|
|
||
|
```
|
||
|
yii asset/template /path/to/myapp/config.php
|
||
|
```
|
||
|
|
||
|
The template itself looks like the following:
|
||
|
|
||
|
```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 [
|
||
11 years ago
|
// 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}',
|
||
11 years ago
|
// The list of asset bundles to compress:
|
||
|
'bundles' => [
|
||
|
// 'yii\web\YiiAsset',
|
||
|
// 'yii\web\JqueryAsset',
|
||
|
],
|
||
|
// Asset bundle for compression output:
|
||
|
'targets' => [
|
||
|
'app\config\AllAsset' => [
|
||
|
'basePath' => 'path/to/web',
|
||
|
'baseUrl' => '',
|
||
11 years ago
|
'js' => 'js/all-{hash}.js',
|
||
|
'css' => 'css/all-{hash}.css',
|
||
11 years ago
|
],
|
||
|
],
|
||
|
// Asset manager configuration:
|
||
|
'assetManager' => [
|
||
|
'basePath' => __DIR__,
|
||
|
'baseUrl' => '',
|
||
|
],
|
||
11 years ago
|
];
|
||
|
```
|
||
|
|
||
|
In the above keys are `properties` of `AssetController`. `bundles` list contains bundles that should be compressed. These are typically what's used by application.
|
||
|
`targets` contains a list of bundles that define how resulting files will be written. In our case we're writing
|
||
|
everything to `path/to/web` that can be accessed like `http://example.com/` i.e. it is website root directory.
|
||
|
|
||
|
> Note: in the console environment some path aliases like '@webroot' and '@web' may not exist,
|
||
|
so corresponding paths inside the configuration should be specified directly.
|
||
|
|
||
11 years ago
|
JavaScript files are combined, compressed and written to `js/all-{hash}.js` where {hash} is replaced with the hash of
|
||
|
the resulting file.
|
||
11 years ago
|
|
||
11 years ago
|
`jsCompressor` and `cssCompressor` are console commands or PHP callbacks, which should perform JavaScript and CSS files
|
||
|
compression correspondingly. You should adjust these values according to your environment.
|
||
|
By default Yii relies on [Closure Compiler](https://developers.google.com/closure/compiler/) for JavaScript file compression,
|
||
|
and on [YUI Compressor](https://github.com/yui/yuicompressor/). You should install this utilities manually, if you wish to use them.
|
||
|
|
||
11 years ago
|
### Providing compression tools
|
||
|
|
||
|
The command relies on external compression tools that are not bundled with Yii so you need to provide CSS and JS
|
||
|
compressors which are correspondingly specified via `cssCompressor` and `jsCompression` properties. If compressor is
|
||
|
specified as a string it is treated as a shell command template which should contain two placeholders: `{from}` that
|
||
|
is replaced by source file name and `{to}` that is replaced by output file name. Another way to specify compressor is
|
||
|
to use any valid PHP callback.
|
||
|
|
||
|
By default for JavaScript compression Yii tries to use
|
||
|
[Google Closure compiler](https://developers.google.com/closure/compiler/) that is expected to be in a file named
|
||
|
`compiler.jar`.
|
||
|
|
||
|
For CSS compression Yii assumes that [YUI Compressor](https://github.com/yui/yuicompressor/) is looked up in a file
|
||
|
named `yuicompressor.jar`.
|
||
|
|
||
11 years ago
|
In order to compress both JavaScript and CSS, you need to download both tools and place them under the directory
|
||
|
containing your `yii` console bootstrap file. You also need to install JRE in order to run these tools.
|
||
|
|
||
|
You may customize the compression commands (e.g. changing the location of the jar files) in the `config.php` file
|
||
|
like the following,
|
||
11 years ago
|
|
||
11 years ago
|
```php
|
||
|
return [
|
||
11 years ago
|
'cssCompressor' => 'java -jar path.to.file\yuicompressor.jar --type css {from} -o {to}',
|
||
|
'jsCompressor' => 'java -jar path.to.file\compiler.jar --js {from} --js_output_file {to}',
|
||
11 years ago
|
];
|
||
|
```
|
||
11 years ago
|
|
||
|
where `{from}` and `{to}` are tokens that will be replaced with the actual source and target file paths, respectively,
|
||
|
when the `asset` command is compressing every file.
|
||
11 years ago
|
|
||
|
|
||
11 years ago
|
### Performing compression
|
||
|
|
||
|
After configuration is adjusted you can run the `compress` action, using created config:
|
||
|
|
||
|
```
|
||
|
yii asset /path/to/myapp/config.php /path/to/myapp/config/assets_compressed.php
|
||
|
```
|
||
|
|
||
|
Now processing takes some time and finally finished. You need to adjust your web application config to use compressed
|
||
|
assets file like the following:
|
||
|
|
||
|
```php
|
||
|
'components' => [
|
||
11 years ago
|
// ...
|
||
|
'assetManager' => [
|
||
|
'bundles' => require '/path/to/myapp/config/assets_compressed.php',
|
||
|
],
|
||
11 years ago
|
],
|
||
|
```
|
||
|
|
||
|
Using asset converter
|
||
|
---------------------
|
||
|
|
||
|
Instead of using CSS and JavaScript directly often developers are using their improved versions such as LESS or SCSS
|
||
|
for CSS or Microsoft TypeScript for JavaScript. Using these with Yii is easy.
|
||
|
|
||
11 years ago
|
First of all, corresponding compression tools should be installed and should be available from where `yii` console
|
||
11 years ago
|
bootstrap file is. The following lists file extensions and their corresponding conversion tool names that Yii converter
|
||
|
recognizes:
|
||
|
|
||
|
- LESS: `less` - `lessc`
|
||
|
- SCSS: `scss`, `sass` - `sass`
|
||
|
- Stylus: `styl` - `stylus`
|
||
|
- CoffeeScript: `coffee` - `coffee`
|
||
|
- TypeScript: `ts` - `tsc`
|
||
|
|
||
|
So if the corresponding tool is installed you can specify any of these in asset bundle:
|
||
|
|
||
|
```php
|
||
|
class AppAsset extends AssetBundle
|
||
|
{
|
||
11 years ago
|
public $basePath = '@webroot';
|
||
|
public $baseUrl = '@web';
|
||
|
public $css = [
|
||
|
'css/site.less',
|
||
|
];
|
||
|
public $js = [
|
||
|
'js/site.ts',
|
||
|
];
|
||
|
public $depends = [
|
||
|
'yii\web\YiiAsset',
|
||
|
'yii\bootstrap\BootstrapAsset',
|
||
|
];
|
||
11 years ago
|
}
|
||
|
```
|
||
|
|
||
|
In order to adjust conversion tool call parameters or add new ones you can use application config:
|
||
|
|
||
|
```php
|
||
|
// ...
|
||
|
'components' => [
|
||
11 years ago
|
'assetManager' => [
|
||
|
'converter' => [
|
||
|
'class' => 'yii\web\AssetConverter',
|
||
|
'commands' => [
|
||
|
'less' => ['css', 'lessc {from} {to} --no-color'],
|
||
|
'ts' => ['js', 'tsc --out {to} {from}'],
|
||
|
],
|
||
|
],
|
||
|
],
|
||
11 years ago
|
],
|
||
|
```
|
||
|
|
||
|
In the above we've left two types of extra file extensions. First one is `less` that can be specified in `css` part
|
||
|
of an asset bundle. Conversion is performed via running `lessc {from} {to} --no-color` where `{from}` is replaced with
|
||
|
LESS file path while `{to}` is replaced with target CSS file path. Second one is `ts` that can be specified in `js` part
|
||
11 years ago
|
of an asset bundle. The command that is run during conversion is in the same format that is used for `less`.
|