Como reduzir a saída de hpml da página php?

143

Eu estou procurando um script php ou classe que pode reduzir minha saída html da página php como a velocidade da página do google.

Como posso fazer isso?

m3tsys
fonte
14
One-liner com base na resposta @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia
5
@FranciscoPresencia Isso é uma coisa muito ruim de se fazer. Você está quebrando tags de script, pré tags etc.
Brad
Isso é verdade, conforme observado em sua resposta, os comentários não funcionam com <pre>ou <code>tags, pois precisam do espaço em branco para a estrutura adequada. No entanto, o <script>deve ser externo normalmente ou em linha, mas usando de ;maneira estrita, para que também funcione. Quais outras tags podem quebrar @Brad? Eu não conseguia pensar nos outros. Eu deveria ter adicionado maneira rápida e suja antes do meu comentário anterior.
Francisco Presencia 14/01

Respostas:

213

CSS e Javascript

Considere o seguinte link para reduzir os arquivos Javascript / CSS: https://github.com/mrclay/minify

HTML

Diga ao Apache para entregar HTML com GZip - isso geralmente reduz o tamanho da resposta em cerca de 70%. (Se você usa o Apache, o módulo que configura o gzip depende da sua versão: o Apache 1.3 usa o mod_gzip enquanto o Apache 2.x usa o mod_deflate.)

Accept-Encoding: gzip, deflate

Codificação de conteúdo: gzip

Use o seguinte trecho para remover espaços em branco do HTML com o buffer da ajuda ob_start:

<?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");

?>
Rakesh Sankar
fonte
54
Essa é uma boa função, mas tenha cuidado se você usar tags PRE , às vezes as novas linhas serão removidas.
fedmich
2
Onde esse código deve estar, na parte superior do script ou na parte inferior?
jdepypere
8
Você também pode usar a classe Minify_HTML dessa biblioteca Minify ( $content = \Minify_HTML::minify($content);você pode até adicionar retornos de chamada aos minificadores js / css para obter código embutido). Veja github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh
21
Isso também quebras em linha JavaScript (ou seja, em <script>etiquetas) que não têm ;no final de cada declaração ou tem comentários que uso//
Konstantin Pereiaslov
8
isso removerá espaços da área de texto, pre, input, img e isso também quebra javascripts embutidos. se alguém não está feliz em usar classe volumosos com DOM analisar esta solução baseada em regexp funciona muito bem
Peter
28

Ative o gzip se desejar fazê-lo corretamente. Você também pode fazer algo assim:

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

Isso remove cerca de 30% do tamanho da página, transformando seu html em uma linha, sem guias, sem novas linhas, sem comentários. A milhagem pode variar

dogmatic69
fonte
1
Fazer as duas coisas reduziria ainda mais a quantidade de bytes necessários.
Wander Nauta
1
na verdade, fazer as duas coisas é o mesmo que fazer o gzip, em uma página de 700kb o gzip o reduz para cerca de 400kb e o preg_replace () cerca de 450kb (tudo depende do conteúdo) ambos terão 399kb, pois o gzip remove os espaços da mesma forma e depois comprime
dogmatic69
18
Isto poderia ser potencialmente perigoso, uma vez que também iria remover condicionais do IE ... - você precisará alterá-lo para /<!--(?![if).*?-->/
Katai
3
Não funciona, removendo muito, atrapalha o código. Antes era válido para o W3C e depois disso não era.
Codebeat 13/01
3
Infelizmente, ele também quebra o código Javascript, como por gerar implementações mais complexas do Google Maps - exatamente para as quais eu precisaria dessa função.
Richey
19

Todas as preg_replace()soluções acima apresentam problemas de comentários de linha única, comentários condicionais e outras armadilhas. Eu recomendo tirar proveito do projeto Minify bem testado , em vez de criar sua própria regex do zero.

No meu caso, coloco o seguinte código no topo de uma página PHP para reduzi-lo:

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');
Andrew
fonte
1
Será que o seu código não colocar o html em uma linha
Karadayı
Leia a primeira pergunta nas perguntas frequentes do projeto Minify . TL; DR: Ignore-os.
18715 Andrew
Eu tentei, não funciona. Eu tenho no meu arquivo php, css entre <style> e javascript incorporado com php entre tags <script>
João Pimentel Ferreira
onde você coloca esse código? último no rodapé ou cabeçalho?
Francesco
@ francesco Esse deve ser o primeiro código da sua página.
28416 Andrew
19

Eu tentei vários minifiers e eles removem muito pouco ou muito.

Esse código remove espaços vazios redundantes e tags HTML (finais) opcionais. Também é seguro e não remove nada que possa potencialmente quebrar HTML, JS ou CSS.

Além disso, o código mostra como fazer isso no 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);
  }
}

