¿Cómo minimizar la salida html de la página php?

143

Estoy buscando un script php o una clase que pueda minimizar la salida html de mi página php como lo hace la velocidad de la página de google.

¿Cómo puedo hacer esto?

m3tsys
fuente
14
One-liner basado en la respuesta de @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia
55
@FranciscoPresencia Eso es algo muy malo que hacer. Estás rompiendo etiquetas de script, preetiquetas, etc.
Brad
Eso es cierto, como se señala en sus comentarios La respuesta no funciona con <pre>o <code>etiquetas ya que necesitan el espacio en blanco para la estructura adecuada. Sin embargo, <script>debe ser externo normalmente, o en línea, pero debe usarse ;de manera estricta para que también funcione. ¿Qué otras etiquetas podrían romper @Brad? No podía pensar en los demás. Sin embargo, debería haber agregado una manera rápida y sucia antes de mi comentario anterior.
Francisco Presencia

Respuestas:

213

CSS y Javascript

Considere el siguiente enlace para minificar archivos Javascript / CSS: https://github.com/mrclay/minify

HTML

Dígale a Apache que entregue HTML con GZip; esto generalmente reduce el tamaño de la respuesta en aproximadamente un 70%. (Si usa Apache, el módulo que configura gzip depende de su versión: Apache 1.3 usa mod_gzip mientras que Apache 2.x usa mod_deflate).

Aceptar-codificación: gzip, desinflar

Codificación de contenido: gzip

Use el siguiente fragmento para eliminar espacios en blanco del HTML con el búfer de ayuda 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
fuente
54
Esta es una buena función, pero tenga cuidado si usa etiquetas PRE , a veces se eliminarán las nuevas líneas allí.
fedmich
2
¿Dónde debería estar este código, en la parte superior de su script o en la parte inferior?
jdepypere
8
También puede usar la clase Minify_HTML de esa biblioteca Minify ( $content = \Minify_HTML::minify($content);incluso puede agregar devoluciones de llamada a los minificadores js / css para el código en línea). Ver github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh
21
Esto también rompe el JavaScript en línea (es decir, en las <script>etiquetas) que no tiene ;al final de cada declaración o tiene comentarios que usan//
Konstantin Pereiaslov
8
Esto eliminará espacios de textarea, pre, input, img y también rompe los javascripts en línea. si alguien no está contento de usar la clase voluminosa con DOM analizando esta solución basada en expresiones regulares funciona muy bien
Peter
28

Active gzip si desea hacerlo correctamente. También puedes hacer algo como esto:

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

Esto elimina aproximadamente el 30% del tamaño de la página al convertir su html en una línea, sin pestañas, sin líneas nuevas, sin comentarios. El millaje puede variar

dogmático69
fuente
1
Hacer ambas cosas reduciría aún más la cantidad de bytes necesarios.
Wander Nauta
1
en realidad, hacer ambas cosas es lo mismo que hacer gzip, en una página de 700kb, gzip lo reducirá a aproximadamente 400kb y preg_replace () a aproximadamente 450kb (todo dependiendo del contenido), ambos serán como 399kb, ya que gzip elimina los espacios de la misma manera y luego lo comprime
dogmatic69
18
Esto podría ser potencialmente peligroso, ya que también eliminaría los condicionales de IE ... - necesitaría cambiarlo a /<!--(?![if).*?-->/
Katai
3
No funciona, eliminando demasiado, estropea el código. Antes era W3C válido y después de esto no lo es.
Codebeat
3
Desafortunadamente, también rompe el código Javascript, como para generar implementaciones más complejas de Google Maps, que es exactamente para lo que necesitaría dicha función.
richey
19

Todas las preg_replace()soluciones anteriores tienen problemas de comentarios de una sola línea, comentarios condicionales y otras dificultades. Recomiendo aprovechar el bien probado proyecto Minify en lugar de crear su propia expresión regular desde cero.

En mi caso, coloco el siguiente código en la parte superior de una página PHP para minimizarlo:

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');
Andrés
fuente
1
Su código no pone el html en una línea
karadayi
Lea la primera pregunta en las preguntas frecuentes del proyecto Minify . TL; DR: Ignóralos.
Andrew
Lo intenté, no funciona. Tengo en mi archivo php, css entre etiquetas <style> y javascript incrustado con php entre etiquetas <script>
João Pimentel Ferreira
¿Dónde colocas este código? último en el pie de página o encabezado?
Francesco
@francesco Esta debería ser la primera pieza de código en su página.
Andrew
19

He probado varios minificadores y eliminan muy poco o demasiado.

Este código elimina espacios vacíos redundantes y etiquetas HTML (finales) opcionales. También es seguro y no elimina nada que pueda romper HTML, JS o CSS.

Además, el código muestra cómo hacerlo en 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);
  }
}

