استفاده از gzip برای افزایش سرعت سایت

سرعت لود شدن سایت برای وبمسترها از اهمیت ویژه ای برخورداره و با توجه به پایین بودن میانگین سرعت اینترنت در ایران این اهمیت مضاعف میشه.

یکی از راهکارهای افزایش سرعت لود شدن سایت استفاده از فشرده سازی gzip هست که میتونه 60 الی 80 درصد حجم صفحات رو کاهش بده. البته استفاده ناصحیح از gzip میتونه باعث بروز مشکلات و یا حتی کند شدن سایت بشه. چگونگی استفاده موثر از این راهکار موضوعیست که در ادامه این بحث به اون خواهیم پرداخت.

قبل از هر چیز از نصب بودن اکتنشن zlib روی php مطمئن بشید. این extension امکان استفاده از فشرده سازی gzip رو به php اضافه میکنه.

ساده ترین راه برای فشرده سازی صفحات سایت استفاده از گزینه ی output_compression هست. اکستنشن zlib این امکان رو به شما میده که با فعال کردن output_compression از طریق php.ini و یا .htaccess خروجی فایل های php خود رو فشرده کنید. برای مثال یک فایل .htaccess روی سرور خود می سازید و خط زیر رو درون این فایل ذخیره میکنید:

php_flag zlib.output_compression on

مزیت این روش اینه که بدون نیاز به تغییر در برنامه در صورتی که مرورگر از gzip پشتیبانی کنه خروجی تمام صفحات php فشرده میشه. ولی این روش اشکالاتی داره از جمله اینکه فقط خروجی فایلهای php شما فشرده میشه و فایلهای دیگه نظیر html و css و js فشرده نمیشه. و اشکال دیگه ای که داره اینه که عملیات فشرده سازی هر بار که یک صفحه صدا زده میشه، انجام میشه و امکان کش کردن خروجی سمت سرور وجود نداره و چنانچه سرور ضعیف و سایت پر بازدیدی داشته باشید مقدار قابل توجهی بار پردازشی روی سرور اعمال میکنه.

روش دوم استفاده از ob_gzhandler به عنوان output_handler هست که همون مزایا و معایب روش فوق رو داره. البته ob_gzhandler رو هم از طریق htaccess یا php.ini و هم به عنوان callback برای ob_start در برنامه میشه استفاده کرد.

نحوه استفاده از ob_gzhandler در فایل .htaccess :

php_flag output_buffering on
php_value output_handler ob_gzhandler

نحوه استفاده از ob_gzhandler به عنوان callback برای ob_start :

<?php
ob_start("ob_gzhandler"); // place this line of code at the start of your files
?>

در صورت استفاده از htaccess و یا php.ini در هر یک از دو روش فوق، توجه داشته باشید که نباید در برنامه خروجی با انکدینگ gzip ارسال نمایید در غیر این صورت محتوای صفحه دو بار انکد شده و فاتحه سایتتان خوانده می شود.

ضمنا همونطور که گفته شد از دو روش فوق فقط برای فشرده سازی خروجی فایلهای php میشه استفاده کرد و برای فشرده سازی فایلهای css و js و html باید خودمون دست به کار بشیم.

ابتدا از روش اولی که گفته شد برای فشرده سازی خروجی php استفاده میکنیم.
حالا برای فایلهای css و js و html باید کدی بنویسیم که نام یک فایل رو بگیره، محتوای فایل رو بخونه و به خروجی بفرسته. نیازی نیست ما فایل رو فشرده کنیم، بقیه کارها رو خود php انجام میده. برای این منظور فایلی به نام compressor.php در root سایت ایجاد می کنیم که نام فایلی که باید فشرده بشه رو از طریق GET دریافت کنه. ضمنا حتما باید پسوند فایل رو توی برناممون چک کنیم تا مشکل امنیتی پیش نیاد.

1
2
3
4
5
<?php
if (!preg_match('/\.(js|css|html|htm)$/i', $_GET['file'])) die('Access Denied');
if (!file_exists($_GET['file'])) die('File Not Found');
readfile($_GET['file']);
?>

