Comment réduire la sortie html d'une page php?

143

Je recherche un script ou une classe php qui peut réduire la sortie html de ma page php comme le fait la vitesse de la page Google.

Comment puis-je faire ceci?

m3tsys
la source
14
One-liner basé sur la réponse @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia
5
@FranciscoPresencia C'est vraiment une mauvaise chose à faire. Vous cassez les balises de script, les balises pré, etc.
Brad
C'est vrai, comme indiqué dans ses commentaires de réponse, cela ne fonctionne pas avec les balises <pre>ou <code>car ils ont besoin d'espaces pour une structure appropriée. Cependant, le <script>devrait être externe normalement, ou en ligne, mais utilisé ;de manière stricte pour qu'il fonctionne également. Quelles autres balises pourraient casser @Brad? Je ne pouvais pas penser aux autres. J'aurais dû ajouter une manière rapide et sale avant mon commentaire précédent.
Francisco Presencia

Réponses:

213

CSS et Javascript

Considérez le lien suivant pour minifier les fichiers Javascript / CSS: https://github.com/mrclay/minify

HTML

Dites à Apache de fournir du HTML avec GZip - cela réduit généralement la taille de la réponse d'environ 70%. (Si vous utilisez Apache, le module de configuration de gzip dépend de votre version: Apache 1.3 utilise mod_gzip tandis qu'Apache 2.x utilise mod_deflate.)

Accept-Encoding: gzip, dégonfler

Encodage de contenu: gzip

Utilisez l' extrait de code suivant pour supprimer les espaces blancs du HTML avec le tampon de l'aide 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
la source
54
C'est une bonne fonction, mais méfiez-vous si vous utilisez des balises PRE , parfois les nouvelles lignes y seront supprimées.
fedmich
2
Où devrait être ce code, en haut de votre script ou en bas?
jdepypere
8
Vous pouvez également utiliser la classe Minify_HTML de cette bibliothèque Minify ( $content = \Minify_HTML::minify($content);, vous pouvez même ajouter des rappels aux minificateurs js / css pour le code en ligne). Voir github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh
21
Cela rompt également le JavaScript en ligne (c'est-à-dire dans les <script>balises) qui n'a pas ;à la fin de chaque déclaration ou qui contient des commentaires qui utilisent//
Konstantin Pereiaslov
8
cela supprimera les espaces de textarea, pre, input, img également cela rompt les javascripts en ligne. si quelqu'un n'est pas content d'utiliser une classe volumineuse avec l'analyse DOM, cette solution basée sur une expression régulière fonctionne très bien
Peter
28

Activez gzip si vous souhaitez le faire correctement. Vous pouvez également faire quelque chose comme ceci:

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

Cela supprime environ 30% de la taille de la page en transformant votre html en une seule ligne, sans onglets, sans nouvelles lignes, sans commentaires. Le kilométrage peut varier

dogmatique69
la source
1
Faire les deux réduirait encore plus la quantité d'octets nécessaires.
Wander Nauta
1
en fait, faire les deux est la même chose que faire gzip, sur une page de 700 ko, gzip le ramènera à environ 400 ko et preg_replace () à environ 450 ko (tout dépendant du contenu) les deux seront comme 399 kb car gzip supprime les espaces de la même manière, puis compresses it
dogmatic69
18
Cela pourrait être potentiellement dangereux, car cela supprimerait également les conditions IE ... - vous devrez le changer en /<!--(?![if).*?-->/
Katai
3
Ne fonctionne pas, en supprimant trop, gâcher le code. Avant, c'était W3C valide et après cela, ce n'est plus le cas.
Codebeat
3
Malheureusement, cela casse également le code Javascript, comme pour générer des implémentations plus complexes de Google Maps - ce pour quoi j'aurais exactement besoin d'une telle fonction.
richey
19

Toutes les preg_replace()solutions ci-dessus ont des problèmes de commentaires sur une seule ligne, de commentaires conditionnels et d'autres pièges. Je recommanderais de profiter du projet Minify bien testé plutôt que de créer votre propre regex à partir de zéro.

Dans mon cas, je place le code suivant en haut d'une page PHP pour la réduire:

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
la source
1
Votre code ne met pas le code HTML sur une seule ligne
karadayi
Lisez la première question de la FAQ du projet Minify . TL; DR: Ignorez-les.
Andrew
J'ai essayé, ça ne marche pas. J'ai sur mon fichier php, css entre les balises <style> et javascript intégré avec php entre les balises <script>
João Pimentel Ferreira
où placez-vous ce code? dernier dans le pied de page ou l'en-tête?
Francesco
@francesco Cela devrait être le tout premier morceau de code sur votre page.
Andrew
19

J'ai essayé plusieurs minificateurs et ils en retirent trop ou trop peu.

Ce code supprime les espaces vides redondants et les balises HTML facultatives (fin). De plus, il joue en toute sécurité et ne supprime rien qui pourrait potentiellement casser HTML, JS ou CSS.

Le code montre également comment faire cela dans 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);
  }
}