Pero tenga en cuenta que cuando usa la compresión gZip, su código se comprime mucho más de lo que cualquier minificación puede hacerlo, ya que combinar minificación y gZip no tiene sentido, porque el tiempo ahorrado por la descarga se pierde por la minificación y también ahorra un mínimo.

Aquí están mis resultados (descargar a través de la red 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
fuente
44
Sí, estoy de acuerdo en que aparentemente no tiene sentido, pero puede sumarle uno o dos puntos preciosos en la velocidad de página para Google, lo cual es relevante para su clasificación en Google. Su código es perfecto para eliminar los espacios innecesarios. Gracias :-)
Tschallacka
1
esto funciona muy bien, tuve problemas con = "/", así que eliminé / 'de' ~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 y $ 4 insertan el primer carácter de espacio en blanco encontrado antes / después del atributo
ask_io
Bueno, resulta que no estoy buscando eliminar espacios en blanco solo para acelerar las cosas, sino porque así es como debería ser HTML para que las cosas no se arruinen por completo, como los elementos de bloque en línea, pero también estoy buscando uno capaz de ignorar cosas que necesitan tener un espacio antes o después (elementos en negrita en un bloque de texto, por ejemplo).
Deji
Encontré un problema con ciertas cosas de Jquery / Foundation ... a menos que comente las siguientes líneas: // elimine las líneas "vacías" que contienen solo el carácter de final de bloque de JS; unirse con la siguiente línea (por ejemplo, "} \ n} \ n </script>" -> "}} </script>" // '/} [\ r \ n \ t] + / s' => '} ', //' /} [\ r \ n \ t] +, [\ r \ n \ t] + / s '=>'}, ',
Ian
1
Si usa el almacenamiento en caché del lado del servidor (para mí Smarty V3), min + gzip es una buena solución, excepto en la primera llamada. Entonces, si después de la decimoquinta llamada, será interesante para el tiempo del servidor. regla = 40x15 = (30x15 + 150) Pero para la segunda llamada ya será más rápido para el visitante.
Meloman
6

Este trabajo para mi.

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
fuente
5

Cree un archivo PHP fuera de la raíz de su documento. Si la raíz de tu documento es

/var/www/html/

cree un archivo llamado minify.php un nivel por encima de él

/var/www/minify.php

Copie y pegue el siguiente código PHP en él

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

Guarde el archivo minify.php y abra el archivo php.ini. Si se trata de un servidor dedicado / VPS, busque la siguiente opción, en un alojamiento compartido con php.ini personalizado, agréguelo.

auto_prepend_file = /var/www/minify.php

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

Avi Tyagi
fuente
2

Puede consultar HTML TIDY - http://uk.php.net/tidy

Se puede instalar como un módulo PHP y eliminará (correctamente, de forma segura) los espacios en blanco y cualquier otra molestia, al tiempo que genera un marcado HTML / XHTML perfectamente válido. También limpiará su código, lo que puede ser algo grandioso o terrible, dependiendo de lo bueno que sea para escribir un código válido en primer lugar ;-)

Además, puede comprimir la salida usando el siguiente código al comienzo de su archivo:

