和并和最小化assets

如果你的页面包含很多CSS和/或Javascript文件,这个页面将会打开的比较慢,因为浏览器发送了大量的HTTP请求来下载每一个文件。为了减少请求和连接的数量,我们可以在生产模式下合并和压缩多个CSS/Javascript文件到一个或者非常少的几个文件,然后将这些压缩的文件包含在页面上。

准备

如何做…

跟随如下步骤,来和并和最小化资源:

  1. 打开你的应用index页面的源HTML代码。检查是否和如下结构比较相似:
  1. <!DOCTYPE html>
  2. <html lang="en-US">
  3. <head>
  4. ...
  5. <title>My Yii Application</title>
  6. <link href="/assets/9b3b2888/css/bootstrap.css"
  7. rel="stylesheet">
  8. <link href="/css/site.css" rel="stylesheet">
  9. </head>
  10. <body>
  11. ...
  12. <script src="/assets/25f82b8a/jquery.js"></script>
  13. <script src="/assets/f4307424/yii.js"></script>
  14. <script src="/assets/9b3b2888/js/bootstrap.js"></script>
  15. </body>
  16. </html>

这个页面包含三个Javascript文件。

  1. 打开config/console.php文件,并添加@webroot@web alias定义:
  1. <?php
  2. Yii::setAlias('@webroot', __DIR__ . '/../web');
  3. Yii::setAlias('@web', '/');
  1. 打开一个控制台,并运行如下命令:
  1. yii asset/template assets.php
  1. 打开生成的assets.php文件,并按如下配置:
  1. <?php
  2. return [
  3. 'jsCompressor' => 'java -jar compiler.jar --js {from}
  4. --js_output_file {to}',
  5. 'cssCompressor' => 'java -jar yuicompressor.jar --type css
  6. {from} -o {to}',
  7. 'bundles' => [
  8. 'app\assets\AppAsset',
  9. 'yii\bootstrap\BootstrapPluginAsset',
  10. ],
  11. 'targets' => [
  12. 'all' => [
  13. 'class' => 'yii\web\AssetBundle',
  14. 'basePath' => '@webroot/assets',
  15. 'baseUrl' => '@web/assets',
  16. 'js' => 'all-{hash}.js',
  17. 'css' => 'all-{hash}.css',
  18. ],
  19. ],
  20. 'assetManager' => [
  21. 'basePath' => '@webroot/assets',
  22. 'baseUrl' => '@web/assets',
  23. ],
  24. ];
  1. 运行合并命令yii asset assets.php config/assets-prod.php。如果成功,你就能得到带有如下配置的config/assets-prod.php文件:
  1. <?php
  2. return [
  3. 'all' => [
  4. 'class' => 'yii\\web\\AssetBundle',
  5. 'basePath' => '@webroot/assets',
  6. 'baseUrl' => '@web/assets',
  7. 'js' => [
  8. 'all-fe792d4766bead53e7a9d851adfc6ec2.js',
  9. ],
  10. 'css' => [
  11. 'all-37cfb42649f74eb0a4bfe0d0e715c420.css',
  12. ],
  13. ],
  14. 'yii\\web\\JqueryAsset' => [
  15. 'sourcePath' => null,
  16. 'js' => [],
  17. 'css' => [],
  18. 'depends' => [
  19. 'all',
  20. ],
  21. ],
  22. 'yii\\web\\YiiAsset' => [
  23. 'sourcePath' => null,
  24. 'js' => [],
  25. 'css' => [],
  26. 'depends' => [
  27. 'yii\\web\\JqueryAsset',
  28. 'all',
  29. ],
  30. ],
  31. 'yii\\bootstrap\\BootstrapAsset' => [
  32. 'sourcePath' => null,
  33. 'js' => [],
  34. 'css' => [],
  35. 'depends' => [
  36. 'all',
  37. ],
  38. ],
  39. 'app\\assets\\AppAsset' => [
  40. 'sourcePath' => null,
  41. 'js' => [],
  42. 'css' => [],
  43. 'depends' => [
  44. 'yii\\web\\YiiAsset',
  45. 'yii\\bootstrap\\BootstrapAsset',
  46. 'all',
  47. ],
  48. ],
  49. 'yii\\bootstrap\\BootstrapPluginAsset' => [
  50. 'sourcePath' => null,
  51. 'js' => [],
  52. 'css' => [],
  53. 'depends' => [
  54. 'yii\\web\\JqueryAsset',
  55. 'yii\\bootstrap\\BootstrapAsset',
  56. 'all',
  57. ],
  58. ],
  59. ];
  1. config/web.php文件中为assetManager组件添加配置:
  1. 'components' => [
  2. // ...
  3. 'assetManager' => [
  4. 'bundles' => YII_ENV_PROD ? require(__DIR__ . '/assets-prod.php') : [],
  5. ],
  6. ],
  1. web/index.php打开生产模式:
  1. defined('YII_ENV') or define('YII_ENV', 'prod');
  1. 在你的浏览器中刷新这个页面,就能看到HTML代码。现在应该有一条包含我们压缩文件的一行:
  1. <!DOCTYPE html>
  2. <html lang="en-US">
  3. <head>
  4. ...
  5. <title>My Yii Application</title>
  6. <link href="/assets/
  7. all-37cfb42649f74eb0a4bfe0d0e715c420.css" rel="stylesheet">
  8. </head>
  9. <body>
  10. ...
  11. <script src="/assets/
  12. all-fe792d4766bead53e7a9d851adfc6ec2.js"></script>
  13. </body>
  14. </html>

