和并和最小化assets
如果你的页面包含很多CSS和/或Javascript文件,这个页面将会打开的比较慢,因为浏览器发送了大量的HTTP请求来下载每一个文件。为了减少请求和连接的数量,我们可以在生产模式下合并和压缩多个CSS/Javascript文件到一个或者非常少的几个文件,然后将这些压缩的文件包含在页面上。
准备
- 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的
yii2-app-basic
应用。 - 从https://developers.google.com/closure/compiler/下载
compiler.jar
文件 - 从https://github.com/yui/yuicompressor/releases下载
yuicompressor.jar
文件 - 从http://www.java.com下载jre。
如何做…
跟随如下步骤,来和并和最小化资源:
- 打开你的应用
index
页面的源HTML代码。检查是否和如下结构比较相似:
<!DOCTYPE html>
<html lang="en-US">
<head>
...
<title>My Yii Application</title>
<link href="/assets/9b3b2888/css/bootstrap.css"
rel="stylesheet">
<link href="/css/site.css" rel="stylesheet">
</head>
<body>
...
<script src="/assets/25f82b8a/jquery.js"></script>
<script src="/assets/f4307424/yii.js"></script>
<script src="/assets/9b3b2888/js/bootstrap.js"></script>
</body>
</html>
这个页面包含三个Javascript文件。
- 打开
config/console.php
文件,并添加@webroot
和@web
alias定义:
<?php
Yii::setAlias('@webroot', __DIR__ . '/../web');
Yii::setAlias('@web', '/');
- 打开一个控制台,并运行如下命令:
yii asset/template assets.php
- 打开生成的
assets.php
文件,并按如下配置:
<?php
return [
'jsCompressor' => 'java -jar compiler.jar --js {from}
--js_output_file {to}',
'cssCompressor' => 'java -jar yuicompressor.jar --type css
{from} -o {to}',
'bundles' => [
'app\assets\AppAsset',
'yii\bootstrap\BootstrapPluginAsset',
],
'targets' => [
'all' => [
'class' => 'yii\web\AssetBundle',
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
'js' => 'all-{hash}.js',
'css' => 'all-{hash}.css',
],
],
'assetManager' => [
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
],
];
- 运行合并命令
yii asset assets.php config/assets-prod.php
。如果成功,你就能得到带有如下配置的config/assets-prod.php
文件:
<?php
return [
'all' => [
'class' => 'yii\\web\\AssetBundle',
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
'js' => [
'all-fe792d4766bead53e7a9d851adfc6ec2.js',
],
'css' => [
'all-37cfb42649f74eb0a4bfe0d0e715c420.css',
],
],
'yii\\web\\JqueryAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'all',
],
],
'yii\\web\\YiiAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'yii\\web\\JqueryAsset',
'all',
],
],
'yii\\bootstrap\\BootstrapAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'all',
],
],
'app\\assets\\AppAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'yii\\web\\YiiAsset',
'yii\\bootstrap\\BootstrapAsset',
'all',
],
],
'yii\\bootstrap\\BootstrapPluginAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'yii\\web\\JqueryAsset',
'yii\\bootstrap\\BootstrapAsset',
'all',
],
],
];
- 在
config/web.php
文件中为assetManager
组件添加配置:
'components' => [
// ...
'assetManager' => [
'bundles' => YII_ENV_PROD ? require(__DIR__ . '/assets-prod.php') : [],
],
],
- 在
web/index.php
打开生产模式:
defined('YII_ENV') or define('YII_ENV', 'prod');
- 在你的浏览器中刷新这个页面,就能看到HTML代码。现在应该有一条包含我们压缩文件的一行:
<!DOCTYPE html>
<html lang="en-US">
<head>
...
<title>My Yii Application</title>
<link href="/assets/
all-37cfb42649f74eb0a4bfe0d0e715c420.css" rel="stylesheet">
</head>
<body>
...
<script src="/assets/
all-fe792d4766bead53e7a9d851adfc6ec2.js"></script>
</body>
</html>
工作原理…
首先,我们的页面有包含文件的集合:
<link href="/assets/9b3b2888/css/bootstrap.css" rel="stylesheet">
<link href="/css/site.css" rel="stylesheet">
...
<script src="/assets/25f82b8a/jquery.js"></script>
<script src="/assets/f4307424/yii.js"></script>
<script src="/assets/9b3b2888/js/bootstrap.js"></script>
接下来,我们生成assets.php
配置文件,并制定需要压缩的东西:
'bundles' => [
'app\assets\AppAsset',
'yii\bootstrap\BootstrapPluginAsset',
],
注意:我们可以指定所有中间资源包,例如yii\web\JqueryAsset
和yii\web\YiiAsset
,但是这些资源已经作为AppAsset
和BootstrapPluginAsset
的依赖被指定了,这个压缩命令会自动解析所有的依赖。
AssetManager发布所有的资源到web/assets
经典子文件夹中,在发布过以后,它会运行压缩器,将所有的CSS和JS文件压缩到all-{hash}.js
和all-{hash}.css
文件中。
检查这个CSS文件是否包含其它带有相对路径的资源,例如bootstrap.css
文件中:
@font-face {
font-family: 'Glyphicons Halflings';
src: url('../fonts/glyphicons-halflings-regular.eot');
}
如果是这样的话,在和并的文件中,我们的压缩器会修改所有的相对路径:
@font-face{
font-family: 'Glyphicons Halflings';
src: url('9b3b2888/fonts/glyphicons-halflings-regular.eot');
}
处理过以后,我们得到了assets-prod.php
文件,里边有assetManager
组件的配置。它定义了新的virtual资源作为原始包的干净拷贝:
return [
'all' => [
'class' => 'yii\\web\\AssetBundle',
'basePath' => '@webroot/assets',
'baseUrl' => '@web/assets',
'js' => [
'all-fe792d4766bead53e7a9d851adfc6ec2.js',
],
'css' => [
'all-37cfb42649f74eb0a4bfe0d0e715c420.css',
],
],
'yii\\web\\JqueryAsset' => [
'sourcePath' => null,
'js' => [],
'css' => [],
'depends' => [
'all',
],
],
// ...
]
现在,我们可以require这个配置到config/web.php
文件中:
'components' => [
// ...
'assetManager' => [
'bundles' => require(__DIR__ . '/assets-prod.php'),
],
],
或者,我们可以只在生产环境中require这个文件:
'components' => [
// ...
'assetManager' => [
'bundles' => YII_ENV_PROD ? require(__DIR__ . '/assets-prod.php') : [],
],
],
注意:不要忘记在更新了原始资源后重新生成所有的压缩和合并文件。
参考
- 欲了解更多关于assets的信息,参考http://www.yiiframework.com/doc-2.0/guide-structure-assets.html
- Closure Compiler的信息,参考https://developers.google.com/closure/compiler/
- 对于YUI压缩器的信息,参考https://github.com/yui/yuicompressor/