缩小HTML/PHP
我使用gzip压缩我的html/php文件以及js/css/等。这很好地减少了负载,但我还想“缩小”我的.html和.php页面的标记。理想情况下,我希望通过一个.htaccess文件(我也在其中执行gzip)来控制它,而不必在每个文件中包含php 我希望输出类似于或和(均由WordPress的W3 Total Cache插件生成)缩小HTML/PHP,php,minify,compression,optimization,Php,Minify,Compression,Optimization,我使用gzip压缩我的html/php文件以及js/css/等。这很好地减少了负载,但我还想“缩小”我的.html和.php页面的标记。理想情况下,我希望通过一个.htaccess文件(我也在其中执行gzip)来控制它,而不必在每个文件中包含php 我希望输出类似于或和(均由WordPress的W3 Total Cache插件生成) 有人能推荐一个好的方法吗。看看这些例子,缩小HTML输出几乎没有任何作用。想一想:缩小对于使用许多重复变量和函数名的Javascript来说是很好的,因为缩小的主要
有人能推荐一个好的方法吗。看看这些例子,缩小HTML输出几乎没有任何作用。想一想:缩小对于使用许多重复变量和函数名的Javascript来说是很好的,因为缩小的主要作用之一就是缩短它们和所有对它们的引用 另一方面,HTML标记没有变量或函数的概念。页面的大部分权重来自实际的标记和内容。这是无法缩小的。甚至表单变量也需要单独处理,因为服务器必须正确处理它们的原始值 gzip将非常有效地压缩空白。在HTML中,这实际上是所有可以做的事情 此外,缩小PHP不适用,因为即使它有变量和函数,也不会发送到客户端。缩短名称对服务器上编译的内容没有任何性能好处
如果你决定缩小你的html,请查看WordPress插件的源代码。这就是开源的美妙之处。然而,我怀疑与Gzipping相比,这一收益微不足道。彼得·安塞尔莫(Peter Anselmo)将缩小与模糊混为一谈。在代码混淆中,代码被缩小,变量被重命名为最短长度的任意名称。缩小仅仅是减少代码大小的实践,例如删除空白,而不改变代码的值、名称或语法 彼得·安塞尔莫(Peter Anselmo)也错误地认为,缩小加价只会带来微不足道的节约。例如,这个页面显示了18.31%的节省,并且一开始就相当整洁。显然,他在发表意见之前从未测试过自己的意见。您可以在以下位置使用Pretty Diff工具查看成本节约情况:
您可以尝试对Pretty Diff用于从PHP执行的小型化引擎进行反向工程。这些代码和附带的文档可以在以下网址找到:prettydiff.com/markupmin.js我创建了3个可能需要优化的简单函数,但它们完成了它们的工作,它们是我用来格式化代码、日期、值等的更大类的一部分: 要使用它,只需调用:
echo format::minify_html($html_output);
下面是代码(仍处于测试阶段,但到目前为止还没有太多问题)
我没有提到缩小PHP,因为它不适用。PHP代码从未发送到客户端。@Peter Anselmo:您应该在答案中添加该注释。我想他指的是PHP页面的HTML输出。@R.Bemose-好主意,它已与答案合并。“缩小HTML输出几乎没有任何作用”。我大体上同意“除非你真的需要,否则不要缩小”的观点,然而,谷歌这样做肯定是有原因的(尽管这可能不适用于99%的项目)。有几个原因我会认真考虑我的项目的HTML缩小。(1) iPhone只缓存小于30k的对象,压缩并不能帮助绕过这一限制(2)如果你不必担心发送给客户端的空白和注释,你可以使用比其他方式更多的内容——我们大量缩进标记。通常情况下,混淆不仅仅是这些!他确实说过,与gzipping相比,缩减收益是微不足道的。从快速试验来看,这是18%对75%。现在gzip缩小版将节省更多的钱-另外1-2%-但是你仅仅用gzip就可以做到这一点。是的,你完全断章取义了我的话,除了gzip缩小版。您的工具pretty diff不会评估此场景,它只评估未压缩代码与缩小的ucompressed代码。此外,许多缩微器(包括YUI压缩器、闭包编译器和打包器)确实会缩短变量名。也许为了OP的利益,我应该更清楚地了解缩小和模糊,但我仍然认为没有必要编辑我的帖子。我应该更清楚一点,但我的意思是简单地缩小和去除空白,而不是模糊。我发现的一个好方法是使用obstart()的输出缓冲,它可以简单地在头中调用,并与一些正则表达式结合使用,在将标记发送到浏览器之前去除标记中不必要的内容。关于PHP页面,是的,我只是指那些页面的标记。prettydiff工具非常有用。谢谢你的提示!你说得对。彼得·安塞尔莫真的应该改变他的答案。缩小(代码的零更改,这是正常的缩小过程)确实会有所不同。当人们声称不是时,这是令人沮丧的。也就是说,gzipping将是迄今为止最大的区别。如果你发送大量电子邮件,18%是非常重要的。我认为在PHP中优化HTML的最大用处是HTML(通常)是动态的,所以虽然我可以从bash构建脚本中缩小JS和CSS,但我不能对HTML这样做。也就是说,这是每个请求都需要完成的事情。
<?php
class format(){
static function minify_css($text){
$from = array(
// '%(#|;|(//)).*%', // comments: # or //
'%/\*(?:(?!\*/).)*\*/%s', // comments: /*...*/
'/\s{2,}/', // extra spaces
"/\s*([;{}])[\r\n\t\s]/", // new lines
'/\\s*;\\s*/', // white space (ws) between ;
'/\\s*{\\s*/', // remove ws around {
'/;?\\s*}\\s*/', // remove ws around } and last semicolon in declaration block
// '/:first-l(etter|ine)\\{/', // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
// '/((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value\\s+/x', // Use newline after 1st numeric value (to limit line lengths).
// '/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i',
);
$to = array(
// '',
'',
' ',
'$1',
';',
'{',
'}',
// ':first-l$1 {',
// "$1\n",
// '$1#$2$3$4$5',
);
$text = preg_replace($from,$to,$text);
return $text;
}
static function minify_js($text){
$file_cache = strtolower(md5($text));
$folder = TMPPATH.'tmp_files'.DIRECTORY_SEPARATOR.substr($file_cache,0,2).DIRECTORY_SEPARATOR;
if(!is_dir($folder)) @mkdir($folder, 0766, true);
if(!is_dir($folder)){
echo 'Impossible to create the cache folder:'.$folder;
return 1;
}
$file_cache = $folder.$file_cache.'_content.js';
if(!file_exists($file_cache)){
if(strlen($text)<=100){
$contents = $text;
} else {
$contents = '';
$post_text = http_build_query(array(
'js_code' => $text,
'output_info' => 'compiled_code',//($returnErrors ? 'errors' : 'compiled_code'),
'output_format' => 'text',
'compilation_level' => 'SIMPLE_OPTIMIZATIONS',//'ADVANCED_OPTIMIZATIONS',//'SIMPLE_OPTIMIZATIONS'
), null, '&');
$URL = 'http://closure-compiler.appspot.com/compile';
$allowUrlFopen = preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen'));
if($allowUrlFopen){
$contents = file_get_contents($URL, false, stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $post_text,
'max_redirects' => 0,
'timeout' => 15,
)
)));
}elseif(defined('CURLOPT_POST')) {
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_text);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
$contents = curl_exec($ch);
curl_close($ch);
} else {
//"Could not make HTTP request: allow_url_open is false and cURL not available"
$contents = $text;
}
if($contents==false || (trim($contents)=='' && $text!='') || strtolower(substr(trim($contents),0,5))=='error' || strlen($contents)<=50){
//No HTTP response from server or empty response or error
$contents = $text;
}
}
if(trim($contents)!=''){
$contents = trim($contents);
$f = fopen($file_cache, 'w');
fwrite($f, $contents);
fclose($f);
}
} else {
touch($file_cache); //in the future I will add a timetout to the cache
$contents = file_get_contents($file_cache);
}
return $contents;
}
static function minify_html($text){
if(isset($_GET['no_mini'])){
return $text;
}
$file_cache = strtolower(md5($text));
$folder = TMPPATH.'tmp_files'.DIRECTORY_SEPARATOR.substr($file_cache,0,2).DIRECTORY_SEPARATOR;
if(!is_dir($folder)) @mkdir($folder, 0766, true);
if(!is_dir($folder)){
echo 'Impossible to create the cache folder:'.$folder;
return 1;
}
$file_cache = $folder.$file_cache.'_content.html';
if(!file_exists($file_cache)){
//get CSS and save it
$search_css = '/<\s*style\b[^>]*>(.*?)<\s*\/style>/is';
$ret = preg_match_all($search_css, $text, $tmps);
$t_css = array();
if($ret!==false && $ret>0){
foreach($tmps as $k=>$v){
if($k>0){
foreach($v as $kk=>$vv){
$t_css[] = $vv;
}
}
}
}
$css = format::minify_css(implode('\n', $t_css));
/*
//get external JS and save it
$search_js_ext = '/<\s*script\b.*?src=\s*[\'|"]([^\'|"]*)[^>]*>\s*<\s*\/script>/i';
$ret = preg_match_all($search_js_ext, $text, $tmps);
$t_js = array();
if($ret!==false && $ret>0){
foreach($tmps as $k=>$v){
if($k>0){
foreach($v as $kk=>$vv){
$t_js[] = $vv;
}
}
}
}
$js_ext = $t_js;
*/
//get inline JS and save it
$search_js_ext = '/<\s*script\b.*?src=\s*[\'|"]([^\'|"]*)[^>]*>\s*<\s*\/script>/i';
$search_js = '/<\s*script\b[^>]*>(.*?)<\s*\/script>/is';
$ret = preg_match_all($search_js, $text, $tmps);
$t_js = array();
$js_ext = array();
if($ret!==false && $ret>0){
foreach($tmps as $k=>$v){
if($k==0){
//let's check if we have a souce (src="")
foreach($v as $kk=>$vv){
if($vv!=''){
$ret = preg_match_all($search_js_ext, $vv, $ttmps);
if($ret!==false && $ret>0){
foreach($ttmps[1] as $kkk=>$vvv){
$js_ext[] = $vvv;
}
}
}
}
} else {
foreach($v as $kk=>$vv){
if($vv!=''){
$t_js[] = $vv;
}
}
}
}
}
$js = format::minify_js(implode('\n', $t_js));
//get inline noscript and save it
$search_no_js = '/<\s*noscript\b[^>]*>(.*?)<\s*\/noscript>/is';
$ret = preg_match_all($search_no_js, $text, $tmps);
$t_js = array();
if($ret!==false && $ret>0){
foreach($tmps as $k=>$v){
if($k>0){
foreach($v as $kk=>$vv){
$t_js[] = $vv;
}
}
}
}
$no_js = implode('\n', $t_js);
//remove CSS and JS
$search = array(
$search_js_ext,
$search_css,
$search_js,
$search_no_js,
'/\>[^\S ]+/s', //strip whitespaces after tags, except space
'/[^\S ]+\</s', //strip whitespaces before tags, except space
'/(\s)+/s', // shorten multiple whitespace sequences
);
$replace = array(
'',
'',
'',
'',
'>',
'<',
'\\1',
);
$buffer = preg_replace($search, $replace, $text);
$append = '';
//add CSS and JS at the bottom
if(is_array($js_ext) && count($js_ext)>0){
foreach($js_ext as $k=>$v){
$append .= '<script type="text/javascript" language="javascript" src="'.$v.'" ></script>';
}
}
if($css!='') $append .= '<style>'.$css.'</style>';
if($js!=''){
//remove weird '\n' strings
$js = preg_replace('/[\s]*\\\n/', "\n", $js);
$append .= '<script>'.$js.'</script>';
}
if($no_js!='') $append .= '<noscript>'.$no_js.'</noscript>';
$buffer = preg_replace('/(.*)(<\s*\/\s*body\s*>)(.*)/','\\1'.$append.'\\2\\3', $buffer);
if(trim($buffer)!=''){
$f = fopen($file_cache, 'w');
fwrite($f, trim($buffer));
fclose($f);
}
} else {
touch($file_cache); //in the future I will add a timetout to the cache
$buffer = file_get_contents($file_cache);
}
return $buffer;
}
}
?>