راهکارهایی برای بهینه سازی سایت
برای سایت های پر بازدید، بهینه بودن سایت از اهمیت زیادی برخورداره. بهینه بودن یعنی اینکه سایت در کمترین زمان ممکن لود بشه و مصرف منابع سرور هم به حداقل ممکن برسه.
میشه فرایند بهینه سازی رو به دو بخش سمت کاربر و سمت سرور تقسیم کرد.
بهینه سازی سمت سرور یعنی بهینه کردن برنامه و کد های سمت سرور برای اینکه حداقل منابع رو مصرف کنه و در حداقل زمان ممکن اجرا بشه. که این قسمت از بهینه سازی فعلا موضوع بحث ما نیست.
و اما بهینه سازی سمت کاربر شامل کلیه اقداماتی است که برای کاهش مصرف پهنای باند وافزایش سرعت لود شدن انجام میشه.
در ادامه این مقاله که در واقع برگرفته از کتاب «High Performance Web Sites» هست می پردازیم به اهمیت و راهکارهای بهینه سازی سمت کاربر.
لازم به ذکر است که این کتاب نوشتهی Steve Souders مسئول performance در یاهو می باشد.
اهمیت بهینه سازی سمت کاربر
از ملاک های اصلی جلب رضایت کاربران، کارایی و سرعت سایت است. بررسی ها نشان داده که کمتر از 20 درصد از زمان بارگزاری سایت صرف لود شدن html میشود و مابقی یعنی بیش از 80 درصد از زمان، صرف بارگزاری آنچه درون صفحه است میشود. که توجه به بهینه سازی این قسمت (ملحقات صفحه) تا حدود زیادی سرعت و کارایی سایت را افزایش میدهد.
سه دلیل عمده برای اهمیت بهینه سازی ملحقات صفحه وجود دارد:
- پتانسیل بیشتری برای بهینه سازی ملحقات وجود دارد. کاهش پنجاه درصدی آن حدود 40 درصد در افزایش سرعت سایت تاثیر دارد درحالی که کاهش 50 درصدی حجم html تاثیرش کمتر از ده درصد است.
- بهینه سازی ملحقات صفحه، زمان و منابع کمتری نیاز دارد نسبت به بهینه سازی سمت سرور (شامل تغییر معماری و کدنویسی مجدد، یافتن و رفع مشکلات و گلوگاه ها در کد، اصلاحات سخت افزاری و قرار دادن دیتابیس ها بر روی سرور های مجزا و … )
- در عمل ثابت شده که این روش خوب جواب می دهد. بیش از 50 تیم در یاهو به این روش توانستند حدود 25 درصد سرعت سایت ها را افزایش دهند.
و اما راهکارها:
- کاهش تعداد درخواست های HTTP
- استفاده از تکنیک CSS Sprites که موجب کاهش تعداد تصاویر استفاده شده در css میشود.
- الحاق فایلهای css به یکدیگر و همچنین اسکریپت ها
- استفاده از تکنیک inline image (البته این تکنیک در IE پشتیبانی نمیشود)
- استفاده از CDN
یک CDN مجموعه ای از وبسرورهاست که در نقاط مختلف دنیا توزیع شده اند و معمولا محتوای static رو میزبانی میکنند. تا بازدید کنندهها بتوانند از نزدیکترین سرور فایل ها را دریافت کنند. این تکنیک برای سایت های کوچک مقرون به صرفه نیست. - افزودن Expires Header
مرورگرها میتوانند پاسخ درخواست های HTTP را کش کنند. با ارسال هدر Expires میتوان به مرورگر گفت که پاسخ را تا چه زمانی کش کند. برای مثال برای محتوای استاتیک میتوان این مقدار را بر روی یکسال گذاشت تا در درخواست های بعدی مرورگر از کش استفاده نماید. - استفاده از gzip
تقریبا اکثر مرورگرها از gzip پشتیبانی میکنند. فشرده سازی gzip بر روی محتوای متنی نظیر css ها و اسکریپت ها و html کارایی خوبی دارد و بیش از 50 درصد حجم درخواست ها را کاهش میدهد. - stylesheet ها را در ابتدای صفحه قرار دهید.
در بعضی مرورگرها درصورتی که stylesheet در انتهای صفحه باشه باعث میشه که محتوای صفحه دوبار رندر بشه و زمان بیشتری صرف بشه و ضمنا دفعه اول بدون style رندر میشه که ظاهر خوشایندی نداره. در بعضی مرورگرها هم موجب میشه رندر بعد از لود شدن محتوا و ملحقات صفحه انجام بشه که باعث میشه ابتدا یک صفحه خالی نمایش داده بشه و رندر با کمی تاخیر انجام بشه.
ضمنا قرار دادن stylesheet ها در ابتدای صفحه موجب میشه رندر به شکل مطلوبی و به صورت تدریجی همزمان با لود شدن محتوا انجام بشه. - اسکریپتها را در انتهای صفحه قرار دهید.
قرار دادن اسکریپتها در ابتدای صفحه باعث میشه جلوی رندر شدن و دانلود شدن سایر محتویات صفحه تا اتمام لود شدن اسکریپت گرفته بشه.
و اما قرار دادن اسکریپتها در انتهای صفحه باعث میشه ابتدا محتوا رندر بشه و سپس سایر ملحقات و اسکریپت ها در پس زمینه لود بشه. - از CSS Expression ها پرهیز کنید
CSS Expression ها فقط در IE پشتیبانی میشوند. با استفاده از این قابلیت میتوان برای مقدار دادن به یک خصوصیت در CSS از جاوااسکریپت استفاده کرد. و این کد اسکریپت در مواقعی نظیر resize شدن صفحه و یا حرکت موس مجددا مقدار رو محاسبه میکنه. این اجرای مکرر میتونه باعث کاهش کیفیت و یا حتی هنگ شدن مرورگر بشه. پس بهتره از این CSS Expression ها استفاده نکنید. - جاوااسکریپت ها و CSS ها را از HTML جدا کنید
گرچه اینکار قاعده شماره 1 رو نقض میکنه ولی با توجه به اینکه با جدا کردن CSS و JS ها و ذخیره اونها در فایلهای استاتیک میشه قواعد 2 و 3 و 4 رو در موردشون بکار بست پس این کار به صرفه است. - تعداد DNS Lookup ها را کم کنید
مرورگرها برای ارتباط با سرورها از IP اونها استفاده میکنند بنابراین مجبورند به ازای هر Hostname ابتدا یک درخواست به DNS سرور ارسال کنند و IP رو بدست بیارند. ضمن اینکه مرورگر میتونه از قابلیت Keep-Alive در مورد درخواستهایی که مربوط به یک Hostname هستند استفاده کنه که باعث میشه چندین درخواست از طریق یک کانکشن انجام بشه.
پس بهتره محتویات سایتتون از Hostname های مختلف نباشه. (دقت کنید که www.example.com و example.com هم دو Hostname متفاوت هستند) - جاوا اسکریپت ها را بچلانید
چلاندن(Minify) یعنی حذف اضافات (شامل کامنتها، فضاها و اینترهای اضافی) از درون اسکریپتها برای کاهش حجم فایل. البته یک گام فراتر هم میشه رفت با استفاده از پیچوندن (Obfuscation) که در این روش علاوه بر حذف اضافات، شناسههای استفاده شده در کد رو هم با شناسههای کوتاهتر جایگزین میکنند.
روش چلاندن رو در مورد CSS هم میشه به کار برد ولی تاثیرش در مورد CSS ها کمتره. البته در مورد CSS میشه با بهینه کردن کد تا حدی از حجم CSS کم کرد. (در این مورد آقایان الوانی و ستاری به طور مفصل توضیح دادند.) - از Redirect کردن پرهیز کنید
هر Redirect مستلزم یک درخواست اضافه است و ضمنا این درخواست به صورت موازی هم نیست یعنی تا کامل نشده درخواستهای بعدی ارسال نمیشوند. پس تا جائیکه ممکنه از Redirect پرهیز کنید. - اسکریپتهای تکراری را حذف کنید
گاهی ممکنه پیش بیاد که یک اسکریپت دو بار در صفحه درج شده باشه مثلا توی کار تیمی ممکنه یک نفر یک اسکریپت رو در یک جای صفحه درج کنه و یک نفر دیگه که از این موضوع خبر نداره مجدد اون رو در جای دیگه ای درج کنه.
این کار دو تا مشکل ایجاد میکنه. یکی اینکه تعداد درخواستهای HTTP افزایش پیدا میکنه و دو اینکه زمان اضافه ای صرف اجرای مجدد اون اسکریپت میشه. البته مورد اول فقط در IE و اون هم در حالتی که اسکریپت قابل کش شدن نباشه اتفاق میافته. - پیکربندی ETag ها
مرورگرها از هدر ETag برای کش کردن محتوای استاتیک تا زمانی که تغییر نکرده استفاده میکنند (مشابه هدر Last-Modified). ولی ETag در صورتی که سایت بر روی بیش از یک سرور میزبانی شده باشد میتواند مشکل ساز شود. مثلا آپاچی به طور پیشفرض برای تولید ETag از «inode – حجم – زمان ویرایش» استفاده میکنه و inode در مورد یک فایل روی سرورهای مختلف فرق میکنه و در صورتی که مرورگر یک فایل رو از یک سرور دریافت کنه و در مراجعه بعدی به اون فایل برای چک کردن تغییرات از سرور دیگری استفاده کنه، با توجه به اختلاف ETag ها، سرور مجددا فایل رو میفرسته که باعث میشه مرورگر از کش استفاده نکنه. IIS هم مشکل مشابهی داره.
اما راهکار اینه که یا کلا ETag رو حذف کنید و یا اینکه اصلاحش کنید برای مثال در آپاچی باید inode رو از ETag حذف کنید. (این کار رو با htaccess میشه انجام داد.) - Ajax را قابل کش شدن کنید
یک برنامهی وب دویی را در نظر بگیرید که مثلا برای لود کردن لیست ایمیلها از Ajax استفاده میکند. در این حالت میتوان تا زمانی که لیست آدرس ها تغییر نکرده این درخواست را با استفاده از هدر Expires قابل کش کرد.
ضمنا قواعد 4، 9، 10، 11 و 13 هم در مورد درخواستهای اجکسی قابل استفاده هستند.
اینها مواردی بود که در کتاب ذکر شده بودند. بعدها موارد دیگه ای هم به اینها اضافه شد و الان تعدادش به 34 مورد رسیده که میتونید اینجا ببینید.
یاهو یک پلاگین برای فایرفاکس برای چک کردن این فاکتورها نوشته به نام YSlow که البته با Firebug کار میکنه.
این پلاگین بر اساس این فاکتورها کیفیت سایت شما رو چک میکنه و مواردی که رعایت نشدند رو مشخص میکنه و یک نمره هم از 100 به سایت شما میده.
ابزارهای مختلفی وجود داره که پیاده سازی این موارد رو ساده میکنه.
مثلا برای چلاندن جاوااسکریپتها (مورد 10) میتونید از ابزارهایی مثل JSMin و Packer و YUI Compressor استفاده کنید.
ابزارهایی هم هستند که با نصب اونها روی سایت به صورت خودکار بعضی از این موارد روی سایت شما اعمال میشوند. مثل Minify و PHPSpeedy و SmartOptimizer.
برای مثال SmartOptimizer میتونه موارد 1 و 3 و 4 و 10 و 13 رو روی سایت شما اعمال کنه و نمره YSlow شما رو حدود 10-20 واحد افزایش بده.
برچسبها: Optimization, performance, YSlow
7 دی 1387 در 12:47 ق.ظ
علی جان کامل بود، فقط شماره ۱۴ یه مقدار تیک میزنه. دلیلش هم این که شما نمیدونی ۳۰ دقیقهی دیگه یا ۵ ساعت دیگه ایمل دریافت میشه که بخواین با expires اونو cache کنین.
7 دی 1387 در 9:32 ق.ظ
@ بهروز:
برای این مورد باید زمان آخرین تغییرات لیست رو به صورت پارامتر GET در URL اجکسی قرار بدیم تا هر موقع لیست تغییری میکنه یک URL جدید ایجاد بشه و هدر Expires هم میتونه روی یکسال تنظیم بشه و مشکلی پیش نمیاد.
در ضمن منظورم از لیست ایمیل ها address book بود.
7 دی 1387 در 3:14 ب.ظ
علی جان پس در این صورت شما یک بار یه request به سرور میفرستی که بهت بگه item جدیدی هست یا نه (یا همون تاریخ تغییرات) بعدش با یه request دیگه اون ها رو از همون آدرسی که expire براش set کرده بودی fetch میکنی!
خوب همهی این ها میتونه با یک request انجام بشه از طرفی چون request های کمتری به سرور ارسال میشه performance بهتری میده و حتی با دردسر کمتری میشه اون رو نوشت.
حتی gmail هم این کار رو میکنه و یه request جدید میفرسته به سرور پس این مورد ۱۴ در مورد web application ها نمیتونه درست باشه!
7 دی 1387 در 4:16 ب.ظ
@بهروز:
کش کردن درخواستهای اجکسی همه جا قابل استفاده نیست. ولی در مواردی نظیر autocomplete برای آدرسهای ایمیل قابل استفاده است. به این صورت که ما تاریخ آخرین تغییرات رو همزمان با لود شدن اولیه صفحه لود میکنیم (نه با یک درخواست جداگانه) و دیگر نیازی به چک کردن مجدد نیست و در مراجعات بعدی در صورتی که لیست هنوز تغییر نکرده باشد از همان لیست موجود در کش استفاده میشود.
یک نگاهی هم به اصل مطلب بنداز (شاید من بد ترجمه کردم).
ضمنا توی کتاب قسمت Rule 14 مفصل توضیح داده و دو تا مثال واقعی هم از Yahoo Mail و Google Doc آورده.
8 دی 1387 در 2:07 ب.ظ
نه علی جان مشکل سر این بود که داشتیم در مورد ۲تا مورد متفاوت صحبت میکردیم. شما منظورتون مواردی بود که توسط کاربر ویرایش میشن که خوب میشه از اون راه حلی که گفتین استفاده کرد اما من داشتم در مورد مواردی صحبت میکردم که کاربر هیچ نقشی در اون ها نداره و رسما به یه عامل بیرونی (بیرون از نرمافزار ما) مربوط میشه.
9 دی 1387 در 10:13 ب.ظ
بابت تقویم جلالی DHTML که رو سایتتون گذاشتین ممنونم .
وبلاگ خوبی هم دارید .
بازم سر می زنم .
موفق باشید
19 دی 1387 در 1:22 ب.ظ
چی بحث میکنید. نگرفتید قضیه چی شد دیگه. آقا علی تمام اینها رو نوشت که فقط به خط آخر برسه و SmartOptimizer رو معرفی کنه
من که میدونم :p
ولی دستت درد نکنه نکات ظریفی بودند. استفاده بردیم.
24 دی 1387 در 6:35 ب.ظ
@نبی:
خوشم میاد که تیزی. زود مطلب رو میگیری
16 بهمن 1387 در 4:45 ب.ظ
فقط یه سوال این برنامه ی smartOptimizer یه پلاگین برای وردپرسه یا اینکه روی هر سی ام اسی می شه نصبش کرد؟
28 بهمن 1387 در 10:53 ق.ظ
@حسین:
نه، روی هر سایتی قابل نصبه.
11 اسفند 1387 در 8:57 ق.ظ
بسیار عالی بود.
10 مرداد 1388 در 9:15 ب.ظ
بسیار مفید و لازم برای توجه. متشکر.
7 بهمن 1388 در 1:26 ب.ظ
سلام
من خیلی دنبال این کتاب گشتم لطف می کنید اگر دارید برام ایمیلش کنید و یا URL بدید دانلود کنم.
volghan@gmail.com
13 خرداد 1389 در 12:11 ق.ظ
مثل همیشه عالی بود…تشکر بسیار زیاد علی جان.
24 مرداد 1389 در 12:27 ب.ظ
سلام خسته نباشید.مطالب خوبیه
22 مهر 1389 در 8:27 ق.ظ
مرسی خیلی مفید و کاربردین
21 اردیبهشت 1390 در 11:59 ق.ظ
اگر این اسمارت اپتیمایزر رو به بک ماژول دروپال هم تبدیل میکردید خیلی عالی میشد .
23 اردیبهشت 1390 در 8:39 ب.ظ
سلام آقای فرهادی ممنون بابت مطالب خوبتون می شه اموزش نصب SmartOptimizer برای من ایمیل کنید.خیلی بهش نیاز دارم
منتظر پاسختون هستم
27 شهریور 1390 در 11:52 ق.ظ
بسیار عالی. من به مباحث بهینه سازی خیلی علاقه دارم. اگر به بلاگم هم سر بزنید در این مورد مقاله زیاد نوشتم. بازم مرسی
9 آبان 1390 در 10:04 ق.ظ
سلام علی جان .. خدارو شکر چند تا ایرانی با هوش هم پیدا شد، وبلاگت خیلی خوب بود .. میخواستم بدونم چطوری میشه خارج از اینجا باهات ارتباط برقرار کرد.