Làm thế nào để giảm thiểu đầu ra html trang php?


143

Tôi đang tìm kiếm một tập lệnh php hoặc lớp có thể thu nhỏ đầu ra html trang php của tôi như tốc độ trang google.

Tôi có thể làm cái này như thế nào?


14
Một lớp lót dựa trên câu trả lời của @RakeshS:ob_start(function($b){return preg_replace(['/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],['>','<','\\1'],$b);});
Francisco Presencia

5
@FranciscoPresencia Đó là một điều thực sự tồi tệ. Bạn đang phá vỡ các thẻ script, thẻ pre, v.v.
Brad

Điều đó đúng, như đã lưu ý trong câu trả lời của anh ấy, nó không hoạt động với <pre>hoặc <code>thẻ vì chúng cần khoảng trắng cho cấu trúc phù hợp. Tuy nhiên, <script>nên là bên ngoài bình thường, hoặc nội tuyến nhưng sử dụng ;một cách nghiêm ngặt để nó cũng hoạt động. Những thẻ khác migh nó phá vỡ @Brad? Tôi không thể nghĩ về người khác. Tôi nên đã thêm cách nhanh chóng và bẩn trước khi bình luận trước đó của tôi mặc dù.
Francisco Presencia 14/1/2015

Câu trả lời:


212

CSS và Javascript

Hãy xem xét liên kết sau để thu nhỏ các tệp Javascript / CSS: https://github.com/mrclay/minify

HTML

Yêu cầu Apache phân phối HTML bằng GZip - điều này thường làm giảm kích thước phản hồi khoảng 70%. (Nếu bạn sử dụng Apache, mô-đun cấu hình gzip tùy thuộc vào phiên bản của bạn: Apache 1.3 sử dụng mod_gzip trong khi Apache 2.x sử dụng mod_deflate.)

Mã hóa chấp nhận: gzip, giảm phát

Mã hóa nội dung: gzip

Sử dụng đoạn mã sau để xóa khoảng trắng khỏi HTML với bộ đệm của 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
Đây là một chức năng tốt nhưng hãy cảnh giác với nó nếu bạn sử dụng thẻ PRE , đôi khi các dòng mới sẽ bị xóa ở đó.
fedmich

2
Mã này nên ở đâu, ở đầu tập lệnh của bạn hay ở dưới cùng?
jdepypere

8
Bạn cũng có thể sử dụng lớp MinifyMHz từ thư viện Minify đó ( $content = \Minify_HTML::minify($content);thậm chí bạn có thể thêm các cuộc gọi lại vào các công cụ khai thác js / css cho mã nội tuyến). Xem github.com/mrclay/minify/blob/master/min/lib/Minify/HTML.php
Barryvdh

21
Điều này cũng phá vỡ JavaScript nội tuyến (tức là trong <script> thẻ) không có ;ở cuối mỗi câu lệnh hoặc có nhận xét sử dụng//
Konstantin Pereiaslov

8
điều này sẽ loại bỏ khoảng trắng khỏi textarea, pre, input, img, điều này cũng phá vỡ các javascripts nội tuyến. nếu ai đó không hài lòng khi sử dụng lớp cồng kềnh với DOM phân tích giải pháp này dựa trên công cụ regex tuyệt vời
Peter

28

Bật gzip nếu bạn muốn làm đúng cách. Bạn cũng có thể làm một cái gì đó như thế này:

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

Điều này loại bỏ khoảng 30% kích thước trang bằng cách biến html của bạn thành một dòng, không có tab, không có dòng mới, không có nhận xét. Số dặm có thể thay đổi


1
Làm cả hai sẽ làm giảm số lượng byte cần thiết hơn nữa.
Đi lang thang Nauta

1
thực sự làm cả hai cũng giống như làm gzip, trên gzip trang 700kb sẽ giảm xuống còn khoảng 400kb và preg numplace () khoảng 450kb (tất cả phụ thuộc vào nội dung) cả hai sẽ giống như 399kb vì gzip sẽ xóa các khoảng trắng giống nhau và sau đó nén nó
dogmatic69

18
Điều này có thể nguy hiểm, vì nó cũng sẽ loại bỏ các điều kiện IE ... - bạn sẽ cần thay đổi nó thành /<!--(?![if).*?-->/
Katai

3
Không hoạt động, loại bỏ quá nhiều, làm rối mã. Trước đó, W3C hợp lệ và sau này thì không.
Codebeat

3
Thật không may, nó cũng phá vỡ mã Javascript, như để tạo ra các triển khai Google Maps phức tạp hơn - chính xác là tôi sẽ cần một chức năng như vậy.
richey

19

Tất cả các preg_replace()giải pháp trên có vấn đề về nhận xét dòng đơn, nhận xét có điều kiện và các cạm bẫy khác. Tôi khuyên bạn nên tận dụng dự án Minify được thử nghiệm tốt hơn là tạo regex của riêng bạn từ đầu.

Trong trường hợp của tôi, tôi đặt đoạn mã sau ở đầu trang PHP để thu nhỏ nó:

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
Mã của bạn không đặt html thành một dòng
karadayi 18/2/2015

Hãy đọc câu hỏi đầu tiên trong Câu hỏi thường gặp về dự án Minify . TL; DR: Bỏ qua chúng.
Andrew

Tôi đã thử, nó không hoạt động. Tôi có trên tệp php của mình, css giữa các thẻ <style> và javascript được nhúng với php giữa các thẻ <script>
João Pimentel Ferreira

Bạn đặt mã này ở đâu? cuối cùng trong chân trang hoặc tiêu đề?
Francesco

@francesco Đây phải là đoạn mã đầu tiên trên trang của bạn.
Andrew

19

Tôi đã thử một vài công cụ khai thác và chúng loại bỏ quá ít hoặc quá nhiều.

Mã này loại bỏ các khoảng trống dư thừa và các thẻ HTML (kết thúc) tùy chọn. Ngoài ra, nó chơi an toàn và không xóa bất kỳ thứ gì có khả năng phá vỡ HTML, JS hoặc CSS.

Ngoài ra mã cho thấy cách thực hiện điều đó trong 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);
  }
}

Nhưng lưu ý rằng khi sử dụng nén gZip, mã của bạn sẽ được nén nhiều hơn nữa mà bất kỳ sự thu nhỏ nào cũng có thể thực hiện được nên việc kết hợp thu nhỏ và gZip là vô nghĩa, vì thời gian lưu bằng cách tải xuống bị mất bằng cách thu nhỏ và cũng tiết kiệm tối thiểu.

Đây là kết quả của tôi (tải xuống qua mạng 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
vâng, tôi đồng ý rằng điều đó dường như vô nghĩa, nhưng nó có thể ghi cho bạn một hoặc hai điểm quý giá trong trang dành cho google, có liên quan đến xếp hạng google của bạn. Mã của bạn là hoàn hảo để tước bỏ các không gian không cần thiết. Cảm ơn :-)
Tschallacka

1
điều này hoạt động rất tốt, có vấn đề với = "/" vì vậy tôi đã lấy / ra khỏi '~ ([\ r \ n \ t])? ([a-zA-Z0-9] +) = "([a-zA -Z0-9 _ / \\ -] +) "([\ r \ n \ t])? ~ S '=>' $ 1 $ 2 = $ 3 $ 4 ', // $ 1 và $ 4 chèn ký tự khoảng trắng đầu tiên được tìm thấy trước / sau thuộc tính
hỏi_io

Vâng, điều đó xảy ra, tôi không tìm cách loại bỏ khoảng trắng chỉ để tăng tốc mọi thứ, mà là vì đó là cách HTML nên để mọi thứ không hoàn toàn sai sót, như các yếu tố khối nội tuyến, nhưng tôi cũng đang tìm kiếm một khả năng bỏ qua những thứ cần có một khoảng trắng trước hoặc sau (ví dụ các phần tử in đậm trong một khối văn bản).
Deji

Tôi đã tìm thấy một vấn đề với một số công cụ Jquery / Foundation nhất định ... trừ khi tôi nhận xét các dòng sau: // xóa các dòng "trống" chỉ chứa ký tự kết thúc khối của JS; tham gia với dòng tiếp theo (ví dụ: "} \ n} \ n </ script>" -> "}} </ script>" // '/} [\ r \ n \ t] + / s' => '} ', //' /} [\ r \ n \ t] +, [\ r \ n \ t] + / s '=>'}, ',
Ian

1
Nếu bạn sử dụng bộ nhớ đệm phía máy chủ (đối với tôi Smarty V3), min + gzip là một giải pháp tốt ngoại trừ trong cuộc gọi đầu tiên. Vì vậy, nếu sau cuộc gọi thứ 15, nó sẽ được xen kẽ thời gian của máy chủ. rule = 40x15 = (30x15 + 150) Nhưng đối với cuộc gọi thứ hai, nó sẽ nhanh hơn cho khách truy cập.
Meloman

6

Công việc này cho tôi.

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

Tạo một tệp PHP bên ngoài gốc tài liệu của bạn. Nếu tài liệu gốc của bạn là

/var/www/html/

tạo một tệp có tên minify.php một cấp trên nó

/var/www/minify.php

Sao chép dán mã PHP sau vào nó

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

Lưu tệp minify.php và mở tệp php.ini. Nếu đó là một máy chủ / VPS chuyên dụng tìm kiếm cho tùy chọn sau, trên lưu trữ được chia sẻ với php.ini tùy chỉnh, hãy thêm nó.

auto_prepend_file = /var/www/minify.php

Tham khảo: http://websistent.com/how-to-use-php-to-minify-html-output/



2

Bạn có thể xem xét HTML TIDY - http://uk.php.net/tidy

Nó có thể được cài đặt như một mô-đun PHP và sẽ (chính xác, an toàn) loại bỏ khoảng trắng và tất cả sự khó chịu khác, trong khi vẫn xuất ra đánh dấu HTML / XHTML hoàn toàn hợp lệ. Nó cũng sẽ làm sạch mã của bạn, điều này có thể là một điều tuyệt vời hoặc là một điều tồi tệ, tùy thuộc vào mức độ bạn giỏi trong việc viết mã hợp lệ ở vị trí đầu tiên ;-)

Ngoài ra, bạn có thể gzip đầu ra bằng cách sử dụng đoạn mã sau khi bắt đầu tệp của mình:

ob_start('ob_gzhandler');

vấn đề là trang web sẽ được lưu trữ trên chia sẻ và tôi sẽ không có quyền truy cập để cài đặt các mô-đun như vậy.
m3tsys

Rất có thể, nó sẽ được cài đặt. Kiểm tra phpinfo()... Ít nhất zlibnên được cài đặt cho phép bạn sử dụng ob_gzhandler.
Rudi Visser

tôi đã sử dụng if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start();không phải là điều tương tự?
m3tsys

2
Đúng vậy, bạn thực sự không cần else ob_start()phần đó, cũng không phải kiểm tra gzip ... ob_gzhandlerphát hiện xem trình duyệt có hỗ trợ bất kỳ phương pháp nén nào trong nội bộ hay không. Đơn giản chỉ cần có là ob_start('ob_gzhandler');đủ.
Rudi Visser

Bất kỳ khả năng TIDY nào chậm hơn các câu trả lời khác ở đây vì chi phí phân tích cú pháp thêm? Có thể tốt cho phát triển - sau đó bạn có thể sửa các lỗi HTML đó trong mã nguồn thực tế - nhưng tôi đặt câu hỏi liệu đây có phải là lựa chọn tốt nhất cho sản xuất không.
Matt Browne

2

Trước hết gzip có thể giúp bạn nhiều hơn Công cụ khai thác Html

  1. Với 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. Với apache, bạn có thể sử dụng mod_gzip

Thứ hai: với gzip + Html Minifying, bạn có thể giảm kích thước tệp một cách mạnh mẽ !!!

Tôi đã tạo HtmlMinifier này cho PHP .

Bạn có thể lấy nó thông qua nhà soạn nhạc : composer require arjanschouten/htmlminifier dev-master.

Có một nhà cung cấp dịch vụ Laravel. Nếu bạn không sử dụng Laravel, bạn có thể sử dụng nó từ 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();

Như bạn thấy bạn có thể mở rộng rất nhiều thứ ở đây và bạn có thể vượt qua các tùy chọn khác nhau. Kiểm tra readme để xem tất cả các tùy chọn có sẵn.

Điều này HtmlMinifier là đầy đủ và an toàn. Phải mất 3 bước cho quy trình thu nhỏ:

  1. Thay thế nội dung quan trọng tạm thời bằng một trình giữ chỗ.
  2. Chạy các chiến lược thu nhỏ.
  3. Khôi phục nội dung ban đầu.

Tôi sẽ đề nghị bạn lưu trữ đầu ra của lượt xem. Quá trình tối thiểu hóa nên là một quá trình một lần. Hoặc làm điều đó ví dụ dựa trên khoảng.

Điểm chuẩn rõ ràng không được tạo ra tại thời điểm đó. Tuy nhiên, công cụ khai thác có thể giảm kích thước trang với 5-25% dựa trên đánh dấu của bạn!

Nếu bạn muốn thêm các chiến lược của riêng mình, bạn có thể sử dụng addPlaceholdercác addMinifierphương thức và.


Cảm ơn thư viện. Các hướng dẫn không nói những tập tin PHP tôi cần bao gồm. Cuối cùng tôi sẽ tìm ra nó, nhưng đó là thứ bạn có thể nên thêm vào trang web của mình.
nước hoa hồng

Có vẻ như nó vẫn yêu cầu Illuminate \ Support \ Collection. Nó không phải là một giải pháp PHP độc lập.
nước hoa hồng

Cảm ơn vì bạn đã phản hồi! Nó là một gói soạn nhạc . Tôi đã cập nhật readme với quy tắc sau: require __DIR__ . '/vendor/autoload.php';Điều duy nhất bạn phải làm là bao gồm tệp này. Điều này được tạo ra bởi nhà soạn nhạc!
ArjanSchouten

2

Tôi có một ý chính GitHub chứa các hàm PHP để thu nhỏ các tệp HTML, CSS và JS → https://gist.github.com/taufik-nurrohman/d7b310dea3b33e4732c0

Đây là cách để giảm thiểu đầu ra HTML một cách nhanh chóng với bộ đệm đầu ra:

<?php

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

ob_start('minify_html');

?>

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

<?php echo ob_get_clean(); ?>

liên kết chính dẫn đến một trang 404
1111161171159459134

2
Cập nhật các liên kết.
Taufik Nurrohman

1

Nếu bạn muốn xóa tất cả các dòng mới trong trang, hãy sử dụng mã nhanh này:

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

0

Cảm ơn Andrew . Đây là những gì đã làm để sử dụng điều này trong cakePHP:

  1. Tải xuống minify-2.1.7
  2. Giải nén tệp và sao chép thư mục con min vào thư mục Nhà cung cấp của bánh
  3. Tạo MinifyCodeHelper.php trong Chế độ xem / Trợ giúp của bánh như thế này:

    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. Đã bật Trình trợ giúp của tôi trong AppContoder

    công khai $ helpers = mảng ('Html', '...', 'MinifyCode');

5 ... Voila!

Kết luận của tôi: Nếu các mô đun khử và tiêu đề của apache bị vô hiệu hóa trong máy chủ của bạn, mức tăng của bạn là 21% kích thước nhỏ hơn và 0,35 giây cộng với yêu cầu nén (số này là trong trường hợp của tôi).

Nhưng nếu bạn đã kích hoạt các mô-đun của apache, phản hồi nén không có sự khác biệt đáng kể (1,3% đối với tôi) và thời gian để nén là samne (0,3 giây đối với tôi).

Vậy ... tại sao tôi lại làm vậy? 'couse tài liệu của dự án của tôi là tất cả trong các bình luận (php, css và js) và người dùng cuối cùng của tôi không cần phải thấy điều này;)


0

Bạn có thể sử dụng một công cụ khai thác Java được thử nghiệm tốt như HTMLCompressor bằng cách gọi nó bằng cách sử dụng passthru( exec).
Nhớ chuyển hướng bảng điều khiển bằng cách sử dụng2>&1

Điều này tuy nhiên có thể không hữu ích, nếu tốc độ là một mối quan tâm. Tôi sử dụng nó cho đầu ra php tĩnh

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.