如何缩小php页面html输出?

Posted

技术标签:

【中文标题】如何缩小php页面html输出?【英文标题】:How to minify php page html output? 【发布时间】:2011-09-07 16:41:38 【问题描述】:

我正在寻找可以像谷歌页面速度一样缩小我的 php 页面 html 输出的 php 脚本或类。

我该怎么做?

【问题讨论】:

基于@RakeshS 的单线答案:ob_start(function($b)return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);); @FranciscoPresencia 这是一件非常糟糕的事情。您正在破坏脚本标签、前置标签等。 这是真的,正如他在回答 cmets 中指出的那样,它不适用于 <pre><code> 标签,因为它们需要空格来实现正确的结构。但是,<script> 通常应该是外部的,或者是内联的,但要严格使用;,所以它也可以工作。哪些其他标签可能会破坏@Brad?我想不出别人。不过,我应该在我之前的评论之前添加 快速而肮脏的方式 【参考方案1】:

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、deflate

内容编码:gzip

使用 following snippet 在 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");

?>

【讨论】:

这是一个很好的功能,但是如果你使用 PRE 标签要小心它,有时换行会被删除。 这段代码应该在哪里,在脚本的顶部还是底部? 你也可以使用 Minify 库中的 Minify_HTML 类($content = \Minify_HTML::minify($content);,你甚至可以为内联代码添加回调到 js/css 压缩器)。见github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php 这也破坏了内联 JavaScript(即在 &lt;script&gt; 标记中)在每个语句的末尾没有 ; 或有使用 // 的 cmets 这将从 textarea、pre、input、img 中删除空格,这也会破坏内联 javascript。如果有人不乐意使用基于正则表达式的 DOM 解析 this solution 的笨重类,效果很好【参考方案2】:

如果您想正确执行,请打开 gzip。你也可以这样做:

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

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

【讨论】:

两者都做会进一步减少所需的字节数。 实际上两者都做与 gzip 相同,在 700kb 的页面上,gzip 会将其降低到大约 400kb,preg_replace() 大约 450kb(全部取决于内容)两者都将像 399kb gzip 删除相同的空格,然后压缩它 这可能有潜在危险,因为它还会删除 IE 条件... - 您需要将其更改为 // 不行,去掉太多,乱码。在 W3C 有效之前它不是有效的。 不幸的是,它还破坏了 Javascript 代码,例如生成更复杂的谷歌地图实现——这正是我需要这样的功能。【参考方案3】:

我尝试了几个缩小器,它们要么删除的太少,要么删除的太多。

此代码删除了多余的空格和可选的 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 压缩时,您的代码会被压缩得比任何压缩都多得多,因此将压缩和 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

【讨论】:

是的,我同意这看似毫无意义,但它可以为您在 google 的 pagespeed 上获得一两个宝贵的分数,这与您的 google 排名有关。您的代码非常适合去除不需要的空间。谢谢:-) 这很好用, ="/" 有问题,所以我把 / 从 '~([\r\n\t ])?([a-zA-Z0-9]+ )="([a-zA-Z0-9_/\\-]+)"([\r\n\t ])?~s' => '$1$2=$3$4', //$1 和 $4 插入在属性之前/之后找到的第一个空白字符 好吧,碰巧我不想删除空格只是为了加快速度,而是因为 HTML 应该 应该这样,以免事情完全搞砸,就像内联块元素一样,但我也在寻找一种能够忽略需要在之前或之后有一个空格的东西(例如,文本块中的粗体元素)。 我发现某些 Jquery/Foundation 的东西有问题......除非我注释掉以下几行: //remove "empty" lines contains only JS's block end character;加入下一行(例如 "\n\n" --> "" // '/[\r\n\t ]+/s' => ' ', // '/[\r\n\t ]+,[\r\n\t ]+/s' => ',', 如果您使用服务器端缓存(对我来说 Smarty V3),min+gzip 是一个很好的解决方案,但在第一次调用时除外。因此,如果在第 15 次调用之后,服务器时间将会很有趣。 rule = 40x15 = (30x15 + 150) 但是对于第二次调用,访问者已经更快了。【参考方案4】:

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

在我的例子中,我将以下代码放在 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');

【讨论】:

您的代码没有将 html 放在一行中 阅读Minify project FAQ 中的第一个问题。 TL;DR:忽略它们。 我试过了,还是不行。我的 php 文件中有 你把这段代码放在哪里?最后在页脚或页眉中? @francesco 这应该是您页面上的第一段代码。【参考方案5】:

这对我有用。

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;

【讨论】:

这删除了接受答案未删除的空格。 ? 谢谢!【参考方案6】:

在文档根目录之外创建一个 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/

【讨论】:

【参考方案7】:

您可以查看这组类: https://code.google.com/p/minify/source/browse/?name=master#git%2Fmin%2Flib%2FMinify ,你会在那里找到 html/css/js 缩小类。

你也可以试试这个:http://code.google.com/p/htmlcompressor/

祝你好运:)

【讨论】:

【参考方案8】:

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