Mais notez que lorsque vous utilisez la compression gZip, votre code est beaucoup plus compressé que toute minification peut le faire, combiner la minification et gZip est inutile, car le temps gagné par le téléchargement est perdu par la minification et économise également un minimum.

Voici mes résultats (téléchargement via le réseau 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
la source
4
oui, je conviens que c'est apparemment inutile, mais cela peut vous marquer un ou deux points précieux en vitesse de page pour google, ce qui est pertinent pour votre classement Google. Votre code est parfait pour supprimer les espaces inutiles. Merci :-)
Tschallacka
1
cela fonctionne très bien, j'ai eu des problèmes avec = "/" donc j'ai pris le / hors de '~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 et $ 4 insèrent le premier caractère d'espace blanc trouvé avant / après l'attribut
demandé_io
Eh bien, je ne cherche pas à supprimer les espaces juste pour accélérer les choses, mais plutôt parce que c'est ainsi que le HTML devrait être pour que les choses ne se gâtent pas totalement, comme les éléments de bloc en ligne, mais je recherche également un capable d'ignorer les choses qui doivent avoir un espace avant ou après (éléments en gras dans un bloc de texte par exemple).
Deji
J'ai trouvé un problème avec certains trucs de Jquery / Foundation ... sauf si j'ai commenté les lignes suivantes: // supprimer les lignes "vides" contenant uniquement le caractère de fin de bloc de JS; joindre avec la ligne suivante (par exemple "} \ n} \ n </script>" -> "}} </script>" // '/} [\ r \ n \ t] + / s' => '} ', //' /} [\ r \ n \ t] +, [\ r \ n \ t] + / s '=>'}, ',
Ian
1
Si vous utilisez la mise en cache côté serveur (pour moi Smarty V3), le min + gzip est une bonne solution sauf au premier appel. Donc, si après le 15e appel, ce sera intéressant pour l'heure du serveur. rule = 40x15 = (30x15 + 150) Mais pour le deuxième appel, ce sera déjà plus rapide pour le visiteur.
Meloman
6

Ce travail pour moi.

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
la source
5

Créez un fichier PHP en dehors de la racine de votre document. Si la racine de votre document est

/var/www/html/

créer un fichier nommé minify.php un niveau au-dessus

/var/www/minify.php

Copiez et collez le code PHP suivant dedans

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

Enregistrez le fichier minify.php et ouvrez le fichier php.ini. S'il s'agit d'un serveur dédié / VPS, recherchez l'option suivante, sur l'hébergement partagé avec php.ini personnalisé, ajoutez-la.

auto_prepend_file = /var/www/minify.php

Référence: http://websistent.com/how-to-use-php-to-minify-html-output/

Avi Tyagi
la source
2

Vous pouvez consulter HTML TIDY - http://uk.php.net/tidy

Il peut être installé en tant que module PHP et supprimera (correctement, en toute sécurité) les espaces blancs et toute autre méchanceté, tout en produisant un balisage HTML / XHTML parfaitement valide. Cela nettoiera également votre code, ce qui peut être une bonne chose ou une chose terrible, selon votre capacité à écrire du code valide en premier lieu ;-)

De plus, vous pouvez gzip la sortie en utilisant le code suivant au début de votre fichier:

ob_start('ob_gzhandler');
Rudi Visser
la source
le problème est que le site sera hébergé sur partagé et je n'aurai pas accès pour installer de tels modules.
m3tsys
Il y a de fortes chances qu'il soit déjà installé. Vérifiez phpinfo()... À tout le moins zlibdevrait être installé vous permettant d'utiliser le ob_gzhandler.
Rudi Visser
j'utilise déjà if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();n'est-ce pas la même chose?
m3tsys
2
Oui, vous n'avez vraiment pas besoin de la else ob_start()pièce, ni de la vérification gzip ... ob_gzhandlerdétecte si le navigateur prend en charge une méthode de compression en interne. Le simple fait d'avoir ob_start('ob_gzhandler');suffira.
Rudi Visser
Une possibilité que TIDY soit plus lent que les autres réponses ici en raison de la surcharge d'analyse supplémentaire? Cela peut être bon pour le développement - alors vous pouvez corriger ces erreurs HTML dans le code source réel - mais je me demande si c'est le meilleur choix pour la production.
Matt Browne
2