ob_start('ob_gzhandler');
Rudi Visser
fuente
El problema es que el sitio estará alojado en compartido y no tendré acceso para instalar dichos módulos.
m3tsys
Lo más probable es que ya esté instalado. Comprobar phpinfo()... Como mínimo, zlibdebe instalarse permitiéndole usar el ob_gzhandler.
Rudi Visser
Ya uso if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();¿no es lo mismo?
m3tsys
2
Sí, realmente no necesita la else ob_start()parte, ni la comprobación de gzip ... ob_gzhandlerdetecta si el navegador admite internamente algún método de compresión. Simplemente tener ob_start('ob_gzhandler');será suficiente.
Rudi Visser
¿Alguna posibilidad de que TIDY sea más lento que las otras respuestas aquí debido a la sobrecarga de análisis adicional? Podría ser bueno para el desarrollo, entonces puede corregir esos errores HTML en el código fuente real, pero me pregunto si esta es la mejor opción para la producción.
Matt Browne
2

En primer lugar, gzip puede ayudarte más que un Minificador Html

  1. Con 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. Con apache puedes usar mod_gzip

Segundo: ¡con gzip + Html Minification puede reducir drásticamente el tamaño del archivo!

He creado este HtmlMinifier para PHP .

Se puede recuperar a través compositor: composer require arjanschouten/htmlminifier dev-master.

Hay un proveedor de servicios Laravel. Si no está usando Laravel, puede usarlo desde 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 puede ver, puede extender muchas cosas aquí y puede pasar varias opciones. Consulte el archivo Léame para ver todas las opciones disponibles.

Este HtmlMinifier es completo y seguro. Se requieren 3 pasos para el proceso de minificación:

  1. Reemplace contenido crítico temporal con un marcador de posición.
  2. Ejecute las estrategias de minificación.
  3. Restaurar el contenido original.

Te sugiero que guardes en caché la salida de tus vistas. El proceso de minificación debe ser un proceso de una sola vez. O hágalo por ejemplo basado en intervalos.

Los puntos de referencia claros no se crean en el momento. Sin embargo, el minificador puede reducir el tamaño de la página en un 5-25% según el marcado.

Si desea agregar sus propias estrategias, puede usar addPlaceholderlos addMinifiermétodos y.

ArjanSchouten
fuente
Gracias por la biblioteca Las instrucciones no dicen qué archivos PHP necesito incluir. Eventualmente lo resolveré, pero eso es algo que probablemente deberías agregar en tu sitio web.
agua de rosas
Parece que todavía requiere Illuminate \ Support \ Collection. No es una solución PHP independiente.
agua de rosas
¡Gracias por la respuesta! Es un paquete compositor . He actualizado elrequire __DIR__ . '/vendor/autoload.php'; archivo Léame con la siguiente regla: lo único que debe hacer es incluir este archivo. Esto es generado por el compositor!
ArjanSchouten
2

Tengo una esencia de GitHub que contiene funciones PHP para minificar archivos HTML, CSS y JS → https://gist.github.com/taufik-nurrohman/d7b310dea3b33e4732c0

Aquí se explica cómo minimizar la salida HTML sobre la marcha con el búfer de salida:

<?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
fuente
enlace esencial conduce a una página 404
1111161171159459134
2
Actualizado el enlace.
Taufik Nurrohman
1

Si desea eliminar todas las líneas nuevas en la 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;}
});
زياد
fuente
0

Gracias a Andrew . Esto es lo que hizo para usar esto en cakePHP:

  1. Descargar minify-2.1.7
  2. Descomprima el archivo y copie la subcarpeta min en la carpeta Vendor de cake
  3. Crea MinifyCodeHelper.php en View / Helper de cake de esta manera:

    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 mi ayudante en AppController

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

5 ... ¡Voila!

Mi conclusión: si los módulos de deflación y encabezado de apache están deshabilitados en su servidor, su ganancia es un 21% menor en tamaño y 0.35s más en la solicitud de compresión (estos números fueron en mi caso).

Pero si hubiera habilitado los módulos de apache, la respuesta comprimida no tiene una diferencia significativa (1.3% para mí) y el tiempo para comprimir es el samne (0.3s para mí).

Entonces ... ¿por qué hice eso? porque el documento de mi proyecto está todo en comentarios (php, css y js) y mi usuario final no necesita ver esto;)

bocapio
fuente
0

Puede usar un minificador Java bien probado como HTMLCompressor invocandolo usando passthru( exec).
Recuerde redirigir la consola usando2>&1

Sin embargo, esto puede no ser útil si la velocidad es una preocupación. Lo uso para la salida estática de php

Ujjwal Singh
fuente