和并和最小化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和@webalias定义:
<?phpYii::setAlias('@webroot', __DIR__ . '/../web');Yii::setAlias('@web', '/');
- 打开一个控制台,并运行如下命令:
yii asset/template assets.php
- 打开生成的
assets.php文件,并按如下配置:
<?phpreturn ['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文件:
<?phpreturn ['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/
