Як мінімізувати вихід HTML-сторінки на PHP?


143

Я шукаю php-скрипт або клас, який може мінімізувати вихід моєї HTML-сторінки на html-файл, як і швидкість сторінки Google.

Як я можу це зробити?


14
Однолінійний на основі відповіді @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Франсіско Presencia

5
@FranciscoPresencia Це дійсно погано робити. Ви ламаєте теги сценаріїв, попередні теги тощо
Бред

Це правда, як зазначив у своєму коментарі відповіді він не працює з <pre>або <code>тегами , так як вони потребують порожньому просторі для правильної структури. Однак, <script>звичайно , це повинно бути зовнішнім або вбудованим, але використовувати ;строго, щоб воно також працювало. Які ще теги можуть зламати @Brad? Я не міг думати про інших. Я мав би додати швидкий і брудний шлях до мого попереднього коментаря, хоча.
Francisco Presencia

Відповіді:


213

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.)

Accept-Encoding: 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 minifiers для вбудованого коду). Дивіться github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh

21
Це також порушує вбудований JavaScript (тобто в <script>тегах), який не міститься ;в кінці кожної заяви або має коментарі, які використовують//
Костянтин Переяслов

8
це видалить пробіли з textarea, pre, input, img, і це порушить вбудовані javascripts. якщо хтось не радий використовувати об'ємний клас з DOM для розбору цього рішення на основі regexp, чудово працює
Пітер,

28

Увімкніть gzip, якщо ви хочете зробити це правильно. Ви також можете зробити щось подібне:

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

Це видаляє близько 30% розміру сторінки, перетворивши HTML в один рядок, без вкладок, без нових рядків, без коментарів. Пробіг може відрізнятися


1
Виконання обох може ще більше зменшити кількість байтів.
Блукати Наута

1
насправді робити обидва те саме, що робити gzip, на сторінці 700 кбіт gzip зменшить її до приблизно 400 кбіт, а у preg_replace () приблизно 450 кб (все залежно від вмісту) обидва будуть схожі на 399 кб, оскільки gzip видаляє пробіли те саме, а потім стискає його
dogmatic69

18
Це може бути потенційно небезпечним, так як він також буде видалити IE умовних ... - Ви повинні були б змінити його /<!--(?![if).*?-->/
Катай

3
Не працює, видаляючи занадто багато, псуйте код. До цього він був чинним W3C, а після цього - ні.
Codebeat

3
На жаль, він також порушує Javascript-код, як, наприклад, для створення більш складних реалізацій Google Maps - саме для цього мені знадобиться така функція.
richey

19

Усі 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');

1
Ваш Код не розміщує html в один рядок
karadayi

Прочитайте перше запитання у FAQ щодо проекту Minify . TL; DR: Ігноруйте їх.
Андрій

Я спробував, це не працює. У мене на PHP-файлі, css між тегами <style> та javascript, вбудованим у php, між тегами <script>
João Pimentel Ferreira

де ви розміщуєте цей код? останнє у нижньому колонтитулі чи заголовку?
Франческо

@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. Ваш код ідеально підходить для позбавлення зайвих пробілів. Дякую :-)
Цхаллачка

1
це чудово працює, виникли проблеми з = "/", тому я взяв / з '~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 і $ 4 вставити перший символ пробілу, знайдений до / після атрибута
запитав_io

Так, як це буває, я не прагну видалити пробіл просто для прискорення речей, а, швидше, тому, що таким чином повинен бути HTML , щоб речі не повністю викручувались, як елементи вбудованого блоку, але я також шукаю потрібного ігнорування речей, для яких потрібно мати пробіл до або після (наприклад, жирних елементів у текстовому блоці).
Deji