حالا به نظر میرسه که این کد باید بدون مشکل کار کنه. اما در عمل ممکنه باعث بروز مشکلاتی از قبیل کاهش سرعت، افزایش مصرف پهنای باند و افزایش مصرف cpu هم بشه. و علتش هم اینه که بدون استفاده از این کد وقتی یک نفر از سایت شما دیدن میکنه تمام فایل های استاتیک در مرورگر کش شده و در مراجعات بعدی مادامی که تغییر نکرده باشند از کش خونده میشن. این در حالیست که با استفاده از این کد در واقع فایل های استاتیک شما به فایل های دینامیک تبدیل شده و هر بار از سرور لود میشن.

برای رفع این مشکل باید کدی بنویسیم که تاریخ آخرین تغییرات فایل رو هم به مرورگر بفرسته در این صورت دفعات بعد که مرورگر فایل رو از سرور درخواست کنه تاریخ آخرین نسخه موجود در کشِ خودش رو هم به سرور میفرسته و ما میتونیم این تاریخ رو با تاریخ فایل مقایسه کنیم و در صورت یکسان بودن به مرورگر بگیم که از همان نسخه موجود در کش استفاده کند.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if (!preg_match('/\.(js|css|html|htm)$/i', $_GET['file'])) die('Access Denied');
if (!file_exists($_GET['file'])) die('File Not Found');
 
$mtimestr = gmdate("D, d M Y H:i:s", filemtime($_GET['file'])) . " GMT";
if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $mtimestr) {
header('HTTP/1.1 304 Not Modified');
die();
}
 
header("Last-Modified: " . $mtimestr);
header("Cache-Control: must-revalidate", false);
readfile($_GET['file']);
?>

در نهایت برای اینکه از بار پردازشی سرور کم کنیم میتونیم از کش سمت سرور هم استفاده کنیم. یعنی فایل های فشرده شده رو روی سرور ذخیره کنیم و مادامی که فایل تغییر نکرده از کش استفاده کنیم. البته این کار پیچیدگی های خاص خودش رو داره. چون در این صورت باید فایل رو خودمون فشرده کنیم و فشرده سازی خودکار رو غیر فعال کنیم. که در این صورت باید قبل از gzip کردن بررسی کنیم که آیا مرورگر از gzip پشتیبانی میکنه یا نه. شاید فکر کنید که این کار لزومی نداشته باشه، چون تقریبا اکثر مرورگر ها از gzip پشتیبانی میکنند، ولی اینطور نیست. به عنوان مثال IE به صورت پیش فرض در صورت استفاده از proxy از HTTP 1.0 استفاده میکنه و gzip رو پشتیبانی نمیکنه.

و البته یک راه دیگه هم برای فشرده تر کردن فایل های js و css وجود داره و اون حذف کامنت ها و فاصله های اضافی از درون کد هست.

در رابطه با این دو مورد آخر برای مشاهده نمونه کد میتونید به سورس jsmart compressor مراجعه کنید.

خوب حالا برنامه ما آماده هست، باید تمام لینک هایی که در سایت به فایل های css و js و html هست رو تغییر بدیم و به جاش لینکی به فایل compressor.php قرار بدیم که نام فایل مورد نظر هم به صورت پارامتر بهش پاس شده باشه. کاره طاقت فرسایی هست و شاید غیر ممکن.

برای اینکه نیاز به تغییر در کدهای فعلی سایتتون نداشته باشید از ماژول mod_rewrite آپاچی کمک می گیریم. یعنی با استفاده از یک rewrite rule تمام request هایی که به فایل های css و js و html ارسال میشه رو به فایل compressor.php می فرستیم.
با این حساب محتوای فایل .htaccess یه چیزی شبیه به این میشه :

1
2
3
4
5
6
php_flag zlib.output_compression on
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*\.(js|css|htm|html))$ compressor.php/?file=$1
</IfModule>

