这一次,我总结和分享一项大型网站优化技术,那就是在项目中自动压缩静态资源文件(css、js),并让网站自动加载压缩后的资源文件。当然,这项技术在雅虎35条前端优化建议里也有记载,但它那只是给出一个理论的方案而已,并且采用的是外部压缩工具去压缩,而在我的项目中,是直接通过自己的程序自动化去压缩所有css、js文件,然后让页面直接加载所压缩后的资源,接下来直接进入主题。
本次实验使用的是PHP脚本语言,版本是PHP5.6,是在LINUX下搭建的环境(网上搭建无论是搭建LAMP还是LNMP的教程都五花八门乱七八糟,下次我会总结和分享如何在LINUX下搭建服务器环境的博文,而且搭建的环境必须一次性搭建成功的)。所选用的框架是CI框架,所使用的模板是Smarty模板引擎。当然了,这些只是我所使用的环境而已,如果你是PHP开发者,假如你要测试下这次实验,那么,我建议你的PHP版本选用5.4以上,至于框架用什么都是可以的。而如果你不是PHP开发者(你是JSP或者是ASP开发者或者是其他开发者),那么你理解好这一思路后,完全可以在自己熟悉的语言里进行实验测试。
一、原理图
首先我画一张思路图,便于大家先理解。
首先是资源压缩原理图:
接着是资源文件替换的原理图:
假如大家认真理解并且看懂这两张原理图的话,基本上也就掌握了我所分享的思路。假如还是不能理解的话,接下来我会结合代码,对以上原理图的每一步进行详细讲解。
二、思路详细分析
1.首先是调用该压缩的方法,你可以把该方法放在网站所要加载的公共类的地方,例如每次访问网站都会调用该压缩方法进行压缩。当然,这个只是在开发环境才会每次都调用,如果是线上的环境,在你的网站发一次新版本的时候,调用一次用来生成压缩版的静态资源就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss资源文件 $this->compressResHandle(); } /** * 压缩js、css资源文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('ResMinifier'); //压缩指定文件夹下的资源文件 $this->resminifier->compressRes(); } } |
2.接着就调用了 ResMinifier类里的 compressRes方法。在这里我先附上 ResMinifier这个类的代码,然后方便一步步进行分析讲解
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 资源压缩类 */ class ResMinifier { /** 需要压缩的资源目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 资源根目录*/ public $resRootDir; /** 资源版本文件路径*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; } public function compressRes() { //获取存放版本的资源文件 $resState = $this->getResState(); $count = 0; //开始遍历需要压缩的资源目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该资源文件的绝对路径 $filePath = str_replace('\\', '/', $file->getRealPath()); //获取文件相对路径 $object = substr($filePath, strlen($this->resRootDir)); //计算文件的版本号 $state = $this->_getResStateVersion($filePath); //获取文件的几个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; } //压缩文件的绝对路径 $minFilePath = str_replace('\\', '/', $this->resRootDir. $minObject); //************此处p判断是最重要部分之一*****************// //判断文件是否存在且已经改动过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; } //确保/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); } $resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState); } public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取资源绝对路径 $filePath = $this->resRootDir . $object; //判断资源是否存在 if (!file_exists($filePath)) return "资源文件不存在{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是否要压缩 $needCompress = true; //判断资源文件是否是以 .min.css或者.min.js结尾的 //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的资源存放路径,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension |