如何缩小php页面的html输出?


143

我正在寻找一个可以减少我的php页面html输出的php脚本或类,就像google page speed一样。

我怎样才能做到这一点?


14
基于@RakeshS的单线回答:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia 2014年

5
@FranciscoPresencia这是一件非常不好的事情。你打破脚本标记,预标记等
布拉德

的确如此,正如他在回答注释中所指出的那样,它<pre><code>标记不起作用,因为它们需要空格来确保适当的结构。但是,<script>通常应在外部使用,也可以在内部使用,但必须;严格使用,这样它也可以使用。其他哪些标签可能会破坏@Brad?我想不起其他人。我应该在之前的评论之前添加快速而肮脏的方式
弗朗西斯科·普雷森西亚

Answers:


212

CSS和Javascript

考虑以下链接以最小化Javascript / CSS文件: https //github.com/mrclay/minify

的HTML

告诉Apache使用GZip交付HTML-通常将响应大小减少约70%。(如果使用Apache,则配置gzip的模块取决于您的版本:Apache 1.3使用mod_gzip,而Apache 2.x使用mod_deflate。)

接受编码:gzip,放气

内容编码:gzip

使用以下代码段通过ob_start帮助缓冲区从HTML中删除空格:

<?php

function sanitize_output($buffer) {

    $search = array(
        '/\>[^\S ]+/s',     // strip whitespaces after tags, except space
        '/[^\S ]+\</s',     // strip whitespaces before tags, except space
        '/(\s)+/s',         // shorten multiple whitespace sequences
        '/<!--(.|\s)*?-->/' // Remove HTML comments
    );

    $replace = array(
        '>',
        '<',
        '\\1',
        ''
    );

    $buffer = preg_replace($search, $replace, $buffer);

    return $buffer;
}

ob_start("sanitize_output");

?>

54
这是一个很好的功能,但是如果您使用PRE标签,请当心,有时会在其中删除换行符。
fedmich

2
该代码应该在脚本顶部还是底部在哪里?
jdepypere 2013年

8
您还可以使用该Minify库中的Minify_HTML类($content = \Minify_HTML::minify($content);,甚至可以向内联代码的js / css压缩器添加回调)。见github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh 2014年

21
这还会破坏<script>没有;在每个语句末尾或没有使用注释的内联JavaScript(即,标记中)//
Konstantin Pereiaslov 2014年

8
这将从textarea,pre,input和img中删除空格,这也会破坏嵌入式javascript。如果有人不乐意使用笨重类DOM解析该解决方案基于正则表达式的伟大工程
彼得

28

如果要正确执行,请打开gzip。您还可以执行以下操作:

$this->output = preg_replace(
    array(
        '/ {2,}/',
        '/<!--.*?-->|\t|(?:\r?\n[ \t]*)+/s'
    ),
    array(
        ' ',
        ''
    ),
    $this->output
);

通过将您的html变成一行,没有制表符,没有新行,没有注释,这可以删除大约30%的页面大小。里程可能会有所不同


1
两者都将进一步减少所需的字节数。
Wander Nauta

1
实际上,两者都与gzip相同,在700kb的页面上,gzip会将其压缩到大约400kb,而preg_replace()大约为450kb(均取决于内容),两者都将像399kb,因为gzip删除了相同的空格,然后压缩它
dogmatic69'6

18
这可能具有潜在危险,因为它还会删除IE条件...-您需要将其更改为/<!--(?![if).*?-->/
Katai

3
不起作用,删除过多,弄乱了代码。在W3C有效之前,在此之后无效。
Codebeat 2013年

3
不幸的是,它也破坏了Javascript代码,就像生成更复杂的Google Maps实现一样-正是我需要这样的功能。
richey

19

preg_replace()上面所有解决方案都有单行注释,条件注释和其他陷阱的问题。我建议利用经过充分测试的Minify项目而不是从头开始创建自己的正则表达式。

就我而言,我将以下代码放在PHP页面的顶部以使其最小化:

function sanitize_output($buffer) {
    require_once('min/lib/Minify/HTML.php');
    require_once('min/lib/Minify/CSS.php');
    require_once('min/lib/JSMin.php');
    $buffer = Minify_HTML::minify($buffer, array(
        'cssMinifier' => array('Minify_CSS', 'minify'),
        'jsMinifier' => array('JSMin', 'minify')
    ));
    return $buffer;
}
ob_start('sanitize_output');

1
您的代码未将html放在一行中
karadayi 2015年

阅读Minify项目常见问题解答中的第一个问题。TL; DR:忽略它们。
安德鲁

我试过了,不起作用。我有我的PHP文件,<script>标签之间嵌入了PHP的<style>标记和JavaScript之间的CSS
若昂·皮门特尔·费雷拉

您在哪里放置此代码?最后在页脚或页眉中?
Francesco'Nov

@francesco这应该是页面上的第一段代码。
安德鲁

19

我已经尝试了多个缩小器,它们要么删除得太少,要么删除得太多。

此代码删除了多余的空格和可选的HTML(结尾)标签。它也起到了安全作用,不会删除任何可能破坏HTML,JS或CSS的内容。

该代码还显示了如何在Zend Framework中做到这一点:

class Application_Plugin_Minify extends Zend_Controller_Plugin_Abstract {

  public function dispatchLoopShutdown() {
    $response = $this->getResponse();
    $body = $response->getBody(); //actually returns both HEAD and BODY

    //remove redundant (white-space) characters
    $replace = array(
        //remove tabs before and after HTML tags
        '/\>[^\S ]+/s'   => '>',
        '/[^\S ]+\</s'   => '<',
        //shorten multiple whitespace sequences; keep new-line characters because they matter in JS!!!
        '/([\t ])+/s'  => ' ',
        //remove leading and trailing spaces
        '/^([\t ])+/m' => '',
        '/([\t ])+$/m' => '',
        // remove JS line comments (simple only); do NOT remove lines containing URL (e.g. 'src="http://server.com/"')!!!
        '~//[a-zA-Z0-9 ]+$~m' => '',
        //remove empty lines (sequence of line-end and white-space characters)
        '/[\r\n]+([\t ]?[\r\n]+)+/s'  => "\n",
        //remove empty lines (between HTML tags); cannot remove just any line-end characters because in inline JS they can matter!
        '/\>[\r\n\t ]+\</s'    => '><',
        //remove "empty" lines containing only JS's block end character; join with next line (e.g. "}\n}\n</script>" --> "}}</script>"
        '/}[\r\n\t ]+/s'  => '}',
        '/}[\r\n\t ]+,[\r\n\t ]+/s'  => '},',
        //remove new-line after JS's function or condition start; join with next line
        '/\)[\r\n\t ]?{[\r\n\t ]+/s'  => '){',
        '/,[\r\n\t ]?{[\r\n\t ]+/s'  => ',{',
        //remove new-line after JS's line end (only most obvious and safe cases)
        '/\),[\r\n\t ]+/s'  => '),',
        //remove quotes from HTML attributes that does not contain spaces; keep quotes around URLs!
        '~([\r\n\t ])?([a-zA-Z0-9]+)="([a-zA-Z0-9_/\\-]+)"([\r\n\t ])?~s' => '$1$2=$3$4', //$1 and $4 insert first white-space character found before/after attribute
    );
    $body = preg_replace(array_keys($replace), array_values($replace), $body);

    //remove optional ending tags (see http://www.w3.org/TR/html5/syntax.html#syntax-tag-omission )
    $remove = array(
        '</option>', '</li>', '</dt>', '</dd>', '</tr>', '</th>', '</td>'
    );
    $body = str_ireplace($remove, '', $body);

    $response->setBody($body);
  }
}

但是请注意,使用gZip压缩时,将代码压缩得比任何压缩都可以压缩得多,因此将minmin和gZip结合起来是没有意义的,因为下载所节省的时间因压缩而浪费了,并且节省了最少的时间。

这是我的结果(通过3G网络下载):

 Original HTML:        150kB       180ms download
 gZipped HTML:          24kB        40ms
 minified HTML:        120kB       150ms download + 150ms minification
 min+gzip HTML:         22kB        30ms download + 150ms minification

4
是的,我同意这看似毫无意义,但它可以为您在google的Pagespeed中获得一两个宝贵的分数,这与您的google排名相关。您的代码非常适合删除不需要的空间。谢谢:-)
Tschallacka