Mas observe que, ao usar a compactação gZip, seu código é compactado muito mais do que qualquer minificação, combinando minificação e o gZip é inútil, porque o tempo economizado pelo download é perdido pela minificação e também economiza o mínimo.

Aqui estão meus resultados (download via rede 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
Radek Pech
fonte
4
Sim, eu concordo que isso é aparentemente inútil, mas ele pode marcar um ou dois pontos preciosos na velocidade da página para o Google, o que é relevante para a sua classificação no Google. Seu código é perfeito para eliminar os espaços desnecessários. Obrigado :-)
Tschallacka
1
isso funciona muito bem, tive problemas com = "/" então tirei o / fora de '~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 e $ 4 insere o primeiro caractere de espaço em branco encontrado antes / depois do atributo
perguntou_io 15/01
Bem, acontece que eu não estou procurando remover espaços em branco apenas para acelerar as coisas, mas sim porque é assim que o HTML deve ser para que as coisas não estraguem totalmente, como elementos de bloco embutidos, mas também estou procurando por um capaz de ignorar coisas que precisam ter um espaço antes ou depois (elementos em negrito em um bloco de texto, por exemplo).
Deji
Eu encontrei um problema com certas coisas do Jquery / Foundation ... a menos que comentei as seguintes linhas: // remove as linhas "vazias" que contêm apenas o caractere final do bloco de JS; junte-se à próxima linha (por exemplo, "} \ n} \ n </script>" -> "}} </script>" // '/} [\ r \ n \ t] + / s' => '} ', //' /} [\ r \ n \ t] +, [\ r \ n \ t] + / s '=>'}, ',
Ian Ian
1
Se você usa o cache do lado do servidor (para mim, Smarty V3), o min + gzip é uma boa solução, exceto na primeira chamada. Portanto, se após a 15ª chamada, será interessante o tempo do servidor. rule = 40x15 = (30x15 + 150) Mas, na segunda chamada, já será mais rápido para o visitante.
Meloman
6

Este trabalho para mim.

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;
}
Mohamad Hamouday
fonte
5

Crie um arquivo PHP fora da raiz do documento. Se a raiz do seu documento for

/var/www/html/

crie um arquivo chamado minify.php um nível acima dele

/var/www/minify.php

Copie e cole o seguinte código PHP nele

<?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");?>

Salve o arquivo minify.php e abra o arquivo php.ini. Se for uma pesquisa de servidor / VPS dedicada para a seguinte opção, na hospedagem compartilhada com o php.ini personalizado, adicione-a.

auto_prepend_file = /var/www/minify.php

Referência: http://websistent.com/how-to-use-php-to-minify-html-output/

Avi Tyagi
fonte
2

Você pode ver o HTML TIDY - http://uk.php.net/tidy

Ele pode ser instalado como um módulo PHP e retira (corretamente, com segurança) o espaço em branco e todas as outras maldades, enquanto ainda gera uma marcação HTML / XHTML perfeitamente válida. Ele também limpará seu código, o que pode ser ótimo ou terrível, dependendo de como você é bom em escrever código válido ;-)

Além disso, você pode compactar a saída usando o seguinte código no início do seu arquivo:

ob_start('ob_gzhandler');
Rudi Visser
fonte
o problema é que o site será hospedado em compartilhado e não terei acesso para instalar esses módulos.
m3tsys
Provavelmente, ele já estará instalado. Marque phpinfo()... No mínimo, zlibdeve ser instalado, permitindo que você use o ob_gzhandler.
Rudi Visser
eu já uso if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();não é a mesma coisa?
M3tsys 03/06
2
Sim, você realmente não precisa da else ob_start()peça, nem a verificação do gzip ... ob_gzhandlerdetecta se o navegador suporta qualquer método de compactação internamente. Simplesmente ter ob_start('ob_gzhandler');será suficiente.
Rudi Visser
Alguma possibilidade de TIDY ser mais lento do que as outras respostas aqui por causa da sobrecarga de análise extra? Pode ser bom para o desenvolvimento - então você pode corrigir esses erros de HTML no código-fonte real - mas questiono se essa é a melhor opção para produção.
precisa
2