工作原理…

首先,我们的页面有包含文件的集合:

  1. <link href="/assets/9b3b2888/css/bootstrap.css" rel="stylesheet">
  2. <link href="/css/site.css" rel="stylesheet">
  3. ...
  4. <script src="/assets/25f82b8a/jquery.js"></script>
  5. <script src="/assets/f4307424/yii.js"></script>
  6. <script src="/assets/9b3b2888/js/bootstrap.js"></script>

接下来,我们生成assets.php配置文件,并制定需要压缩的东西:

  1. 'bundles' => [
  2. 'app\assets\AppAsset',
  3. 'yii\bootstrap\BootstrapPluginAsset',
  4. ],

注意:我们可以指定所有中间资源包,例如yii\web\JqueryAssetyii\web\YiiAsset,但是这些资源已经作为AppAssetBootstrapPluginAsset的依赖被指定了,这个压缩命令会自动解析所有的依赖。

AssetManager发布所有的资源到web/assets经典子文件夹中,在发布过以后,它会运行压缩器,将所有的CSS和JS文件压缩到all-{hash}.jsall-{hash}.css文件中。

检查这个CSS文件是否包含其它带有相对路径的资源,例如bootstrap.css文件中:

  1. @font-face {
  2. font-family: 'Glyphicons Halflings';
  3. src: url('../fonts/glyphicons-halflings-regular.eot');
  4. }

如果是这样的话,在和并的文件中,我们的压缩器会修改所有的相对路径:

  1. @font-face{
  2. font-family: 'Glyphicons Halflings';
  3. src: url('9b3b2888/fonts/glyphicons-halflings-regular.eot');
  4. }

处理过以后,我们得到了assets-prod.php文件,里边有assetManager组件的配置。它定义了新的virtual资源作为原始包的干净拷贝:

  1. return [
  2. 'all' => [
  3. 'class' => 'yii\\web\\AssetBundle',
  4. 'basePath' => '@webroot/assets',
  5. 'baseUrl' => '@web/assets',
  6. 'js' => [
  7. 'all-fe792d4766bead53e7a9d851adfc6ec2.js',
  8. ],
  9. 'css' => [
  10. 'all-37cfb42649f74eb0a4bfe0d0e715c420.css',
  11. ],
  12. ],
  13. 'yii\\web\\JqueryAsset' => [
  14. 'sourcePath' => null,
  15. 'js' => [],
  16. 'css' => [],
  17. 'depends' => [
  18. 'all',
  19. ],
  20. ],
  21. // ...
  22. ]

现在,我们可以require这个配置到config/web.php文件中:

  1. 'components' => [
  2. // ...
  3. 'assetManager' => [
  4. 'bundles' => require(__DIR__ . '/assets-prod.php'),
  5. ],
  6. ],

或者,我们可以只在生产环境中require这个文件:

  1. 'components' => [
  2. // ...
  3. 'assetManager' => [
  4. 'bundles' => YII_ENV_PROD ? require(__DIR__ . '/assets-prod.php') : [],
  5. ],
  6. ],

注意:不要忘记在更新了原始资源后重新生成所有的压缩和合并文件。

参考