|
|
|
Assets
|
|
|
|
======
|
|
|
|
|
|
|
|
Un asset en Yii es un archivo al que se puede hacer referencia en una página Web. Puede ser un archivo CSS, un archivo
|
|
|
|
JavaScript, una imagen o un archivo de video, etc. Los assets se encuentran en los directorios públicos de la web y se
|
|
|
|
sirven directamente por los servidores Web.
|
|
|
|
|
|
|
|
A menudo es preferible gestionar los assets mediante programación. Por ejemplo, cuando se usa el widget
|
|
|
|
[[yii\jui\DatePicker]] en una página, éste incluirá automáticamente los archivos CSS y JavaScript requeridos, en vez
|
|
|
|
de tener que buscar los archivos e incluirlos manualmente. Y cuando se actualice el widget a una nueva versión, ésta
|
|
|
|
usará de forma automática la nueva versión de los archivos asset.
|
|
|
|
En este tutorial, se describirá la poderosa capacidad que proporciona la gestión de assets en Yii.
|
|
|
|
|
|
|
|
## Asset Bundles <span id="asset-bundles"></span>
|
|
|
|
|
|
|
|
Yii gestiona los assets en unidades de *asset bundle*. Un asset bundle es simplemente un conjunto de assets
|
|
|
|
localizados en un directorio. Cuando se registra un asset bundle en una [vista](structure-views.md), éste incluirá los
|
|
|
|
archivos CSS y JavaScript del bundle en la página Web renderizada.
|
|
|
|
|
|
|
|
## Definición de Asset Bundles <span id="defining-asset-bundles"></span>
|
|
|
|
|
|
|
|
Los asset bundles son descritos como clases PHP que extienden a [[yii\web\AssetBundle]]. El nombre del bundle es
|
|
|
|
simplemente su correspondiente nombre de la classe PHP que debe ser [autocargable](concept-autoloading.md). En una
|
|
|
|
clase asset bundle, lo más habitual es especificar donde se encuentran los archivos asset, que archivos CSS y
|
|
|
|
JavaScript contiene el bundle, y como depende este bundle de otros bundles.
|
|
|
|
|
|
|
|
El siguiente código define el asset bundle principal que se usa en
|
|
|
|
[la plantilla de aplicación básica](start-installation.md):
|
|
|
|
|
|
|
|
```php
|
|
|
|
<?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',
|
|
|
|
];
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
La anterior clase `AppAsset` especifica que los archivos asset se encuentran en el directorio `@webroot` que
|
|
|
|
corresponde a la URL `@web`; el bundle contiene un único archivo CSS `css/site.css` y ningún archivo JavaScript;
|
|
|
|
el bundle depende de otros dos bundles: [[yii\web\YiiAsset]] y [[yii\bootstrap\BootstrapAsset]].
|
|
|
|
A continuación se explicarán más detalladamente las propiedades del [[yii\web\AssetBundle]]:
|
|
|
|
|
|
|
|
* [[yii\web\AssetBundle::sourcePath|sourcePath]]: especifica el directorio raíz que contiene los archivos asset en el
|
|
|
|
bundle. Si no, se deben especificar las propiedades [[yii\web\AssetBundle::basePath|basePath]] y
|
|
|
|
[[yii\web\AssetBundle::baseUrl|baseUrl]], en su lugar. Se pueden usar [alias de ruta](concept-aliases.md).
|
|
|
|
* [[yii\web\AssetBundle::basePath|basePath]]: especifica el directorio Web público que contiene los archivos assets de
|
|
|
|
este bundle. Cuando se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de
|
|
|
|
assets](#asset-manager) publicará los assets de este bundle en un directorio Web público y sobrescribirá la
|
|
|
|
propiedad en consecuencia. Se debe establecer esta propiedad si los archivos asset ya se encuentran en un directorio
|
|
|
|
Web público y no necesitan ser publicados. Se pueden usar [alias de ruta](concept-aliases.md).
|
|
|
|
* [[yii\web\AssetBundle::baseUrl|baseUrl]]: especifica la URL correspondiente al directorio
|
|
|
|
[[yii\web\AssetBundle::basePath|basePath]]. Como en [yii\web\AssetBundle::basePath|basePath]], si se especifica la
|
|
|
|
propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de assets](#asset-manager) publicara los assets
|
|
|
|
y sobrescribirá esta propiedad en consecuencia. Se pueden usar [alias de ruta](concept-aliases.md).
|
|
|
|
* [[yii\web\AssetBundle::js|js]]: un array lista los archivos JavaScript que contiene este bundle. Tenga en cuenta que
|
|
|
|
solo deben usarse las barras invertidas "/" como separadores de directorios. Cada archivo Javascript se puede
|
|
|
|
especificar en uno de los siguientes formatos:
|
|
|
|
- una ruta relativa que represente un archivo local JavaScript (ej. `js/main.js`). La ruta actual del fichero
|
|
|
|
se puede determinar anteponiendo [[yii\web\AssetManager::basePath]] a la ruta relativa, y la URL actual de un
|
|
|
|
archivo puede ser determinada anteponiendo [[yii\web\AssetManager::baseUrl]] a la ruta relativa.
|
|
|
|
- una URL absoluta que represente un archivo JavaScript externo. Por ejemplo,
|
|
|
|
`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` o
|
|
|
|
`//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
|
|
|
|
* [[yii\web\AssetBundle::css|css]]: un array que lista los archivos CSS que contiene este bundle. El formato de este
|
|
|
|
array es el mismo que el de [[yii\web\AssetBundle::js|js]].
|
|
|
|
* [[yii\web\AssetBundle::depends|depends]]: un array que lista los nombres de los asset bundles de los que depende este
|
|
|
|
asset bundle (para explicarlo brevemente).
|
|
|
|
* [[yii\web\AssetBundle::jsOptions|jsOptions]]: especifica las opciones que se enviarán al método
|
|
|
|
[[yii\web\View::registerJsFile()]] cuando se le llame para registrar *todos* los archivos JavaScript de este bundle.
|
|
|
|
* [[yii\web\AssetBundle::cssOptions|cssOptions]]: especifica las opciones que se enviarán al método
|
|
|
|
[[yii\web\View::registerCssFile()]] cuando se le llame para registrar *todos* los archivos CSS de este bundle.
|
|
|
|
* [[yii\web\AssetBundle::publishOptions|publishOptions]]: especifica las opciones que se enviarán al método
|
|
|
|
[[yii\web\AssetManager::publish()]] cuando se le llame para publicar los archivos de los assets fuente a un
|
|
|
|
directorio Web.
|
|
|
|
Solo se usa si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]].
|
|
|
|
|
|
|
|
### Ubicación de los Assets <span id="asset-locations"></span>
|
|
|
|
|
|
|
|
Según la localización de los assets, se pueden clasificar como:
|
|
|
|
|
|
|
|
* assets fuente (source assets): los assets se encuentran junto con el código fuente PHP, al que no se puede acceder
|
|
|
|
directamente a través de la Web. Para usar los assets fuente en una página, deben ser copiados en un directorio
|
|
|
|
público y transformados en los llamados assets publicados. El proceso se llama *publicación de assets* que será
|
|
|
|
descrito a continuación.
|
|
|
|
* assets publicados (published assets): los archivos assets se encuentran en el directorio Web y son accesibles vía Web.
|
|
|
|
* assets externos (external assets): los archivos assets se encuentran en un servidor Web diferente al de la aplicación.
|
|
|
|
|
|
|
|
Cuando se define una clase asset bundle, si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]],
|
|
|
|
significa que cualquier asset listado que use rutas relativas será considerado como un asset fuente. Si no se
|
|
|
|
especifica la propiedad, significa que los assets son assets publicados (se deben especificar
|
|
|
|
[[yii\web\AssetBundle::basePath|basePath]] y
|
|
|
|
[[yii\web\AssetBundle::baseUrl|baseUrl]] para hacerle saber a Yii dónde se encuentran.)
|
|
|
|
|
|
|
|
Se recomienda ubicar los assets que correspondan a la aplicación en un directorio Web para evitar publicaciones de
|
|
|
|
assets innecesarias. Por esto en el anterior ejemplo `AppAsset` especifica [[yii\web\AssetBundle::basePath|basePath]]
|
|
|
|
en vez de [[yii\web\AssetBundle::sourcePath|sourcePath]].
|
|
|
|
|
|
|
|
Para las [extensiones](structure-extensions.md), por el hecho de que sus assets se encuentran junto con el código
|
|
|
|
fuente, en directorios que no son accesibles para la Web, se tiene que especificar la propiedad
|
|
|
|
[[yii\web\AssetBundle::sourcePath|sourcePath]] cuando se definan clases asset bundle para ellas.
|
|
|
|
|
|
|
|
> Nota: No se debe usar `@webroot/assets` como [yii\web\AssetBundle::sourcePath|source path]]. Este directorio se usa
|
|
|
|
por defecto por el [[yii\web\AssetManager|asset manager]] para guardar los archivos asset publicados temporalmente y
|
|
|
|
pueden ser eliminados.
|
|
|
|
|
|
|
|
### Dependencias de los Asset <span id="asset-dependencies"></span>
|
|
|
|
|
|
|
|
Cuando se incluyen múltiples archivos CSS o JavaScript en una página Web, tienen que cumplir ciertas órdenes para
|
|
|
|
evitar problemas de sobrescritura. Por ejemplo, si se usa un widget jQuery UI en una página Web, tenemos que
|
|
|
|
asegurarnos de que el archivo JavaScript jQuery se incluya antes que el archivo JavaScript jQuery UI. A esto se le
|
|
|
|
llama ordenar las dependencias entre archivos.
|
|
|
|
|
|
|
|
Las dependencias de los assets se especifican principalmente a través de la propiedad [[yii\AssetBundle::depends]].
|
|
|
|
En el ejemplo `AppAsset`, el asset bundle depende de otros dos asset bundles [[yii\web\YiiAsset]] y
|
|
|
|
[[yii\bootstrap\BootstrapAsset]], que significa que los archivos CSS y JavaScript en `AppAsset` se incluirán *después*
|
|
|
|
que los archivos de los dos bundles dependientes.
|
|
|
|
|
|
|
|
Las dependencias son transitivas. Esto significa, que si un bundle A depende de un bundle B que depende de C, A
|
|
|
|
dependerá de C, también.
|
|
|
|
|
|
|
|
### Opciones de los Assets <span id="asset-options"></span>
|
|
|
|
|
|
|
|
Se pueden especificar las propiedades [[yii\web\AssetBundle::cssOptions|cssOptions]] y
|
|
|
|
[[yii\web\AssetBundle::jsOptions|jsOptions]] para personalizar la forma en que los archivos CSS y JavaScript serán
|
|
|
|
incluidos en una página. Los valores de estas propiedades serán enviadas a los métodos
|
|
|
|
[[yii\web\View::registerCssFile()]] y [[yii\web\View::registerJsFile()]], respectivamente cuando las
|
|
|
|
[vistas](structure-views.md) los llamen para incluir los archivos CSS y JavaScript.
|
|
|
|
|
|
|
|
> Nota: Las opciones que se especifican en una clase bundle se aplican a *todos* los archivos CSS/JavaScript de un
|
|
|
|
bundle. Si se quiere usar diferentes opciones para diferentes archivos, se deben crear assets bundles separados y
|
|
|
|
usar un conjunto de opciones para cada bundle.
|
|
|
|
|
|
|
|
Por ejemplo, para incluir una archivo CSS condicionalmente para navegadores que como IE9 o anteriores, se puede usar la
|
|
|
|
siguiente opción:
|
|
|
|
|
|
|
|
```php
|
|
|
|
public $cssOptions = ['condition' => 'lte IE9'];
|
|
|
|
```
|
|
|
|
|
|
|
|
Esto provoca que un archivo CSS dentro de un bundle sea incluido usando los siguientes tags HTML:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<!--[if lte IE9]>
|
|
|
|
<link rel="stylesheet" href="path/to/foo.css">
|
|
|
|
<![endif]-->
|
|
|
|
```
|
|
|
|
|
|
|
|
Para envolver el tag del enlace con `<noscript>` se puede usar el siguiente código:
|
|
|
|
|
|
|
|
```php
|
|
|
|
public $cssOptions = ['noscript' => true];
|
|
|
|
```
|
|
|
|
|
|
|
|
Para incluir un archivo JavaScript en la sección cabecera (head) de una página (por defecto, los archivos JavaScript se
|
|
|
|
incluyen al final de la sección cuerpo(body)), se puede usar el siguiente código:
|
|
|
|
|
|
|
|
```php
|
|
|
|
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
|
|
|
|
```
|
|
|
|
|
|
|
|
Por defecto, cuando un asset bundle está siendo publicado, todos los contenidos del directorio especificado por [[yii\web\AssetBundle::sourcePath]]
|
|
|
|
serán publicados. Puedes personalizar este comportamiento configurando la propiedad [[yii\web\AssetBundle::publishOptions|publishOptions]]. Por
|
|
|
|
ejemplo, públicar solo uno o unos pocos subdirectorios de [[yii\web\AssetBundle::sourcePath]], puedes hacerlo de la siguiente manera en la clase
|
|
|
|
asset bundle:
|
|
|
|
|
|
|
|
```php
|
|
|
|
<?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 function init()
|
|
|
|
{
|
|
|
|
parent::init();
|
|
|
|
$this->publishOptions['beforeCopy'] = function ($from, $to) {
|
|
|
|
$dirname = basename(dirname($from));
|
|
|
|
return $dirname === 'fonts' || $dirname === 'css';
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
El ejemplo anterior define un asset bundle para el ["fontawesome" package](http://fontawesome.io/). Especificando
|
|
|
|
la opción de publicación `beforeCopy`, solo los subdirectorios `fonts` y `css` serán publicados.
|
|
|
|
|
|
|
|
### Bower y NPM Assets <span id="bower-npm-assets"></span>
|
|
|
|
|
|
|
|
La mayoría de paquetes JavaScript/CSS se gestionan con [Bower](http://bower.io/) y/o [NPM](https://www.npmjs.org/).
|
|
|
|
Si tu aplicación o extensión usa estos paquetes, se recomienda seguir los siguientes pasos para gestionar los assets en
|
|
|
|
la librería:
|
|
|
|
|
|
|
|
1. Modificar el archivo `composer.json` de tu aplicación o extensión e introducir el paquete en la lista `require`.
|
|
|
|
Se debe usar `bower-asset/PackageName` (para paquetes Bower) o `npm-asset/PackageName` (para paquetes NPM) para
|
|
|
|
referenciar la librería.
|
|
|
|
2. Crear una clase asset bundle y listar los archivos JavaScript/CSS que se planea usar en la aplicación o extensión.
|
|
|
|
Se debe especificar la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]] como `@bower\PackageName` o
|
|
|
|
`@npm\PackageName`. Esto se debe a que Composer instalará el paquete Bower o NPM en el correspondiente directorio de
|
|
|
|
este alias.
|
|
|
|
|
|
|
|
> Nota: Algunos paquetes pueden distribuir sus archivos en subdirectorios. Si es el caso, se debe especificar el
|
|
|
|
subdirectorio como valor del [[yii\web\AssetBundle::sourcePath|sourcePath]]. Por ejemplo, [[yii\web\JqueryAsset]]
|
|
|
|
usa `@bower/jquery/dist` en vez de `@bower/jquery`.
|
|
|
|
|
|
|
|
## Uso de Asset Bundles <span id="using-asset-bundles"></span>
|
|
|
|
|
|
|
|
Para usar un asset bundle, debe registrarse con una [vista](structure-views.md) llamando al método
|
|
|
|
[[yii\web\AssetBundle::register()]]. Por ejemplo, en plantilla de vista se puede registrar un asset bundle como en el
|
|
|
|
siguiente ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
use app\assets\AppAsset;
|
|
|
|
AppAsset::register($this); // $this representa el objeto vista
|
|
|
|
```
|
|
|
|
|
|
|
|
> Información: El método [[yii\web\AssetBundle::register()]] devuelve un objeto asset bundle que contiene la
|
|
|
|
información acerca de los assets publicados, tales como [[yii\web\AssetBundle::basePath|basePath]] o
|
|
|
|
[[yii\web\AssetBundle::baseUrl|baseUrl]].
|
|
|
|
|
|
|
|
Si se registra un asset bundle en otro lugar, se debe proporcionar la vista necesaria al objeto. Por ejemplo, para
|
|
|
|
registrar un asset bundle en una clase [widget](structure-widgets.md), se puede obtener el objeto vista mediante
|
|
|
|
`$this->view`.
|
|
|
|
|
|
|
|
Cuando se registra un asset bundle con una vista, por detrás, Yii registrará todos sus asset bundles dependientes.
|
|
|
|
Y si un asset bundle se encuentra en un directorio inaccesible por la Web, éste será publicado a un directorio Web
|
|
|
|
público. Después cuando la vista renderice una página, se generarán las etiquetas (tags) `<link>` y `<script>` para
|
|
|
|
los archivos CSS y JavaScript listados en los bundles registrados. El orden de estas etiquetas será determinado por
|
|
|
|
las dependencias entre los bundles registrados y los otros assets listados en las propiedades
|
|
|
|
[[yii\web\AssetBundle::css]] y [[yii\web\AssetBundle::js]].
|
|
|
|
|
|
|
|
### Personalización de Asset Bundles <span id="customizing-asset-bundles"></span>
|
|
|
|
|
|
|
|
Yii gestiona los asset bundles a través de un componente de aplicación llamado `assetManager` que está implementado
|
|
|
|
por [[yii\web\AssetManager]]. Configurando la propiedad [[yii\web\AssetManager::bundles]], se puede personalizar el
|
|
|
|
comportamiento (behavior) de un asset bundle. Por ejemplo, de forma predeterminada, el asset bundle [[yii\web\Jquery]]
|
|
|
|
, utiliza el archivo `jquery.js` desde el paquete Bower instalado. Para mejorar la disponibilidad y el rendimiento se
|
|
|
|
puede querer usar la versión alojada por Google. Ésta puede ser obtenida configurando `assetManager` en la
|
|
|
|
configuración de la aplicación como en el siguiente ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
// ...
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'bundles' => [
|
|
|
|
'yii\web\JqueryAsset' => [
|
|
|
|
'sourcePath' => null, // no publicar el bundle
|
|
|
|
'js' => [
|
|
|
|
'//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
|
|
|
|
]
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Del mismo modo, se pueden configurar múltiples asset bundles a través de [[yii\web\AssetManager::bundles]]. Las claves
|
|
|
|
del array deben ser los nombres de clase (sin la primera barra invertida) de los asset bundles, y los valores del array
|
|
|
|
deben ser las correspondientes [configuraciones de arrays](concept-configurations.md).
|
|
|
|
|
|
|
|
> Consejo: Se puede elegir condicionalmente que assets se van a usar en un asset bundle. El siguiente ejemplo
|
|
|
|
muestra como usar `jquery.js` en el entorno de desarrollo y `jquery.min.js` en los otros casos:
|
|
|
|
>
|
|
|
|
> ```php
|
|
|
|
> 'yii\web\JqueryAsset' => [
|
|
|
|
> 'js' => [
|
|
|
|
> YII_ENV_DEV ? 'jquery.js' : 'jquery.min.js'
|
|
|
|
> ]
|
|
|
|
> ],
|
|
|
|
> ```
|
|
|
|
|
|
|
|
Se puede deshabilitar uno o más asset bundles asociando `false` a los nombres de los asset bundles que se quieran
|
|
|
|
deshabilitar. Cuando se registra un asset bundle deshabilitado con una vista, ninguno de sus bundles dependientes será
|
|
|
|
registrado, y la vista tampoco incluirá ningún asset del bundle en la página que se renderice.
|
|
|
|
Por ejemplo, para deshabilitar [[yii\web\JqueryAsset]], se puede usar la siguiente configuración:
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
// ...
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'bundles' => [
|
|
|
|
'yii\web\JqueryAsset' => false,
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Además se pueden deshabilitar *todos* los asset bundles asignando `false` a [[yii\web\AssetManager::bundles]].
|
|
|
|
|
|
|
|
### Mapeo de Assets (Asset Mapping) <span id="asset-mapping"></span>
|
|
|
|
|
|
|
|
A veces se puede querer "arreglar" rutas de archivos incorrectos/incompatibles usadas en múltiples asset bundles.
|
|
|
|
Por ejemplo, el bundle A usa `jquery.min.js` con versión 1.11.1, y el bundle B usa `jquery.js` con versión 2.11.1.
|
|
|
|
Mientras que se puede solucionar el problema personalizando cada bundle, una forma más fácil, es usar la
|
|
|
|
característica *asset map* para mapear los assets incorrectos a los deseados. Para hacerlo, se tiene que configurar la
|
|
|
|
propiedad [[yii\web\AssetManager::assetMap]] como en el siguiente ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
// ...
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'assetMap' => [
|
|
|
|
'jquery.js' => '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Las claves de [[yii\web\AssetManager::assetMap|assetmMap]] son los nombres de los assets que se quieren corregir,
|
|
|
|
y los valores son las rutas de los assets deseados. Cuando se registra un asset bundle con una vista, cada archivo de
|
|
|
|
asset relativo de [[yii\web\AssetBundle::css|css]] y [[yii\web\AssetBundle::js|js]] serán contrastados con este mapa.
|
|
|
|
Si se detecta que alguna de estas claves es la última parte de un archivo asset (prefijado con
|
|
|
|
[[yii\web\AssetBundle::sourcePath]], si esta disponible), el correspondiente valor reemplazará el asset y será
|
|
|
|
registrado con la vista.
|
|
|
|
Por ejemplo, un archivo asset `mi/ruta/a/jquery.js` concuerda con la clave `jquery.js`.
|
|
|
|
|
|
|
|
> Nota: Sólo los assets especificados usando rutas relativas están sujetos al mapeo de assets. Y las rutas de los
|
|
|
|
assets destino deben ser tanto URLs absolutas o rutas relativas a [[yii\web\AssetManager::basePath]].
|
|
|
|
|
|
|
|
### Publicación de Asset <span id="asset-publishing"></span>
|
|
|
|
|
|
|
|
Como se ha comentado anteriormente, si un asset bundle se encuentra en un directorio que no es accesible por la Web,
|
|
|
|
este asset será copiado a un directorio Web cuando se registre el bundle con una vista. Este proceso se llama
|
|
|
|
*publicación de assets*, y se efectúa automáticamente por el [[yii\web\AssetManager|asset manager]].
|
|
|
|
|
|
|
|
De forma predeterminada, los assets se publican en el directorio `@webroot/assets` cuando corresponden a la URL
|
|
|
|
`@web\assets`. Se puede personalizar esta ubicación configurando las propiedades
|
|
|
|
[[yii\web\AssetManager::basePath|basePath]] y [[yii\web\AssetManager::baseUrl|baseUrl]].
|
|
|
|
|
|
|
|
En lugar de publicar los assets copiando archivos, se puede considerar usar enlaces simbólicos, si tu
|
|
|
|
SO (sistema operativo) y servidor Web lo permiten. Esta característica se puede habilitar estableciendo el valor de
|
|
|
|
[[yii\web\AssetManager::linkAssets|linkAssets]] en `true`.
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
// ...
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'linkAssets' => true,
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Con la anterior configuración, el gestor de assets creará un enlace simbólico a la ruta de origen del asset bundle
|
|
|
|
cuando éste sea publicado. Esto es más rápido que copiar archivos y también asegura que siempre estén actualizados.
|
|
|
|
|
|
|
|
## Los Asset Bundles más Comunes <span id="common-asset-bundles"></span>
|
|
|
|
|
|
|
|
El código del núcleo de Yii tiene definidos varios asset bundles. Entre ellos, los siguientes bundles son los más
|
|
|
|
usados y pueden referenciarse en códigos de aplicaciones o extensiones.
|
|
|
|
|
|
|
|
- [[yii\web\YiiAsset]]: Principalmente incluye el archivo `yii.js` que implementa un mecanismo de organización de
|
|
|
|
código JavaScript en los módulos. También proporciona soporte especial para los atributos `data-method` y
|
|
|
|
`data-confirm` y otras característica útiles.
|
|
|
|
- [[yii\web\JqueryAsset]]: Incluye el archivo `jquery.js` desde el paquete Bower jQuery.
|
|
|
|
- [[yii\bootstrap\BootstrapAsset]]: Incluye el archivo CSS desde el framework Twitter Bootstrap.
|
|
|
|
- [[yii\bootstrap\BootstrapPluginAsset]]: Incluye el archivo JavaScript desde el framework Twitter Bootstrap para dar
|
|
|
|
soporte a los plugins JavaScript de Bootstrap.
|
|
|
|
- [[yii\jui\JuiAsset]]: Incluye los archivos CSS y JavaScript desde la librería jQuery UI.
|
|
|
|
|
|
|
|
Si el código depende de jQuery, jQuery UI o Bootstrap, se pueden usar estos asset bundles predefinidos en lugar de
|
|
|
|
crear versiones propias. Si la configuración predeterminada de estos bundles no satisface las necesidades, se puede
|
|
|
|
personalizar como se describe en la subsección [Personalización de Asset Bundles](#customizing-asset-bundles).
|
|
|
|
|
|
|
|
## Conversión de Assets <span id="asset-conversion"></span>
|
|
|
|
|
|
|
|
En lugar de escribir código CSS y/o JavaScript directamente, los desarrolladores a menudo escriben código usando una
|
|
|
|
sintaxis extendida y usan herramientas especiales para convertirlos en CSS/JavaScript. Por ejemplo, para código CSS se
|
|
|
|
puede usar [LESS](http://lesscss.org) o [SCSS](http://sass-lang.com/); y para JavaScript se puede usar
|
|
|
|
[TypeScript](http://www.typescriptlang.org/).
|
|
|
|
|
|
|
|
Se pueden listar los archivos asset con sintaxis extendida (extended syntax) en [[yii\web\AssetBundle::css|css]] y
|
|
|
|
[[yii\web\AssetBundle::js|js]] en un asset bundle. Por ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
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',
|
|
|
|
];
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Cuando se registra uno de estos asset bundles en una vista, el [[yii\web\AssetManager|asset manager]] ejecutará
|
|
|
|
automáticamente las herramientas pre-procesadoras para convertir los assets de sintaxis extendidas reconocidas en
|
|
|
|
CSS/JavaScript. Cuando la vista renderice finalmente una página, se incluirán los archivos CSS/JavaScript
|
|
|
|
en la página, en lugar de los assets originales en sintaxis extendidas.
|
|
|
|
|
|
|
|
Yii usa las extensiones de archivo para identificar que sintaxis extendida se está usando. De forma predeterminada se
|
|
|
|
reconocen las siguientes sintaxis y extensiones de archivo.
|
|
|
|
|
|
|
|
- [LESS](http://lesscss.org/): `.less`
|
|
|
|
- [SCSS](http://sass-lang.com/): `.scss`
|
|
|
|
- [Stylus](http://learnboost.github.io/stylus/): `.styl`
|
|
|
|
- [CoffeeScript](http://coffeescript.org/): `.coffee`
|
|
|
|
- [TypeScript](http://www.typescriptlang.org/): `.ts`
|
|
|
|
|
|
|
|
Yii se basa en las herramientas pre-procesadoras instalada para convertir los assets. Por ejemplo, para usar
|
|
|
|
[LESS](http://lesscss.org/) se debe instalar el comando pre-procesador `lessc`.
|
|
|
|
|
|
|
|
Se pueden personalizar los comandos de los pre-procesadores y las sintaxis extendidas soportadas configurando
|
|
|
|
[[yii\web\AssetManager::converter]] como en el siguiente ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'converter' => [
|
|
|
|
'class' => 'yii\web\AssetConverter',
|
|
|
|
'commands' => [
|
|
|
|
'less' => ['css', 'lessc {from} {to} --no-color'],
|
|
|
|
'ts' => ['js', 'tsc --out {to} {from}'],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
En el anterior ejemplo se especifican las sintaxis extendidas soportadas a través de la propiedad
|
|
|
|
[[yii\web\AssetConverter::commands]]. Las claves del array son los nombres de extensión de archivo (sin el punto), y
|
|
|
|
los valores del array las extensiones de archivo resultantes y los comandos para realizar la conversión de assets.
|
|
|
|
Los tokens `{from}` y `{to}` en los comandos se reemplazarán por las rutas de origen de los archivos asset y las rutas
|
|
|
|
de destino de los archivos asset.
|
|
|
|
|
|
|
|
> Información: Hay otras maneras de trabajar con las assets de sintaxis extendidas, además de la descrita
|
|
|
|
anteriormente. Por ejemplo, se pueden usar herramientas generadoras tales como [grunt](http://gruntjs.com/) para
|
|
|
|
monitorear y convertir automáticamente los assets de sintaxis extendidas. En este caso, se deben listar los archivos
|
|
|
|
CSS/JavaScript resultantes en lugar de los archivos de originales.
|
|
|
|
|
|
|
|
## Combinación y Compresión de Assets <span id="combining-compressing-assets"></span>
|
|
|
|
|
|
|
|
Una página web puede incluir muchos archivos CSS y/o JavaScript. Para reducir el número de peticiones (requests)
|
|
|
|
HTTP y el tamaño total de descarga de estos archivos, una práctica común es combinar y comprimir uno o
|
|
|
|
varios archivos, y después incluir los archivos comprimidos en las páginas Web.
|
|
|
|
|
|
|
|
>Información: La combinación y compresión de assets es habitualmente necesario cuando una aplicación se encuentra en
|
|
|
|
modo de producción. En modo de desarrollo, es más conveniente usar los archivos CSS/JavaScript originales por temas
|
|
|
|
relacionados con el debugging.
|
|
|
|
|
|
|
|
En el siguiente ejemplo, se muestra una propuesta para combinar y comprimir archivos asset sin necesidad de modificar
|
|
|
|
el código de la aplicación.
|
|
|
|
|
|
|
|
1. Buscar todos los asset bundles en la aplicación que se quieran combinar y comprimir.
|
|
|
|
2. Dividir estos bundles en uno o más grupos. Tenga en cuenta que cada bundle solo puede pertenecer a un único grupo.
|
|
|
|
3. Combina/Comprime los archivos CSS de cada grupo en un único archivo. Hace lo mismo para los archivos JavaScript.
|
|
|
|
4. Define un nuevo asset bundle para cada grupo:
|
|
|
|
* Establece las propiedades [[yii\web\AssetBundle::css|css]] y [[yii\web\AssetBundle::js|js]] para que sean los
|
|
|
|
archivos CSS y JavaScript combinados, respectivamente.
|
|
|
|
* Personaliza los asset bundles en cada grupo configurando sus propiedades [[yii\web\AssetBundle::css|css]] y
|
|
|
|
[[yii\web\AssetBundle::js|js]] para que sean el nuevo asset bundle creado para el grupo.
|
|
|
|
|
|
|
|
Usando este propuesta, cuando se registre un asset bundle en una vista, se genera un registro automático del nuevo
|
|
|
|
asset bundle para el grupo al que pertenece el bundle original. Y como resultado, los archivos combinados/comprimidos
|
|
|
|
se incluyen en la página, en lugar de los originales.
|
|
|
|
|
|
|
|
### Un Example <span id="example"></span>
|
|
|
|
|
|
|
|
Vamos a usar un ejemplo para explicar la propuesta anterior.
|
|
|
|
|
|
|
|
Asumiendo que la aplicación tenga dos páginas X e Y. La página X utiliza el asset bundle A, B y C mientras que la
|
|
|
|
página Y usa los asset bundles B, C y D.
|
|
|
|
|
|
|
|
Hay dos maneras de dividir estos asset bundles. Uno es usar un único grupo que incluye todos los asset bundles,
|
|
|
|
el otro es poner (A, B y C) en el Grupo X, y (B, C, D) en el grupo Y. ¿Cuál es mejor? El primero tiene la ventaja
|
|
|
|
de que las dos páginas comparten los mismos archivos CSS y JavaScript combinados, que producen una caché HTTP más
|
|
|
|
efectiva. Por otra parte, por el hecho de que un único grupo contenga todos los bundles, los archivos JavaScript serán
|
|
|
|
más grandes y por tanto incrementan el tiempo de transmisión del archivo inicial. En este ejemplo, se usará la primera
|
|
|
|
opción, ej., usar un único grupo que contenga todos los bundles.
|
|
|
|
|
|
|
|
> Información: Dividiendo los asset bundles en grupos no es una tarea trivial. Normalmente requiere un análisis de los
|
|
|
|
datos del tráfico real de varios assets en diferentes páginas. Al principio, se puede empezar con un
|
|
|
|
único grupo para simplificar.
|
|
|
|
|
|
|
|
Se pueden usar herramientas existentes (ej. [Closure Compiler](https://developers.google.com/closure/compiler/),
|
|
|
|
[YUI Compressor](https://github.com/yui/yuicompressor/)) para combinar y comprimir todos los bundles. Hay que tener en
|
|
|
|
cuenta que los archivos deben ser combinados en el orden que satisfaga las dependencias entre los bundles.
|
|
|
|
Por ejemplo, si el Bundle A depende del B que depende a su vez de C y D, entonces, se deben listar los archivos asset
|
|
|
|
empezando por C y D, seguidos por B y finalmente A.
|
|
|
|
|
|
|
|
Después de combinar y comprimir obtendremos un archivo CSS y un archivo JavaScript. Supongamos que se llaman
|
|
|
|
`all-xyz.css` y `all-xyz.js`, donde `xyz` representa un timestamp o un hash que se usa para generar un nombre de
|
|
|
|
archivo único para evitar problemas con la caché HTTP.
|
|
|
|
|
|
|
|
Ahora estamos en el último paso. Configurar el [[yii\web\AssetManager|asset manager]] como en el siguiente ejemplo en
|
|
|
|
la configuración de la aplicación:
|
|
|
|
|
|
|
|
```php
|
|
|
|
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']],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Como se ha explicado en la subsección [Personalización de Asset Bundles](#customizing-asset-bundles), la anterior
|
|
|
|
configuración modifica el comportamiento predeterminado de cada bundle. En particular, el Bundle A, B, C y D ya no
|
|
|
|
tendrán ningún archivo asset. Ahora todos dependen del bundle `all` que contiene los archivos combinados `all-xyz.css`
|
|
|
|
y `all-xyz.js`. Por consiguiente, para la Página X, en lugar de incluir los archivos originales desde los bundles A, B
|
|
|
|
y C, solo se incluirán los dos archivos combinados; pasa lo mismo con la Página Y.
|
|
|
|
|
|
|
|
Hay un último truco para hacer que el enfoque anterior se adapte mejor. En lugar de modificar directamente el archivo
|
|
|
|
de configuración de la aplicación, se puede poner el array del personalización del bundle en un archivo separado y que
|
|
|
|
se incluya condicionalmente este archivo en la configuración de la aplicación. Por ejemplo:
|
|
|
|
|
|
|
|
```php
|
|
|
|
return [
|
|
|
|
'components' => [
|
|
|
|
'assetManager' => [
|
|
|
|
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Es decir, el array de configuración del asset bundle se guarda en `asset-prod.php` para el modo de producción, y
|
|
|
|
`assets-del.php` para los otros modos.
|
|
|
|
|
|
|
|
### Uso del Comando `asset` <span id="using-asset-command"></span>
|
|
|
|
|
|
|
|
Yii proporciona un comando de consola llamado `asset` para automatizar el enfoque descrito.
|
|
|
|
|
|
|
|
Para usar este comando, primero se debe crear un archivo de configuración para describir que asset bundle se deben
|
|
|
|
combinar y cómo se deben agrupar. Se puede usar el sub-comando `asset/template` para generar una plantilla primero y
|
|
|
|
después modificarla para que se adapte a nuestras necesidades.
|
|
|
|
|
|
|
|
```
|
|
|
|
yii asset/template assets.php
|
|
|
|
```
|
|
|
|
|
|
|
|
El comando genera un archivo llamado `assets.php` en el directorio actual. El contenido de este archivo es similar al
|
|
|
|
siguiente código:
|
|
|
|
|
|
|
|
```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 [
|
|
|
|
// Ajustar comando/callback para comprimir los ficheros JavaScript:
|
|
|
|
'jsCompressor' => 'java -jar compiler.jar --js {from} --js_output_file {to}',
|
|
|
|
// Ajustar comando/callback para comprimir los ficheros CSS:
|
|
|
|
'cssCompressor' => 'java -jar yuicompressor.jar --type css {from} -o {to}',
|
|
|
|
// La lista de assets bundles para comprimir:
|
|
|
|
'bundles' => [
|
|
|
|
// 'yii\web\YiiAsset',
|
|
|
|
// 'yii\web\JqueryAsset',
|
|
|
|
],
|
|
|
|
// Asset bundle para la salida de compresión:
|
|
|
|
'targets' => [
|
|
|
|
'all' => [
|
|
|
|
'class' => 'yii\web\AssetBundle',
|
|
|
|
'basePath' => '@webroot/assets',
|
|
|
|
'baseUrl' => '@web/assets',
|
|
|
|
'js' => 'js/all-{hash}.js',
|
|
|
|
'css' => 'css/all-{hash}.css',
|
|
|
|
],
|
|
|
|
],
|
|
|
|
// Configuración del Asset manager:
|
|
|
|
'assetManager' => [
|
|
|
|
],
|
|
|
|
];
|
|
|
|
```
|
|
|
|
|
|
|
|
Se debe modificar este archivo para especificar que bundles plantea combinar en la opción `bundles`. En la opción
|
|
|
|
`targets` se debe especificar como se deben dividir entre los grupos. Se puede especificar uno o más grupos,
|
|
|
|
como se ha comentado.
|
|
|
|
|
|
|
|
> Nota: Debido a que los alias `@webroot` y `@web` no están disponibles en la aplicación de consola, se deben definir
|
|
|
|
explícitamente en la configuración.
|
|
|
|
|
|
|
|
Los archivos JavaScript se combinan, comprimen y guardan en `js/all-{hash}.js` donde {hash} se reemplaza con el hash
|
|
|
|
del archivo resultante.
|
|
|
|
|
|
|
|
Las opciones `jsCompressor` y `cssCompressor` especifican los comandos de consola o llamadas PHP (PHP callbacks) para
|
|
|
|
realizar la combinación/compresión de JavaScript y CSS. De forma predeterminada Yii usa
|
|
|
|
[Closure Compiler](https://developers.google.com/closure/compiler/) para combinar los archivos JavaScript y
|
|
|
|
[YUI Compressor](https://github.com/yui/yuicompressor/) para combinar archivos CSS. Se deben instalar las herramientas
|
|
|
|
manualmente o ajustar sus configuraciones para usar nuestras favoritas.
|
|
|
|
|
|
|
|
Con el archivo de configuración, se puede ejecutar el comando `asset` para combinar y comprimir los archivos asset y
|
|
|
|
después generar un nuevo archivo de configuración de asset bundles `asset-prod.php`:
|
|
|
|
|
|
|
|
```
|
|
|
|
yii asset assets.php config/assets-prod.php
|
|
|
|
```
|
|
|
|
|
|
|
|
El archivo de configuración generado se puede incluir en la configuración de la aplicación, como se ha descrito en la
|
|
|
|
anterior subsección.
|
|
|
|
|
|
|
|
> Información: Usar el comando `asset` no es la única opción de automatizar el proceso de combinación y compresión.
|
|
|
|
Se puede usar la excelente herramienta de ejecución de tareas [grunt](http://gruntjs.com/) para lograr el mismo
|
|
|
|
objetivo.
|