البته برای اینکه این rule با rule های دیگه ای که در برنامه ها برای تبدیل لینک های php به html استفاده میشه تداخل پیدا نکنه یک condition هم بهش اضافه کردیم تا فقط درمورد فایل هایی که وجود خارجی دارند این rule عمل کنه.

تموم شد.
امیدوارم مفید بوده باشه :)

برچسب‌ها: ,

17 دیدگاه برای “استفاده از gzip برای افزایش سرعت سایت”

  1. moryabdi گفته:

    مطالبت حرفه ای و عالیه… موفق باشی دوست عزیز

  2. فرهادی گفته:

    ممنون، لطف داری

  3. مانی گفته:

    ایده جالبی بود آقای فرهادی … الان مشکل بزرگی که سایت های بزرگ باهاش سر و کار دارند بیشتر لود سرور هست تا پهنای باند. اگر یک مقاله تکمیلی در مورد کش کردن هم اضافه کنید به این سری خیلی خوب می شه. در ضمن اگر دوست داشتید حتما این مقاله رو به iranphp.net ثبت کنید.

  4. مهدی کمری گفته:

    ممنونم . خیلی جالب بود .

  5. saeed گفته:

    با فایلهای css مشکل دارد باید فایل compressor.php را به شکل زیر اصلاح کرد .

  6. نبی گفته:

    سلام،

    1- مقاله فوق العاده جالبی بود، خیلی دنبال یه مقاله در مورد gzip میگشتم.

    2- در صورت استفاده از smarty کدوم بخش مقاله مهمه و باید کار خاصی انجام داد؟

    3- من دیدم بعضیها برای کلاس کاری که مثلاً بگن سایت ما داینامیک است، پسوند فایلهای html خود رو php میزارند. من فکر میکنم اینکار اشتباست و باعث میشه صفحات استاتیک که براحتی در مرورگر میتونن کش بشن، کش نشن و البته بار اضافه هم به سرور تحمیل بشه. نظر شما چیست؟

    4- طاغت رو هم اشتباه نوشتی ;) (طاقت)

    بازم ممنون

  7. محمد مهدوی کیا گفته:

    خوب بود
    منم برنامه نویس پی اچ پی هستم . ازاونایی که با چنگ و دندون چیزایی یاد گرفتن. به هر حال امیدوارم موفق باشی.

  8. علی گفته:

    سلام آقا نبی،

    1- لطف داری
    2- فرقی نمی کنه
    3- موافقم. به جای این کار میتونن با mod_rewrite آدرس های php رو به html ریدایرکت کنند.
    4- اصلاح کردم. ممنون.

  9. بهروز پولادرگ گفته:

    واقعا عالی بود ممنون

  10. unk گفته:

    well done
    thanks so much

  11. نون گفته:

    فوق العاده جالب بود… فوق العاده استفاده کردم از مطالب این پست و پست های جاوااسکریپت

  12. علی گفته:

    مطلب جالبی بود استفاده کردم ازش

  13. ناصر گفته:

    باید به شما برای برنامه نویسی SmartOptimizer v1.7 beta احسنت گفت. کار فوق العاده ای کردید.
    امیدوارم در ویرایش های بعدی فشرده سازی خروجی php را هم در نظر بگیرید.

  14. افشین مهربانی گفته:

    عالی بود. ممنون

  15. مهربان گفته:

    مطلب بسییار خوب ومفیدی بود متشکرم .

  16. hh گفته:

    اسکریپت زیر هم می تونه در افزایش سرعت لود شدن سایت بسیار موثر باشه .
    جهت کست اطلاعات بیشتر به لینک زیر مراجعه کنید:
    http://irank.ir/انجمن-ها/اسکریپت/سایتی-با-سرعت-نور-داشته-باشید

  17. امیر عظمتی گفته:

    سلام. ممنون از مقاله بسیار عالی تون. همونطور که سعید در این کامنت گفته: http://farhadi.ir/blog/1386/07/03/speed-up-your-site-using-gzip/#comment-3402
    با فایل های سی اس اس مشکل داره. یعنی انگار که فایل سی اس اس لود نمیشه. کاری میشه کرد؟

دیدگاهی بنویسید