Tout d'abord, gzip peut vous aider plus qu'un Minifier Html

  1. Avec 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. Avec apache, vous pouvez utiliser mod_gzip

Deuxièmement: avec gzip + Html Minification, vous pouvez réduire considérablement la taille du fichier !!!

J'ai créé ce HtmlMinifier pour PHP .

Vous pouvez le récupérer par le compositeur: composer require arjanschouten/htmlminifier dev-master.

Il existe un fournisseur de services Laravel. Si vous n'utilisez pas Laravel, vous pouvez l'utiliser depuis 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();

Comme vous pouvez le voir, vous pouvez étendre beaucoup de choses ici et vous pouvez passer diverses options. Vérifiez le readme pour voir toutes les options disponibles.

Ce HtmlMinifier est complet et sûr. Il faut 3 étapes pour le processus de minification:

  1. Remplacez temporairement le contenu critique par un espace réservé.
  2. Exécutez les stratégies de minification.
  3. Restaurez le contenu d'origine.

Je vous suggère de mettre en cache la sortie de vos vues. Le processus de minification doit être un processus unique. Ou faites-le par exemple basé sur un intervalle.

Des repères clairs ne sont pas créés à l'époque. Cependant, le minificateur peut réduire la taille de la page de 5 à 25% en fonction de votre balisage!

Si vous souhaitez ajouter vos propres stratégies, vous pouvez utiliser addPlaceholderles addMinifierméthodes et.

ArjanSchouten
la source
Merci pour la bibliothèque. Les instructions ne disent pas quels fichiers PHP je dois inclure. Je finirai par comprendre, mais c'est quelque chose que vous devriez probablement ajouter sur votre site Web.
eau de rose
Il semble que cela nécessite toujours Illuminate \ Support \ Collection. Ce n'est pas une solution PHP autonome.
eau de rose
Merci pour les commentaires! C'est un package de composition . J'ai mis à jour le fichier Lisez-moi avec la règle suivante: require __DIR__ . '/vendor/autoload.php';la seule chose à faire est d'inclure ce fichier. Ceci est généré par le compositeur!
ArjanSchouten
2

J'ai un gist GitHub contenant des fonctions PHP pour minifier les fichiers HTML, CSS et JS → https://gist.github.com/taufik-nurrohman/d7b310dea3b33e4732c0

Voici comment réduire la sortie HTML à la volée avec le tampon de sortie:

<?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
la source
Le lien principal mène à une page 404
1111161171159459134
2
Mise à jour du lien.
Taufik Nurrohman le
1

Si vous souhaitez supprimer toutes les nouvelles lignes de la page, utilisez ce code rapide:

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

Merci à Andrew . Voici ce que vous avez fait pour l'utiliser dans cakePHP:

  1. Télécharger minify-2.1.7
  2. Décompressez le fichier et copiez le sous-dossier min dans le dossier Vendor de cake
  3. Crée MinifyCodeHelper.php dans le View / Helper de cake comme ceci:

    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. Activé mon Helper dans AppController

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

5 ... Voila!

Ma conclusion: si les modules de dégonflage et d'en-tête d'Apache sont désactivés dans votre serveur, votre gain est de 21% de taille en moins et de 0,35 s plus en demande de compression (ce nombre était dans mon cas).

Mais si vous aviez activé les modules d'Apache, la réponse compressée n'a pas de différence significative (1,3% pour moi) et le temps de compression est le même (0,3 s pour moi).

Alors ... pourquoi ai-je fait ça? 'couse la doc de mon projet est tout dans les commentaires (php, css et js) et mon utilisateur final n'a pas besoin de voir ça;)

bocapio
la source
0

Vous pouvez utiliser un minificateur Java bien testé comme HTMLCompressor en l' appelant à l' aide de passthru( exec).
N'oubliez pas de rediriger la console en utilisant2>&1

Cela peut cependant ne pas être utile si la vitesse est un problème. Je l'utilise pour la sortie php statique

Ujjwal Singh
la source