1
这很好用,有=“ /”的问题,所以我把'〜([\ r \ n \ t])中的/取出来?([a-zA-Z0-9] +)=“([a-zA -Z0-9 _ / \\-] +)“([[r \ n \ t])?〜s'=>'$ 1 $ 2 = $ 3 $ 4',// $ 1和$ 4插入第一个空格字符后属性
ask_io '16

碰巧的是,我并不是想删除空格只是为了加快速度,而是因为这应该是HTML ,这样才能使事情不会完全弄乱,例如内联块元素,但我也在寻找一种功能忽略需要前后留一个空格的事物(例如,文本块中的粗体元素)。
德吉

我发现某些Jquery / Foundation东西有问题……除非我注释掉以下几行://删除仅包含JS块结束符的“空”行;加入下一行(例如“} \ n} \ n </ script>”->“}} </ script>” //'/} [\ r \ n \ t] + / s'=>'} ',//'/} [\ r \ n \ t] +,[\ r \ n \ t] + / s'=>'},'
Ian

1
如果您使用服务器端缓存(对我来说是Smarty V3),则min + gzip是一个很好的解决方案,但首次调用时除外。因此,如果在第15次通话之后,它将占用服务器时间。规则= 40x15 =(30x15 + 150)但对于第二个呼叫,访问者已经更快了。
Meloman

6

这为我工作。

function Minify_Html($Html)
{
   $Search = array(
    '/(\n|^)(\x20+|\t)/',
    '/(\n|^)\/\/(.*?)(\n|$)/',
    '/\n/',
    '/\<\!--.*?-->/',
    '/(\x20+|\t)/', # Delete multispace (Without \n)
    '/\>\s+\</', # strip whitespaces between tags
    '/(\"|\')\s+\>/', # strip whitespaces between quotation ("') and end tags
    '/=\s+(\"|\')/'); # strip whitespaces between = "'

   $Replace = array(
    "\n",
    "\n",
    " ",
    "",
    " ",
    "><",
    "$1>",
    "=$1");

$Html = preg_replace($Search,$Replace,$Html);
return $Html;
}

5

在文档根目录之外创建一个PHP文件。如果您的文档根目录是

/var/www/html/

在其上一级创建一个名为minify.php的文件

/var/www/minify.php

将以下PHP代码复制粘贴到其中

<?php
function minify_output($buffer){
    $search = array('/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s');
    $replace = array('>','<','\\1');
    if (preg_match("/\<html/i",$buffer) == 1 && preg_match("/\<\/html\>/i",$buffer) == 1) {
        $buffer = preg_replace($search, $replace, $buffer);
    }
    return $buffer;
}
ob_start("minify_output");?>

保存minify.php文件,然后打开php.ini文件。如果它是专用的服务器/ VPS,请搜索以下选项,并使用自定义php.ini在共享主机上添加它。

auto_prepend_file = /var/www/minify.php

参考:http : //websistent.com/how-to-use-php-to-minify-html-output/



2

您可以查看HTML TIDY- http://uk.php.net/tidy

它可以作为PHP模块安装,并且(正确,安全地)去除空格和所有其他麻烦,同时仍然输出完全有效的HTML / XHTML标记。它还会清除您的代码,这可能是一件好事,也可能会很糟糕,这取决于您在一开始编写有效代码的能力如何;-)

此外,您可以在文件开头使用以下代码gzip输出:

ob_start('ob_gzhandler');

问题是该站点将托管在共享站点上,而我将无权安装此类模块。
m3tsys 2011年

很有可能,它将已经安装。检查phpinfo()...至少zlib应该安装允许您使用的ob_gzhandler
Rudi Visser

我已经使用的if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();是不是同一件事?
m3tsys 2011年

2
是的,您确实不需要该else ob_start()部分,也不需要gzip check ... ob_gzhandler检测浏览器内部是否支持任何压缩方法。仅仅拥有ob_start('ob_gzhandler');就足够了。
Rudi Visser

由于存在额外的解析开销,TIDY是否可能比此处的其他答案慢?可能对开发有益-然后您可以在实际的源代码中更正这些HTML错误-但我怀疑这是否是生产的最佳选择。
马特·布朗

2

首先,gzip不仅可以为HTML Minifier提供帮助,

  1. 使用nginx

    gzip on;
    gzip_disable "msie6";
    
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  2. 使用apache可以使用mod_gzip

第二:使用gzip + HTML压缩,您可以大幅减少文件大小!!!