它可以作为 PHP 模块安装,并且会(正确、安全地)去除空格和所有其他脏东西,同时仍然输出完全有效的 HTML / XHTML 标记。它还会清理你的代码,这可能是一件好事,也可能是一件糟糕的事情,这取决于你在编写有效代码方面的能力;-)

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

ob_start('ob_gzhandler');

【讨论】:

问题是该站点将托管在共享上,我将无权安装此类模块。 很有可能,它已经被安装了。检查phpinfo()... 至少应该安装zlib 允许您使用ob_gzhandler 我已经在使用if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start(); 不是一样的吗? 是的,你真的不需要else ob_start() 部分,也不需要gzip 检查...ob_gzhandler 检测浏览器是否在内部支持任何压缩方法。只需拥有ob_start('ob_gzhandler'); 就足够了。 由于额外的解析开销,TIDY 是否有可能比此处的其他答案慢?可能对开发有好处 - 然后您可以在实际源代码中纠正这些 HTML 错误 - 但我怀疑这是否是生产的最佳选择。【参考方案9】:

首先,gzip 可以帮助您的不仅仅是 Html Minifier

    With 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;
    
    With apache you can use mod_gzip

第二:使用 gzip + Html Minification 可以大幅减小文件大小!!!

我创建了这个HtmlMinifier for PHP。

您可以通过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();

如您所见,您可以在这里扩展很多东西,并且可以传递各种选项。 Check the readme 查看所有可用选项。

此HtmlMinifier 完整且安全。缩小过程需要 3 个步骤:

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

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

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

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

【讨论】:

感谢图书馆。说明没有说明我需要包含哪些 PHP 文件。我最终会弄明白的,但这是您应该在您的网站上添加的内容。 看起来它仍然需要 Illuminate\Support\Collection。它不是一个独立的 PHP 解决方案。 感谢您的反馈!这是一个composer 包。 I've updated the readme 使用以下规则:require __DIR__ . '/vendor/autoload.php'; 您唯一要做的就是包含此文件。这是作曲家生成的!【参考方案10】:

我有一个 GitHub gist 包含用于缩小 HTML、CSS 和 JS 文件的 PHP 函数 → 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(); ?>

【讨论】:

【参考方案11】:

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

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

【讨论】:

【参考方案12】:

感谢Andrew。 这是在 cakePHP 中使用它的方法:

    下载minify-2.1.7 解压文件并将 min 子文件夹复制到 cake 的 Vendor 文件夹中

    在 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;
        
    
    

    在 AppController 中启用我的 Helper

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

5...瞧!

我的结论:如果 apache 的 deflate 和 headers 模块在您的服务器中被禁用,您的收益将减少 21% 的大小和 0.35 秒加上压缩请求(这个数字是在我的情况下)。

但是,如果您启用了 apache 的模块,则压缩响应没有显着差异(对我来说是 1.3%),并且压缩时间是相同的(对我来说是 0.3 秒)。

那么……我为什么要这样做? '因为我项目的文档都在 cmets(php、css 和 js)中,我的最终用户不需要看到这个;)

【讨论】:

【参考方案13】:

您可以通过使用passthru (exec) 来调用像HTMLCompressor 这样经过良好测试的Java minifier。 记得使用2&gt;&amp;1重定向控制台

但是,如果速度是一个问题,这可能没有用。我将它用于静态 php 输出

【讨论】:

【参考方案14】:

最简单的方法是使用strtr 并删除空格。 话虽如此,请不要使用 javascript,因为它可能会破坏您的代码。

$html_minify = fn($html) => strtr($html, [PHP_EOL => '', "\t" => '', '  ' => '', '< ' => '<', '> ' => '>']);

echo $html_minify(<<<HTML
<li class="flex--item">
    <a href="#"
        class="-marketing-link js-gps-track js-products-menu"
        aria-controls="products-popover"
        data-controller="s-popover"
        data-action="s-popover#toggle"
        data-s-popover-placement="bottom"
        data-s-popover-toggle-class="is-selected"
        data-gps-track="top_nav.products.click(location:2, destination:1)"
        data-ga="[&quot;top navigation&quot;,&quot;products menu click&quot;,null,null,null]">
        Products
    </a>
</li>
HTML);

// Response (echo): <li class="flex--item"><a href="#"class="-marketing-link js-gps-track js-products-menu"aria-controls="products-popover"data-controller="s-popover"data-action="s-popover#toggle"data-s-popover-placement="bottom"data-s-popover-toggle-class="is-selected"data-gps-track="top_nav.products.click(location:2, destination:1)"data-ga="[&quot;top navigation&quot;,&quot;products menu click&quot;,null,null,null]">Products</a></li>

【讨论】:

以上是关于如何缩小php页面html输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PHP 输出插入 html div 替换临时图形

如何在页面输出HTML标签

php 我创建的缩小php脚本,以最大限度地提高Googles页面速度得分

php解析json并输出到html页面

php 如何输出DB类上所有SQL语句,页面上的所有 有关mysql 连接,语句 等信息

如何让exec自己运行,php页面继续运行,让PHP不再阻塞