我最近开始进入优化客户端的性能和加载时间,压缩css / js,gzipping,关注YSlow等领域。
我想知道,在尝试实现所有这些微优化时,将php文件作为css或javascript提供的优缺点是什么?
我不完全确定瓶颈在哪里,如果有的话。我认为在相同的CSS和php文件之间,“纯”的css文件会稍微快一点,因为它不需要解析php代码。但是,在php文件中,您可以更好地控制标题,这可能更重要(?)。
目前我正在对“触发器”文件进行filemtime()
检查,并使用一些php voodoo从中编写单个压缩css文件,并与定义组中的其他几个文件结合使用。这将创建一个类似css/groupname/301469778.css
的文件,php模板捕获并使用新文件名更新html标记。它似乎是最安全的方法,但我不喜欢服务器缓存在几次编辑后被垃圾css文件填满。对于仅为某些页面加载的小“帮助”css文件,我也不打算这样做。
mod_rewrite
使用css / js扩展名的文件是否适用于浏览器误解的任何边缘情况?不能受伤?不需要吗?@imports
的css文件,或一个包含多个readfile()
来电的php文件?我更喜欢使用带有.htaccess的php,因为它更简单,但最后我会使用最好的方法。
答案 0 :(得分:4)
我们正在使用大约2 MB以上的JavaScript代码开发非常大的DHTML / AJAX Web应用程序,并且仍然可以通过一些优化快速加载:
尝试减少包含的脚本网址的数量。我们使用一个简单的PHP脚本来加载一堆.js文件并将它们一次性发送到浏览器(所有连接)。当您拥有大量.js文件时,这将使您的页面加载 lot 更快,因为设置HTTP连接的开销通常远高于实际传输内容本身。请注意,浏览器需要同时下载JS文件。
缓存友好。我们的HTML页面也是通过PHP生成的,脚本的URL包含一个依赖于文件修改时间的哈希。上面结合.js文件的PHP脚本然后检查HTTP缓存标头并设置一个很长的过期时间,这样浏览器甚至不必在用户第二次访问页面时加载任何外部脚本。
GZIP压缩脚本。这将使您的代码减少约90%。我们甚至不需要缩小代码(这使调试更容易)。
所以,是的,使用PHP发送CSS / JS文件可以大大缩短页面的加载时间 - 特别是对于大页面。
编辑:您可以使用此代码组合文件:
function combine_files($list, $mime) {
if (!is_array($list))
throw new Exception("Invalid list parameter");
ob_start();
$lastmod = filemtime(__FILE__);
foreach ($list as $fname) {
$fm = @filemtime($fname);
if ($fm === false) {
$msg = $_SERVER["SCRIPT_NAME"].": Failed to load file '$fname'";
if ($mime == "application/x-javascript") {
echo 'alert("'.addcslashes($msg, "\0..\37\"\\").'");';
exit(1);
} else {
die("*** ERROR: $msg");
}
}
if ($fm > $lastmod)
$lastmod = $fm;
}
//--
$if_modified_since = preg_replace('/;.*$/', '',
$_SERVER["HTTP_IF_MODIFIED_SINCE"]);
$gmdate_mod = gmdate('D, d M Y H:i:s', $lastmod) . ' GMT';
$etag = '"'.md5($gmdate_mod).'"';
if (headers_sent())
die("ABORTING - headers already sent");
if (($if_modified_since == $gmdate_mod) or
($etag == $_SERVER["HTTP_IF_NONE_MATCH"])) {
if (php_sapi_name()=='CGI') {
Header("Status: 304 Not Modified");
} else {
Header("HTTP/1.0 304 Not Modified");
}
exit();
}
header("Last-Modified: $gmdate_mod");
header("ETag: $etag");
fc_enable_gzip();
// Cache-Control
$maxage = 30*24*60*60; // 30 Tage (Versions-Unterstützung im HTML Code!)
$expire = gmdate('D, d M Y H:i:s', time() + $maxage) . ' GMT';
header("Expires: $expire");
header("Cache-Control: max-age=$maxage, must-revalidate");
header("Content-Type: $mime");
echo "/* ".date("r")." */\n";
foreach ($list as $fname) {
echo "\n\n/***** $fname *****/\n\n";
readfile($fname);
}
}
function files_hash($list, $basedir="") {
$temp = array();
$incomplete = false;
if (!is_array($list))
$list = array($list);
if ($basedir!="")
$basedir="$basedir/";
foreach ($list as $fname) {
$t = @filemtime($basedir.$fname);
if ($t===false)
$incomplete = true;
else
$temp[] = $t;
}
if (!count($temp))
return "ERROR";
return md5(implode(",",$temp)) . ($incomplete ? "-INCOMPLETE" : "");
}
function fc_compress_output_gzip($output) {
$compressed = gzencode($output);
$olen = strlen($output);
$clen = strlen($compressed);
if ($olen)
header("X-Compression-Info: original $olen bytes, gzipped $clen bytes ".
'('.round(100/$olen*$clen).'%)');
return $compressed;
}
function fc_compress_output_deflate($output) {
$compressed = gzdeflate($output, 9);
$olen = strlen($output);
$clen = strlen($compressed);
if ($olen)
header("X-Compression-Info: original $olen bytes, deflated $clen bytes ".
'('.round(100/$olen*$clen).'%)');
return $compressed;
}
function fc_enable_gzip() {
if(isset($_SERVER['HTTP_ACCEPT_ENCODING']))
$AE = $_SERVER['HTTP_ACCEPT_ENCODING'];
else
$AE = $_SERVER['HTTP_TE'];
$support_gzip = !(strpos($AE, 'gzip')===FALSE);
$support_deflate = !(strpos($AE, 'deflate')===FALSE);
if($support_gzip && $support_deflate) {
$support_deflate = $PREFER_DEFLATE;
}
if ($support_deflate) {
header("Content-Encoding: deflate");
ob_start("fc_compress_output_deflate");
} else{
if($support_gzip){
header("Content-Encoding: gzip");
ob_start("fc_compress_output_gzip");
} else{
ob_start();
}
}
}
使用files_hash()生成一个唯一的哈希字符串,每当源文件发生更改时都会更改,而combine_files()会将组合文件发送到浏览器。因此,在生成标记的HTML代码时使用files_hash(),并在通过该标记加载的PHP脚本中使用combine_files()。只需将哈希值放在URL的查询字符串中即可。
<script language="JavaScript" src="get_the_code.php?hash=<?=files_hash($list_of_js_files)?>"></script>
确保在两种情况下都指定相同的$ list。
答案 1 :(得分:4)
不可能给你一个更具体的答案,因为它取决于很多你的项目细节。
答案 2 :(得分:1)
你所说的是通过PHP提供静态文件,实际上没有什么意义,因为它总是比服务普通文件的Apache慢。一个CSS @import会比PHP的readfile()更快,但是通过提供一个缩小的CSS文件可以获得最佳性能,该文件结合了你需要使用的所有CSS。
如果听起来像你在正确的轨道上。我建议预处理你的CSS并保存到磁盘。如果您需要为缓存之类的内容设置特殊标头,请在VirtualHost指令或.htaccess文件中执行此操作。
为避免大量缓存文件,您可以为缩小的CSS使用简单的文件命名约定。例如,如果您的主CSS文件名为main.css并且它通过@imports引用reset.css和forms.css,则缩小版本可以称为main.min.css
重新生成此文件时,它只是替换它。如果在HTML中包含对该文件的引用,则可以将该请求发送给PHP(如果该文件不存在),合并并缩小文件(通过YUI Compressor之类的内容),并将其保存到磁盘,因此通过普通HTTP为所有未来请求提供服务。
更新CSS时,只需删除main.min.css版本,它就会自动重新生成。
答案 3 :(得分:0)
您可以使用ANT Build进行预处理。对不起,这篇文章是德语,但我已经尝试过translate.google.com并且工作正常:-)所以你可以使用帖子作为教程来获得更好的表现...... 我会预处理文件并将它们保存到磁盘,就像simonrjones说的那样。缓存等等应该由专用元素完成,如Apache WebServer,Headers和Browser。
答案 4 :(得分:0)
虽然速度较慢,但您可能必须执行此操作的一个优点/原因是将动态内容放入服务器上的文件中,但仍然从客户端角度看它们是js或css。
就像这样,例如,将环境从php传递给javascript:
var environment = <?=getenv('APPLICATION_ENV');?>
// More JS code here ...