Yii 中的资源(asset) 是一个要引入页面的文件。可以是 CSS, JavaScript 或任何其他文件。框架提供了很多种途径来使用资源,从最简单的方式比如使用标签 <script src="..."> 添加文件(在 视图 一章中描述),到高级应用比如发布不在web目录下的文件,解析Javascript依赖或者最小化CSS,接下来将分别进行描述。
声明资源包
要在网站中定义资源集合,你可以声明一个所谓资源包(asset bundle)的类。这个包定义了一系列资源文件以及它们对于其他资源包的依赖关系。
资源文件可以放在服务器可访问目录也可以隐藏在应用或 vendor 目录内。如果是后者,资源包喜欢发布自身到服务器可访问目录以便被网站引入。这个功能对扩展很有用,扩展可以在一个目录装载所有内容,让安装更容易。
要定义一个资源需要创建一个继承自[[yii\web\AssetBundle]]的类并根据需求设置属性。以下是资源定义示例,资源定义是基础应用模板的一部分,即AppAsset
资源包类,它定义了应用必需资源:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?php
use
yii\web\AssetBundle
as
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'
,
];
}
|
上述 $basePath
指定资源从哪个可网络访问的目录提供服务。这是相对$css
和 $js
路径的根目录,如@webroot/css/site.css
指向 css/site.css
。这里的 @webroot
是指向应用 web
目录的别名。
$baseUrl
用来指定刚才的 $css
和 $js
相对的根 URL ,如 @web/css/site.css
中的 @web
是一个 [别名],对应你的网站根 URL 如 http://example.com/
。
如果你的资源文件放在网络无法访问的目录,Yii 扩展正是如此,这样你必须指定 $sourcePath
而不是 $basePath
and$baseUrl
。原始路径的所有文件在注册前将被复制或符号链接(symlink)到你应用的 web/assets
目录。这种情况下$basePath
和 $baseUrl
将在发布资源包时自动生成。这是发布完整目录的资源工作方式,目录内可以包括图片、前端文件等。
注意: 不要使用
web/assets
目录放你自己的文件。它只用于资源发布。 当你创建网络可访问目录内的文件时,把它们放在类似web/css
或web/js
的文件夹内。
和其他资源包的依赖关系用 $depends
属性指定。这是个包括资源包完整合格类名的数组,资源包内的这些类应发布以便该资源包能正常工作。此例中, AppAsset
的Javascript 和 CSS 文件添加到 header 的[[yii\web\YiiAsset]]和[[yii\bootstrap\BootstrapAsset]]之后。
这里的[[yii\web\YiiAsset]]添加 Yii 的 JavaScript库,而[[yii\bootstrap\BootstrapAsset]]包括Bootstrap前端框架。
资源包是常规类,所以如需定义更多资源包,以唯一名创建同样的类即可。新建的类可以放到任何地方,但惯例是放到应用的 assets
目录。
此外,可以在注册和发布资源时指定 $jsOptions
, $cssOptions
和 $publishOptions
参数分别传递到[[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] 和 [[yii\web\AssetManager::publish()]]。
特定语言资源包
如果你想在一个资源包中包含特定语言的JavaScript文件,你可以实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
LanguageAsset
extends
AssetBundle
{
public
$language
;
public
$sourcePath
=
'@appassets/language'
;
public
$js
= [
];
public
function
registerAssetFiles(
$view
)
{
$language
=
$this
->language ?
$this
->language : Yii::
$app
->language;
$this
->js[] =
'language-'
.
$language
.
'.js'
;
parent::registerAssetFiles(
$view
);
}
}
|
然后在视图中注册一个资源包时,使用下述代码设置具体的语言:
1
|
LanguageAsset::register(
$this
)->language =
$language
;
|
注册资源包
资源包类通常要注册到视图文件或小部件,以 css 和 javascript 文件来提供功能。 特例是以上定义的 AppAsset 类, AppAsset 类添加到应用的主布局文件并注册到该应用的任何页面。注册资源包简单到调用[[yii\web\AssetBundle::register()|register()]]方法即可实现:
1
2
|
use
app\assets\AppAsset;
AppAsset::register(
$this
);
|
由于我们在一个视图上下文中,$this
指向 View
类对象。为了在widget中注册一个资源,视图实例通过 $this->view
来获取:
1
|
AppAsset::register(
$this
->view);
|
注意:如果需要修改第三方资源包,建议你创建自己的包,依赖于第三方包,然后使用CSS或JavaScript功能来修改缺省行为,不要直接修改或替换第三方包的文件。
覆盖资源包
有时候你需要覆盖一些应用程序作用范围的资源包,比如想从CDN加载jQuery而不是自己的服务器。为此我们需要在config文件中配置 assetManager
应用程序组件。对于基础应用程序而言,就是 config/web.php
文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
return
[
// ...
'components'
=> [
'assetManager'
=> [
'bundles'
=> [
'yii\web\JqueryAsset'
=> [
'sourcePath'
=> null,
'js'
=> [
'//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'
]
],
],
],
],
];
|
以上添加了资源包定义到[[yii\web\AssetManager::bundles|bundles]]资源管理器属性,数组键是拟覆写的资源包类的合格完整类名,而数组值是拟设置的类属性及对应值数组。
sourcePath
设置为 null
是告诉资源管理器在 js
以 CDN 链接来覆写本地文件时不要复制。
启动符号链接(symlinks)
资源管理器能使用符号链接,不用复制文件。符号链接默认是关闭的,因为它在虚拟主机通常无法使用。如果你的主机环境支持符号链接,就肯定能通过应用配置启用这个功能:
1
2
3
4
5
6
7
8
|
return
[
// ...
'components'
=> [
'assetManager'
=> [
'linkAssets'
=> true,
],
],
];
|
启用符号链接有两个好处,第一是无须复制所以更快,第二是资源会链接源文件保持最新。
压缩和合并资源
要改进应用性能可以压缩和合并多个 CSS 或 JS 文件到更少的文件以便减少 HTTP 请求次数和页面加载所需下载量。Yii 提供了一个控制台命令使你能一次完成压缩和合并。
准备配置
要使用 asset
命令需先准备配置文件,可使用以下命令生成内置模板的配置文件:
1
|
yii asset/template /path/to/myapp/config.php
|
模板如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?php
/**
* "yii asset" 控制台命令的配置文件
* 注意控制台环境下有些路径别名可能不存在,如 '@webroot' 和 '@web'
* 请先定义找不到的路径别名
*/
return
[
// 为 JavaScript 文件压缩调整 command/callback 命令:
'jsCompressor'
=>
'java -jar compiler.jar --js {from} --js_output_file {to}'
,
// 为 CSS 文件压缩调整 command/callback 命令:
'cssCompressor'
=>
'java -jar yuicompressor.jar --type css {from} -o {to}'
,
// 要压缩的资源包列表:
'bundles'
=> [
// 'yii\web\YiiAsset',
// 'yii\web\JqueryAsset',
],
// 输出的已压缩资源包:
'targets'
=> [
'app\config\AllAsset'
=> [
'basePath'
=>
'path/to/web'
,
'baseUrl'
=>
''
,
'js'
=>
'js/all-{ts}.js'
,
'css'
=>
'css/all-{ts}.css'
,
],
],
// 资源管理器配置:
'assetManager'
=> [
'basePath'
=> __DIR__,
'baseUrl'
=>
''
,
],
];
|
以上数值键是 AssetController
的 properties
。该资源控制器的属性之一 bundles
列表包括拟压缩资源包,通常被应用程序使用。targets
包括定义文件编写方式的输出资源包列表。我们的例子中编写所有文件到 path/to/web
,以http://example.com/
来访问,这是个网站根目录。
注意:控制台环境有些路径别名不存在,如 '@webroot' 和 '@web' ,所以在配置文件中的相应路径要直接指定。
JavaScript 文件将压缩合并写入 js/all-{ts}.js
,其中 {ts} 将替换为当前的 UNIX 时间戳。
jsCompressor
和 cssCompressor
是控制台命令或 PHP 回调函数,它们分别执行 JavaScript 和 CSS 文件压缩。你可以根据你的环境调整这些值。默认情况下,Yii 依靠Closure Compiler来压缩 JavaScript 文件,依赖YUI Compressor压缩 CSS 文件。如果你想使用它们请手动安装这些实用程序。
提供压缩工具
命令依靠未绑定到Yii 的外部压缩工具,所以你需要指定 cssCompressor
和 jsCompression
属性来分别提供 CSS 和 JS 的压缩工具。如果压缩工具指定为字符串将视为 shell 命令模板,该模板包括两个占位符: {from}
将用源文件名替换,而 {to}
将用输出的文件名替换。另一个指定压缩工具的方法是使用有效的 PHP 回调函数。
Yii 压缩 JavaScript 默认使用名为 compiler.jar
的Google Closure compiler 压缩工具。
Yii 压缩 CSS 使用名为 yuicompressor.jar
的YUI Compressor压缩工具。
要同时压缩 JavaScript 和 CSS ,需要下载以上两个工具并放在和 yii
控制台引导文件同一个目录下,并须安装 JRE 来运行这些工具。
要自定义压缩命令(如更改 jar 文件位置),请在 config.php
中如下设置:
1
2
3
4
|
return
[
'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}'
,
];
|
其中 {from}
和 {to}
asset
是占位符,将在命令压缩文件时分别被真实的源文件路径和目标文件路径替换。
执行压缩
1
|
yii asset /path/to/myapp/config.php /path/to/myapp/config/assets_compressed.php
|
现在进程将占用一点时间并最终完成。你需要调整你的 web 应用配置来使用已压缩的资源文件,如下:
1
2
3
4
5
6
|
'components'
=> [
// ...
'assetManager'
=> [
'bundles'
=>
require
'/path/to/myapp/config/assets_compressed.php'
,
],
],
|
使用资源转换器
通常开发人员不直接使用 CSS 和 JavaScript 而是使用改进版本如 CSS 的 LESS 或 SCSS 和 JavaScript 的微软出品 TypeScript 。在 Yii 中使用它们是非常简单的。
首先,相应的压缩工具已经安装在 yii
控制台引导程序同目录下且可用。以下列示了文件扩展和相应的 Yii 转换器能识别的转换工具名。
- LESS:
less
-lessc
- SCSS:
scss
,sass
-sass
- Stylus:
styl
-stylus
- CoffeeScript:
coffee
-coffee
- TypeScript:
ts
-tsc
如果相应的工具已安装,就可以在资源包指定它们:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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'
,
];
}
|
要调整转换工具调用参数或添加新的调用参数,可以使用应用配置:
1
2
3
4
5
6
7
8
9
10
11
12
|
// ...
'components'
=> [
'assetManager'
=> [
'converter'
=> [
'class'
=>
'yii\web\AssetConverter'
,
'commands'
=> [
'less'
=> [
'css'
,
'lessc {from} {to} --no-color'
],
'ts'
=> [
'js'
,
'tsc --out {to} {from}'
],
],
],
],
],
|
以上列示了两种外部文件扩展,第一个是 less
,指定在资源包的 css
部分。转换通过运行 lessc {from} {to} --no-color
来执行,其中{from}
以 LESS 文件路径替换而 {to}
用目标 CSS 文件路径替换。第二个文件扩展是 ts
,指定在资源包的 js
部分。这个命令在转换时运行,格式同 less
。