- Hikaru {Aka} Yuuki のブログ - http://www.hikaruyuuki.com -

Mengkompress Manual Javascript dan CSS dengan PHP GZip di .htaccess

This post is also available in: English [1]

Suatu halaman web akan di-render dimana yang dimuat pertama kali adalah file HTML-nya, kemudian CSS-nya dan yang terakhir file Javascript (JS) –best practice-nya, file CSS di bagian header sedangkan file JS di bagian footer. Apabila halaman tersebut merupakan halaman interaktif dimana file HTML, CSS, dan JS ukurannya akan semakin membesar, maka suatu halaman akan semakin lama dimuat. Oleh karena itu, kompresi static content seperti plain-text (seperti HTML, CSS, JS) sangat dibutuhkan. Hal ini diperuntukkan untuk mengurangi waktu loading halaman web. Kompresi terbaik yang digunakan melalui sisi server adalah GZIP, DEFLATE. Namun, ada kalanya module ini tidak diload pada beberapa hostingan –seperti yang saya alami, sudah beberapa kali memberitahu pihak hostingan Capoeng, namun tak ada tanggapan :sigh:–

Untuk mengetahui apakah suatu halaman/file tersebut dikompres, kita dapat menggunakan online GZIP Test seperti GIDZipTest [2], atau manual melalui YSlow atau melalui Firebug (lihat Header Info, bagian Content-encoding).

Beberapa kali saya mencoba banyak konfigurasi .htaccess untuk kompresi GZip di web saya, dari berbagai web lain. Namun, sepertinya kompresi Apache GZip (mod_gzip) tidak didukung oleh server Apache. Ngoprek bagaimanapun juga sepertinya gagal. Content-encoding dari file-file plain-text tidak seperti yang diinginkan (“gzip” atau “deflate”).

Namun akhirnya bisa menemukan cara, secara tidak sengaja melihat header info dari file di WordPress Admin lewat YSlow dan memanfaatkan ini.

Beberapa konfigurasi yang gagal saya coba (dari yang sederhana pun), antara lain:

SetOutputFilter DEFLATE

atau

AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml application/x-javascript text/javascript application/javascript

atau

mod_gzip_on       Yes
mod_gzip_dechunk  Yes
mod_gzip_item_include file      \.(html?|txt|css|js|php|pl|jpg|png|gif)$
mod_gzip_item_include handler   ^cgi-script$
mod_gzip_item_include mime      ^text/.*
mod_gzip_item_include mime      ^application/x-javascript.*
mod_gzip_item_exclude mime      ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*

atau

php_value output_handler ob_gzhandler
php_flag zlib.output_compression On
php_value zlib.output_compression_level 6

atau seperti di:

GZip files with .htaccess and PHP @ lateralcode.com [3]

How To Optimize Your Site With GZIP Compression [4]

Akhirnya supaya bisa mengkompres saya menggunakan DEFLATE dimana semua file JS dan CSS di-redirect terlebih dahulu ke file GZip.php. Kelemahan dari metode ini adalah kemungkinan time-consuming, karena file-file tersebut harus di-redirect dan dikompres on-the-fly.

di file .htaccess

RewriteEngine on
RewriteRule ^(.*\.(js|css))$ /gzip.php?file=$1

buat file gzip.php

<?php
/*if(isset($_SERVER['HTTP_ACCEPT_ENCODING']) && substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'))
ob_start('ob_gzhandler');
else
ob_start();
*/

function get_file($path) {
 if ( function_exists('realpath') )
 $path = realpath($path);

 if ( ! $path || ! @is_file($path) )
 return '';

 return @file_get_contents($path);
}

$compress = true; //( isset($_GET['c']) && $_GET['c'] );
$force_gzip = false; //( $compress && 'gzip' == $_GET['c'] );

$out = '';
$out .= get_file($_GET['file']) . "\n";

if ( $compress && ! ini_get('zlib.output_compression') && 'ob_gzhandler' != ini_get('output_handler') ) {
 $fileName = $_GET['file'];
 $ext = strtolower(substr($fileName, strrpos($fileName, '.') + 1));

 if ($ext=='css')
 header('Content-type: text/css');
 else if ($ext=='js')
 header('Content-type: application/x-javascript');

 header('Vary: Accept-Encoding'); // Handle proxies
 if ( false !== strpos( strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), 'deflate') && function_exists('gzdeflate') && ! $force_gzip ) {
 header('Content-Encoding: deflate');
 $out = gzdeflate( $out, 3 );
 } elseif ( false !== strpos( strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), 'gzip') && function_exists('gzencode') ) {
 header('Content-Encoding: gzip');
 $out = gzencode( $out, 3 );
 }
}

echo $out;
exit;

?>