Как минимизировать вывод html страницы php?

148

Я ищу php-скрипт или класс, который может минимизировать html-вывод моей php-страницы, как это делает скорость страницы google.

Как я могу это сделать?

m3tsys
источник
15
Однострочный текст на основе ответа @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia,
5
@FranciscoPresencia Это действительно плохой поступок. Вы нарушаете теги сценария, предварительные теги и т. Д.
Брэд,
1
Это правда, как отмечалось в его комментариях к ответу, они не работают с тегами <pre>или, <code>поскольку им нужны пробелы для правильной структуры. Однако <script>обычно он должен быть внешним или встроенным, но с ;строгим использованием, чтобы он также работал. Какие еще теги могут нарушить @Brad? Я не мог думать о других. Однако я должен был добавить быстрый и грязный путь до моего предыдущего комментария.
Francisco Presencia

Ответы:

219

CSS и Javascript

Рассмотрим следующую ссылку для минимизации файлов Javascript / CSS: https://github.com/mrclay/minify

HTML

Скажите Apache доставлять HTML с помощью GZip - это обычно уменьшает размер ответа примерно на 70%. (Если вы используете Apache, модуль настройки gzip зависит от вашей версии: Apache 1.3 использует mod_gzip, а Apache 2.x использует mod_deflate.)

Принятие кодировки: gzip, deflate

Кодирование содержимого: gzip

Используйте следующий фрагмент, чтобы удалить пробелы из HTML с помощью буфера 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");

?>
Ракеш Санкар
источник
54
Это хорошая функция, но будьте осторожны, если вы используете теги PRE , иногда там удаляются новые строки.
fedmich
2
Где должен быть этот код, вверху или внизу вашего скрипта?
jdepypere
8
Вы также можете использовать класс Minify_HTML из этой библиотеки Minify ( $content = \Minify_HTML::minify($content);вы даже можете добавить обратные вызовы в минификаторы js / css для встроенного кода). См github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh
21
Это также нарушает встроенный JavaScript (то есть в <script>тегах), который не находится ;в конце каждого оператора или имеет комментарии, которые используются//
Константин Переяслов
8
это удалит пробелы из textarea, pre, input, img, также это нарушит встроенные javascripts. если кто-то не счастлив использовать громоздкий класс с DOM, анализируя это решение на основе регулярного выражения, отлично работает
Питер,
27

Включите gzip, если хотите, чтобы это было правильно. Вы также можете сделать что-то вроде этого:

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

Это удаляет около 30% размера страницы, превращая ваш html в одну строку, без вкладок, без новых строк, без комментариев. Пробег может отличаться

догматический69
источник
1
И то, и другое снизит количество необходимых байтов еще больше.
Wander Nauta
1
на самом деле выполнение обоих аналогично использованию gzip, на странице 700 КБ gzip уменьшит его примерно до 400 КБ, а preg_replace () около 450 КБ (все в зависимости от содержимого), оба будут как 399 КБ, поскольку gzip удаляет пробелы одинаково, а затем сжимает его
dogmatic69
18
Это может быть потенциально опасно, так как при этом также удаляются условные обозначения IE ... - вам нужно будет изменить его на /<!--(?![if).*?-->/
Катай
4
Не работает, удаляю лишнее, испортил код. Раньше это было действительным W3C, а после этого нет.
Codebeat
3
К сожалению, он также нарушает код Javascript, например, для создания более сложных реализаций Google Maps - именно для этого мне понадобится такая функция.
Ричи 03
20

У всех 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');
Андрей
источник
2
В вашем коде HTML-код не помещается в одну строку
karadayi
Прочтите первый вопрос в FAQ по проекту Minify . TL; DR: игнорировать их.
Эндрю
Я пробовал, не работает. В моем файле php есть css между тегами <style> и javascript, встроенный с php между тегами <script>,
Жоао Пиментел Феррейра
где вы размещаете этот код? последний в нижнем колонтитуле или заголовке?
Francesco
@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 ваш код сжимается намного сильнее, чем может сделать любая минификация, поэтому объединение минификации и 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, что имеет отношение к вашему рейтингу в Google. Ваш код идеально подходит для удаления ненужных пробелов. Спасибо :-)
Tschallacka 06
1
это отлично работает, были проблемы с = "/", поэтому я взял / из '~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 и $ 4 вставляют первый символ пробела, найденный перед / после атрибута
ask_io
Что ж, так получилось, что я не хочу удалять пробелы, чтобы ускорить процесс, а скорее потому, что таким должен быть HTML , чтобы что-то не облажалось полностью, например, встроенные блочные элементы, но я также ищу один способный игнорирования вещей, которые должны иметь один пробел до или после (например, жирные элементы в текстовом блоке).
Deji
Я обнаружил проблему с некоторыми материалами JQuery / Foundation ... если я не закомментировал следующие строки: // удалить "пустые" строки, содержащие только символ конца блока JS; присоединиться к следующей строке (например, "} \ n} \ n </script>" -> "}} </script>" // '/} [\ r \ n \ t] + / s' => '} », // '/} [\ г \ п \ т] + [\ г \ п \ т] + / с' => '},',
Ян
1
Если вы используете кеширование на стороне сервера (для меня Smarty V3), min + gzip - хорошее решение, за исключением первого вызова. Так что, если после 15-го звонка, будет интересно по серверному времени. rule = 40x15 = (30x15 + 150) Но для второго звонка посетителю уже будет быстрее.
Meloman
9