Я знайшов проблему з певними елементами Jquery / Foundation ... якщо я не прокоментував такі рядки: // видалити "порожні" рядки, що містять лише символ кінця блоку JS; приєднатися до наступного рядка (наприклад, "} \ n} \ n </script>" -> "}} </script>" // '/} [\ r \ n \ t] + / s' => '} ', //' /} [\ r \ n \ t] +, [\ r \ n \ t] + / s '=>'}, ',
Іван

1
Якщо ви використовуєте кешування на стороні сервера (для мене Smarty V3), min + gzip є хорошим рішенням, яке виключається під час першого дзвінка. Тож, якщо після 15-го дзвінка, це буде перепитування на час сервера. правило = 40x15 = (30x15 + 150) Але для другого дзвінка це вже буде швидше для відвідувача.
Меломан

6

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

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

5

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

Крім того, ви можете отримати gzip вихід, використовуючи наступний код на початку вашого файлу:

ob_start('ob_gzhandler');

проблема полягає в тому, що сайт буде розміщений на спільному веб-сайті, і я не матиму доступу до встановлення таких модулів.
м3цис

Швидше за все, вона вже буде встановлена. Перевірте phpinfo()... Як мінімум zlibслід встановити, що дозволяє використовувати ob_gzhandler.
Руді Віссер

Я вже використовую, if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();чи не те саме?
m3tsys

2
Так, вам справді не потрібна else ob_start()деталь, ні перевірка gzip ... ob_gzhandlerвиявляє, чи підтримує браузер який-небудь метод стиснення внутрішньо. Просто мати ob_start('ob_gzhandler');буде достатньо.
Руді Віссер

Будь-яка можливість 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. За допомогою апачу можна використовувати 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();

Як бачите, ви можете розширити багато речей тут, і ви можете пройти різні варіанти. Перевірте ритм щоб побачити всі доступні опції.

Цей HtmlMinifier є повним та безпечним. Для процесу мінімізації потрібно 3 кроки:

  1. Замініть критичний вміст тимчасовим на заповнювач.
  2. Виконайте стратегії мінімізації.
  3. Відновити оригінальний вміст.

Я б запропонував вам кешувати висновки своїх поглядів. Процес мінімізації повинен бути одноразовим. Або зробити це, наприклад, на основі інтервалу.

Чіткі орієнтири наразі не створюються. Однак мініфікатор може зменшити розмір сторінки на 5-25% залежно від розмітки!

Якщо ви хочете додати свої власні стратегії, ви можете використовувати методи addPlaceholderта addMinifierметоди.


Дякуємо за бібліотеку. В інструкціях не вказано, які файли PHP мені потрібно включити. Я врешті-решт це зрозумію, але це, напевно, слід додати на своєму веб-сайті.
rosewater

Схоже, це все ще потребує освітлення \ підтримка \ колекція. Це не окреме рішення PHP.
rosewater

Дякуємо за відгук! Це композиторський пакет. Я оновив readme за допомогою наступного правила: require __DIR__ . '/vendor/autoload.php';Єдине, що вам потрібно зробити, це включити цей файл. Це генерує композитор!
ArjanSchouten

2

У мене є суть GitHub, що містить функції 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. Розпакуйте файл і скопіюйте міні-папку у папку постачальника торта
  3. Створює 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;
        }
    }
  4. Увімкнено мого помічника в AppController

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

5 ... Вуаля!

Мій висновок: Якщо на вашому сервері відключені модулі дефляції та заголовків apache, ви отримаєте на 21% менший розмір і 0,35s плюс при запиті на стиснення (у моєму випадку це цифри).

Але якщо ви ввімкнули модулі apache, стислий відгук не має суттєвої різниці (для мене 1,3%), а час на стиснення - це samne (0,3 для мене).

Отже ... чому я це зробив? 'Купіть документ мого проекту все в коментарях (php, css та js), і моєму кінцевому користувачеві цього не потрібно бачити;)


0

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

Однак це може бути не корисним, якщо швидкість викликає занепокоєння. Я використовую його для статичного виводу PHP

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.