Antes de tudo, o gzip pode ajudá-lo mais do que um Minificador de HTML

  1. Com 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. Com o apache você pode usar o mod_gzip

Segundo: com gzip + Html Minification você pode reduzir drasticamente o tamanho do arquivo !!!

Eu criei este HtmlMinifier para PHP .

Você pode recuperá-lo através compositor: composer require arjanschouten/htmlminifier dev-master.

Existe um provedor de serviços Laravel. Se você não estiver usando o Laravel, poderá usá-lo no 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();

Como você pode ver, você pode estender muitas coisas aqui e pode passar várias opções. Verifique o leia - me para ver todas as opções disponíveis.

Este HtmlMinifier é completo e seguro. São necessárias três etapas para o processo de minificação:

  1. Substitua o conteúdo crítico temporariamente por um espaço reservado.
  2. Execute as estratégias de minificação.
  3. Restaure o conteúdo original.

Eu sugiro que você armazene em cache a saída de suas visualizações. O processo de minificação deve ser único. Ou faça-o, por exemplo, com base em intervalo.

Benchmarks claros não são criados no momento. No entanto, o minificador pode reduzir o tamanho da página em 5 a 25%, com base na sua marcação!

Se você quiser adicionar suas próprias estratégias, poderá usar addPlaceholderos addMinifiermétodos

ArjanSchouten
fonte
Obrigado pela biblioteca. As instruções não dizem quais arquivos PHP eu preciso incluir. Acabarei descobrindo, mas isso é algo que você provavelmente deve adicionar ao seu site.
Rosewater
Parece que ainda requer Illuminate \ Support \ Collection. Não é uma solução PHP independente.
Rosewater
Obrigado pelo feedback! É um compositor pacote de . Atualizei o leia - me com a seguinte regra: require __DIR__ . '/vendor/autoload.php';A única coisa que você deve fazer é incluir este arquivo. Isso é gerado pelo compositor!
ArjanSchouten
2

Eu tenho uma lista GitHub que contém funções PHP para reduzir arquivos HTML, CSS e JS → https://gist.github.com/taufik-nurrohman/d7b310dea3b33e4732c0

Veja como reduzir a saída HTML em tempo real com o buffer de saída:

<?php

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

ob_start('minify_html');

?>

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

<?php echo ob_get_clean(); ?>
Taufik Nurrohman
fonte
o link principal leva a uma página 404
1111161171159459134 em 29/01
2
Atualizado o link.
Taufik Nurrohman 29/01
1

Se você deseja remover todas as novas linhas da página, use este código rápido:

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

Obrigado ao Andrew . Aqui está o que você fez para usar isso no cakePHP:

  1. Download minify-2.1.7
  2. Descompacte o arquivo e copie a subpasta min para a pasta Fornecedor do bolo
  3. Cria MinifyCodeHelper.php no View / Helper do bolo, assim:

    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. Habilitado meu auxiliar no AppController

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

5 ... Voila!

Minha conclusão: se os módulos deflate e headers do apache estiverem desativados no seu servidor, seu ganho será 21% menor e 0,35s mais no pedido de compactação (esse número foi no meu caso).

Mas se você ativou os módulos do apache, a resposta compactada não tem diferença significativa (1,3% para mim) e o tempo para compactar é o mesmo (0,3s para mim).

Então ... por que eu fiz isso? porque o documento do meu projeto está todo em comentários (php, css e js) e meu usuário final não precisa ver isso;)

bocapio
fonte
0

Você pode usar um minificador Java bem testado como HTMLCompressor chamando-o usando passthru( exec).
Lembre-se de redirecionar o console usando2>&1

No entanto, isso pode não ser útil, se a velocidade for uma preocupação. Eu o uso para saída php estática

Ujjwal Singh
fonte