Эта работа для меня.

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;
}
Мохамад Хамудей
источник
1
Это удалило пробелы, которые не были удалены принятым ответом. 👏 Спасибо!
Хьюго Х,
1
На мой взгляд, лучший ответ, это отлично работает для меня ... Спасибо
Колаволе Эммануэль Иззи
4

Создайте файл 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. Он также очистит ваш код, что может быть как отличным, так и ужасным, в зависимости от того, насколько вы хороши в написании правильного кода в первую очередь ;-)

Кроме того, вы можете сжать выходные данные, используя следующий код в начале вашего файла:

ob_start('ob_gzhandler');
Руди Виссер
источник
проблема в том, что сайт будет размещен в общем доступе, и у меня не будет доступа для установки таких модулей.
m3tsys 03
Скорее всего, он уже будет установлен. Проверить phpinfo()... По крайней мере zlibдолжен быть установлен, чтобы вы могли использовать ob_gzhandler.
Руди Виссер
я уже пользуюсь if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();, разве это не то же самое?
m3tsys 03
2
Да, вам действительно не нужна эта else ob_start()часть, ни проверка gzip ... 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 Minification вы можете значительно уменьшить размер файла !!!

Я создал этот HtmlMinifier для PHP .

Вы можете получить его через композитор: 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();

Как видите, здесь можно многое расширить и передать различные параметры. Проверьте readme, чтобы увидеть все доступные параметры.

Этот HtmlMinifier полный и безопасный. Для процесса минификации требуется 3 шага:

  1. Временная замена критически важного содержимого заполнителем.
  2. Запустите стратегии минификации.
  3. Восстановите исходный контент.

Я бы посоветовал вам кешировать вывод ваших просмотров. Процесс минификации должен быть однократным. Или сделайте это, например, на основе интервала.

Четких тестов на данный момент не создается. Однако минификатор может уменьшить размер страницы на 5-25% в зависимости от вашей разметки!

Если вы хотите добавить вы будете собственные стратегии , которые вы можете использовать addPlaceholderи те addMinifierметоды.

ArjanSchouten
источник
Спасибо за библиотеку. В инструкциях не указано, какие файлы PHP мне нужно включить. В конце концов я это выясню, но вам, вероятно, стоит добавить это на свой сайт.
розовая вода
Похоже, все еще требует Illuminate \ Support \ Collection. Это не отдельное решение PHP.
розовая вода
Спасибо за ответ! Это композиторский пакет. Я обновилrequire __DIR__ . '/vendor/autoload.php'; файл readme следующим правилом: единственное, что вам нужно сделать, это включить этот файл. Это создано композитором!
ArjanSchouten
2

У меня есть GitHub gist, содержащий функции 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
Обновил ссылку.
Тауфик Нуррохман
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 в папку производителя торта.
  3. Создает MinifyCodeHelper.php в View / Helper торта следующим образом:

    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,35 секунды плюс запрос на сжатие (эти числа были в моем случае).

Но если вы включили модули apache, сжатый ответ не имеет существенной разницы (1,3% для меня), а время сжатия составляет samne (0,3 с для меня).

Итак ... зачем я это сделал? Потому что все документы моего проекта находятся в комментариях (php, css и js), и моему последнему пользователю это не нужно видеть;)

бокапио
источник
0

Вы можете использовать хорошо протестированный Java- минификатор, например HTMLCompressor , вызвав его с помощью passthru( exec).
Не забудьте перенаправить консоль, используя2>&1

Однако это может оказаться бесполезным, если важна скорость. Я использую его для статического вывода php

Удджвал Сингх
источник