我已经为PHP创建了此HtmlMinifier

您可以通过composer检索它composer require arjanschouten/htmlminifier dev-master

有一个Laravel服务提供商。如果您不使用Laravel,则可以从PHP使用它。

// create a minify context which will be used through the minification process
$context = new MinifyContext(new PlaceholderContainer());
// save the html contents in the context
$context->setContents('<html>My html...</html>');
$minify = new Minify();
// start the process and give the context with it as parameter
$context = $minify->run($context);

// $context now contains the minified version
$minifiedContents = $context->getContents();

如您所见,您可以在此处扩展很多内容,还可以传递各种选项。检查自述文件以查看所有可用选项。

这个HtmlMinifier是完整和安全的。缩小过程需要3个步骤:

  1. 用占位符临时替换关键内容。
  2. 运行缩小策略。
  3. 恢复原始内容。

我建议您缓存视图的输出。缩小过程应该是一次性过程。或例如基于间隔进行。

当时未创建明确的基准。但是,minifier可以根据您的标记将页面大小减小5-25%!

如果要添加自己的策略,则可以使用addPlaceholderaddMinifier方法。


感谢图书馆。说明没有说我需要包含哪些PHP文件。我最终会弄清楚的,但这可能是您应该在您的网站上添加的内容。
玫瑰水,2015年

看起来它仍然需要Illuminate \ Support \ Collection。它不是一个独立的PHP解决方案。
玫瑰水,2015年

感谢您的反馈!它是一个作曲家程序包。我已经使用以下规则更新了自述文件require __DIR__ . '/vendor/autoload.php';您要做的唯一一件事就是包括该文件。这是由作曲家生成的!
ArjanSchouten 2015年

2

我有一个GitHub要点,其中包含PHP函数以最小化HTML,CSS和JS文件→ https://gist.github.com/taufik-nurrohman/d7b310dea3b33e4732c0

以下是使用输出缓冲区动态缩小HTML输出的方法:

<?php

include 'path/to/php-html-css-js-minifier.php';

ob_start('minify_html');

?>

<!-- HTML code goes here ... -->

<?php echo ob_get_clean(); ?>

gist链接指向404页面
1111161171159459134

2
更新了链接。
Taufik Nurrohman

1

如果要删除页面中的所有新行,请使用以下快速代码:

ob_start(function($b){
if(strpos($b, "<html")!==false) {
return str_replace(PHP_EOL,"",$b);
} else {return $b;}
});

0

感谢安德鲁。这是在cakePHP中使用它的方法:

  1. 下载minify-2.1.7
  2. 解压缩文件并将min子文件夹复制到cake的Vendor文件夹
  3. 像下面这样在cake的View / Helper中创建MinifyCodeHelper.php:

    App::import('Vendor/min/lib/Minify/', 'HTML');
    App::import('Vendor/min/lib/Minify/', 'CommentPreserver');
    App::import('Vendor/min/lib/Minify/CSS/', 'Compressor');
    App::import('Vendor/min/lib/Minify/', 'CSS');
    App::import('Vendor/min/lib/', 'JSMin');
    class MinifyCodeHelper extends Helper {
        public function afterRenderFile($file, $data) {
            if( Configure::read('debug') < 1 ) //works only e production mode
                $data = Minify_HTML::minify($data, array(
                    'cssMinifier' => array('Minify_CSS', 'minify'),
                    'jsMinifier' => array('JSMin', 'minify')
                ));
            return $data;
        }
    }
  4. 在AppController中启用了我的助手

    public $ helpers = array('Html','...','MinifyCode');

5 ...瞧!

我的结论是:如果在您的服务器中禁用了apache的deflate和headers模块,则您的增益将减少21%,减少0.35s,并请求压缩(在我的情况下,此数字)。

但是,如果启用了apache的模块,则压缩响应没有明显差异(对我而言为1.3%),而压缩时间为samne(对我而言为0.3s)。

所以...我为什么要这样做?“因为我项目的文档全都在注释中(php,css和js),而我的最终用户则无需查看此内容;)


0

您可以使用()调用经过良好测试的Java压缩程序,例如HTMLCompressor。 记住要使用重定向控制台passthruexec
2>&1

但是,如果考虑到速度,这可能没有用。我将其用于静态php输出

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.