وردپرس و ووکامرس
افزایش سرعت ووکامرس با پیدا کردن علت کندی فروشگاه
برای افزایش سرعت ووکامرس اول با curl و Query Monitor ببینید زمان در سرور، دیتابیس، افزونه ها یا سرویس های بیرونی مثل درگاه و پیامک هدر می رود و بعد همان بخش را درست کنید. سبد خرید و صفحه پرداخت کش نمی شوند، پس افزونه کش به تنهایی کندی آن ها را برطرف نمی کند.
صفحه محصولی که چهار ثانیه طول می کشد تا باز شود، ممکن است منتظر جواب سرور پیامک مانده باشد یا از جدولی بخواند که سال ها پاک نشده است. افزونه کش روی این دو مشکل یک اثر ندارد. گاهی کندی را برای بازدیدکننده مهمان پنهان می کند و خریدار موقع پرداخت باز همان کندی را می بیند.
به همین دلیل کار افزایش سرعت ووکامرس را با اندازه گیری شروع کنید و بعد از هر تغییر دوباره عدد بگیرید تا معلوم شود کدام تنظیم اثر داشته است.
اندازه گیری قبل از افزایش سرعت ووکامرس
سه نوع صفحه را جدا تست کنید: یک دسته بندی، یک محصول و سبد خرید. دسته بندی و محصول معمولا کش می شوند ولی سبد خرید کش نمی شود، پس زمان سبد خرید نشان می دهد PHP و دیتابیس بدون کمک کش چقدر سریع اند.
داده میدانی و داده آزمایشگاهی در PageSpeed Insights
بخش بالای PageSpeed Insights داده میدانی است. این داده از گزارش CrUX کروم می آید و تجربه کاربران واقعی در ۲۸ روز گذشته را خلاصه می کند. بخش پایین داده آزمایشگاهی Lighthouse است که صفحه را یک بار روی دستگاه و شبکه ای شبیه سازی شده باز می کند.
برای تصمیم گیری به داده میدانی تکیه کنید. گوگل صدک ۷۵ بازدیدها را ملاک می گیرد و در Core Web Vitals این مقدارها خوب حساب می شوند: LCP (نمایش بزرگ ترین بخش صفحه) تا ۲٫۵ ثانیه، INP (پاسخ صفحه به کلیک و لمس) تا ۲۰۰ میلی ثانیه و CLS (جابه جایی چیدمان) تا ۰٫۱.
اگر صفحه بازدید کافی از کاربران کروم نداشته باشد، PSI داده کل دامنه را نشان می دهد و اگر آن هم کافی نباشد، این بخش خالی می ماند. آن وقت از داده آزمایشگاهی فقط برای پیدا کردن مشکل استفاده کنید. Lighthouse در PSI صفحه را فقط بار می کند و با آن کار نمی کند، برای همین INP ندارد و Total Blocking Time را گزارش می دهد.
TTFB را با curl بگیرید
TTFB فاصله بین فرستادن درخواست و رسیدن اولین بایت پاسخ است. این شاخص جزو Core Web Vitals نیست، ولی web.dev مقدار ۰٫۸ ثانیه یا کمتر را به عنوان راهنما خوب می داند. TTFB به سرور، کش و کد PHP بستگی دارد و حجم عکس ها رویش اثری ندارد. آدرس ها را با آدرس فروشگاه خودتان عوض کنید:
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s total: %{time_total}s\n" https://example.com/product/sample/
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s total: %{time_total}s\n" https://example.com/cart/
curl -sI https://example.com/product/sample/ | grep -i x-litespeed-cache
در cmd ویندوز به جای curl بنویسید curl.exe، به جای /dev/null بنویسید NUL و در دستور سوم به جای grep -i از findstr /i استفاده کنید.
هر دستور را چند بار اجرا کنید. اگر صفحه محصول در اجرای دوم خیلی سریع تر شد و هدر x-litespeed-cache مقدار hit داشت، کش صفحه کار می کند. سبد خریدی که دو یا سه ثانیه طول می کشد یعنی کندی در PHP و دیتابیس است و خریدار موقع افزودن به سبد و پرداخت همین زمان را منتظر می ماند. اگر سرور خارج از ایران است، دستور را یک بار از سیستم خودتان و یک بار از SSH هاست بگیرید. اختلاف دو عدد تقریبا سهم مسیر شبکه است.
Query Monitor برای پیدا کردن افزونه و کوئری کند
Query Monitor افزونه رایگان عیب یابی وردپرس است و خروجی اش به طور پیش فرض فقط به مدیر سایت نشان داده می شود. نصبش کنید، سبد خرید را باز کنید و از نوار بالای صفحه این پنل ها را ببینید:
- Queries by Component زمان کوئری ها را به تفکیک افزونه و قالب جمع می زند. افزونه ای که بیشترین سهم را دارد اولین مظنون است.
- Database Queries کوئری های کند و تکراری را جدا می کند. کوئری تکراری معمولا از افزونه ای است که برای هر محصول داخل حلقه جداگانه سراغ دیتابیس می رود.
- HTTP API Calls درخواست هایی را نشان می دهد که خود سرور هنگام ساختن صفحه به سرویس های بیرونی فرستاده، مثل بررسی لایسنس قالب یا API پیامک.
- پنل های Scripts و Styles فایل های JS و CSS بارشده روی همان صفحه را فهرست می کنند.
گزارش وضعیت ووکامرس و Site Health
در WooCommerce > Status نسخه PHP و WP Memory Limit را یادداشت کنید و در بخش Database حجم جدول ها را ببینید. اگر wp_actionscheduler_actions یا wp_woocommerce_sessions از جدول های اصلی مثل wp_posts بزرگ تر شده، پاک سازی دیتابیس را جلو بیندازید. در Tools > Site Health هم از وردپرس ۶٫۶ به بعد، وقتی مجموع گزینه های autoload از ۸۰۰ کیلوبایت بیشتر شود، هشدار Autoloaded options could affect performance ظاهر می شود.
نشانه ها و علت های رایج کندی ووکامرس
کندی ووکامرس معمولا از کش نشدن صفحه ها، کوئری های سنگین روی سبد و پرداخت، درخواست cart fragments، عقب افتادن WP-Cron یا انتظار برای سرویس های بیرونی مثل درگاه و پیامک است. از روی نشانه ها می شود حدس زد از کجا شروع کنید:
| نشانه | علت احتمالی | چه چیزی را بررسی کنید |
|---|---|---|
| همه صفحه ها کندند، حتی صفحه های ساده | کش صفحه کار نمی کند یا PHP قدیمی است | هدر x-litespeed-cache، نسخه PHP و OPcache |
| صفحه محصول سریع است ولی سبد خرید و پرداخت کندند | کوئری سنگین یا افزونه هایی که روی سبد و پرداخت اجرا می شوند | Query Monitor روی سبد خرید |
| در کمپین یا ساعت شلوغ خطای 508 نمایش داده می شود | سقف پردازش هم زمان حساب (Entry Processes) پر شده | بخش Resource Usage در cPanel |
| پیشخوان و فهرست سفارش ها کند باز می شود | سفارش ها هنوز در wp_posts هستند یا گزینه های autoload حجیم اند | وضعیت HPOS و هشدار Site Health |
روی هر صفحه درخواست wc-ajax=get_refreshed_fragments دیده می شود | اسکریپت cart fragments | تب Network مرورگر و سبد کشویی قالب |
| صفحه چند ثانیه سفید می ماند و بعد یکباره باز می شود | فایل یا اسکریپت خارجی که جواب نمی دهد | تب Network و پنل HTTP API Calls |
| بعد از پرداخت، برگشت به سایت طول می کشد | ارسال پیامک یا تایید تراکنش در همان درخواست | یک سفارش آزمایشی روی نسخه تست |
| کارهای زمان بندی شده عقب می افتند و صف Pending بزرگ است | WP-Cron فقط با بازدید اجرا می شود | Scheduled Actions و کرون سرور |
وقتی مشکل از سرور و تنظیمات هاست است
اگر TTFB سبد خرید روی نسخه آزمایشی و با افزونه های کمتر هم بالا ماند، سراغ نسخه PHP، کش صفحه و کش اشیا و سقف منابع حساب بروید.
نسخه PHP و OPcache
وردپرس الان PHP 8.3 یا بالاتر را پیشنهاد می کند. در cPanel نسخه را از MultiPHP Manager عوض می کنید و در هاست های کلودلینوکس از Select PHP Version. قبلش درگاه پرداخت و افزونه های قدیمی را روی یک کپی آزمایشی امتحان کنید، چون افزونه ای که سال ها آپدیت نشده ممکن است روی PHP جدید خطا بدهد. در همان Select PHP Version ببینید افزونه opcache فعال باشد. OPcache کد کامپایل شده PHP را در حافظه نگه می دارد تا فایل ها در هر درخواست از اول پردازش نشوند.
کش صفحه با LiteSpeed Cache
روی هاست لایت اسپید، افزونه LiteSpeed Cache کش صفحه را به خود وب سرور می سپارد. طبق مستندات LSCache برای وردپرس، سبد خرید، تسویه حساب و حساب کاربری به طور پیش فرض کش نمی شوند و برای ووکامرس روشن کردن ESI توصیه شده است. تنظیم قدم به قدم افزونه، استثنای صفحه پرداختی که با صفحه ساز ساخته اید و تفاوت عملی لایت اسپید با آپاچی در راهنمای LiteSpeed Cache و مقایسه لایت اسپید با آپاچی آمده است.
اگر سبد خرید یا حساب کاربری کش شود، ممکن است خریداری اطلاعات نفر دیگری را ببیند. بعد از هر تغییر در تنظیمات کش، با همان دستور curl مطمئن شوید این صفحه ها مقدار hit نمی گیرند.
کش اشیا با Redis برای سبد خرید و کاربر واردشده
کش صفحه معمولا برای کاربر واردشده و سبد خرید به کار نمی آید. در این درخواست ها کش اشیا کمک می کند، چون نتیجه کوئری های تکراری در Redis یا Memcached می ماند. LiteSpeed Cache خودش Redis ندارد و فقط به سرویسی وصل می شود که روی سرور نصب است، پس گزینه Object Cache را فقط وقتی روشن کنید که هاست این سرویس را داشته باشد. در صفحه هاست ووکامرس پیکوهاست کش اشیای Redis کنار وب سرور لایت اسپید و دیسک NVMe آمده است.
سقف پردازش هم زمان و خطای 508
روی هاست اشتراکی با کلودلینوکس، هر حساب برای پردازش های هم زمان (Entry Processes) سقف دارد. اگر در کمپین فروش درخواست های کش نشده از این سقف بیشتر شوند، بازدیدکننده خطای 508 Resource Limit Is Reached می بیند. بخش Resource Usage در cPanel نشان می دهد در چه ساعتی به سقف CPU، رم، Entry Processes یا I/O رسیده اید.
اگر بعد از کم کردن درخواست های کش نشده، مثل cart fragments، باز در ساعت های عادی به سقف می رسید، پلن را ارتقا بدهید یا سراغ سرور مجازی بروید. اثر نوع دیسک و رم روی سرعت دیتابیس را در مطلب هارد NVMe و رم DDR4 در سرور مجازی توضیح داده ایم.
بهینه سازی دیتابیس ووکامرس
قبل از هر تغییری در این بخش از دیتابیس بکاپ بگیرید، با خروجی SQL در phpMyAdmin یا دستور wp db export.
HPOS ووکامرس
HPOS (High-Performance Order Storage) سفارش ها را از جدول های عمومی wp_posts و wp_postmeta به جدول های مخصوص سفارش منتقل می کند. در فروشگاه هایی که از ووکامرس ۸٫۲ به بعد نصب شده اند HPOS از ابتدا روشن است و فروشگاه های قدیمی تر باید خودشان فعالش کنند. مراحل طبق مستندات HPOS ووکامرس:
- به WooCommerce > Settings > Advanced > Features بروید. اگر افزونه ناسازگاری نصب باشد، همین صفحه به آن اشاره می کند.
- گزینه Enable compatibility mode را روشن کنید تا سفارش ها بین جدول های قدیم و جدید همگام شوند.
- صبر کنید تا کارهای همگام سازی در WooCommerce > Status > Scheduled Actions تمام شوند. ووکامرس سفارش ها را ۲۵ تا ۲۵ تا منتقل می کند.
- گزینه High-performance order storage را انتخاب و ذخیره کنید.
افزونه هایی مثل Subscriptions که از نوع نوشته سفارشی استفاده می کنند باید در طول انتقال فعال بمانند. طبق همین مستندات، غیرفعال کردنشان قبل از انتقال ممکن است داده ها را ناهماهنگ کند. درگاه و افزونه پیامک را هم قبل از خاموش کردن حالت سازگاری با یک سفارش آزمایشی تست کنید.
گزینه های autoload در wp_options
وردپرس در هر درخواست همه گزینه هایی را که autoload دارند یک جا از wp_options می خواند. افزونه ای که مدت ها پیش پاکش کرده اید ممکن است تنظیمات حجیمش را آنجا گذاشته باشد. این کوئری در phpMyAdmin بزرگ ترین ها را نشان می دهد. اگر پیشوند جدول ها wp_ نیست، مقدار $table_prefix در wp-config.php را جایش بنویسید.
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;
گزینه ای که مال افزونه حذف شده است را می توانید پاک کنید، ولی اگر مطمئن نیستید مال کدام افزونه است، دست نزنید. برای گزینه افزونه فعال فقط autoload را خاموش کنید و اگر کش اشیا دارید، بعدش کش را خالی کنید:
UPDATE wp_options SET autoload = 'off' WHERE option_name = 'option_name_here';
ترنزینت ها و سشن های مشتری
ترنزینت ها داده های موقتی اند و همه شان بعد از انقضا خودبه خود پاک نمی شوند. ابزار ترنزینت های منقضی را در WooCommerce > Status > Tools اجرا کنید، یا با WP-CLI:
wp transient delete --expired
جدول wp_woocommerce_sessions سبدهای خرید بازدیدکننده ها را نگه می دارد. ابزار Clear customer sessions در همان صفحه خالی اش می کند، ولی سبدهای باز همه خریدارها هم با آن پاک می شود. آن را در ساعت کم بازدید اجرا کنید.
جدول های Action Scheduler
ووکامرس و بسیاری از افزونه ها کارهای پس زمینه را با Action Scheduler اجرا می کنند و سابقه شان در wp_actionscheduler_actions و wp_actionscheduler_logs می ماند. کارهای Complete و Canceled به طور پیش فرض بعد از ۳۰ روز پاک می شوند، ولی کارهای Failed در این پاک سازی نیستند.
در WooCommerce > Status > Scheduled Actions تعداد هر وضعیت را ببینید. صف Pending با ده ها هزار کار یعنی کارها اجرا نمی شوند و علتش معمولا کرون است. هزاران کار Failed با یک hook مشخص هم از خطای یک افزونه خبر می دهد. بعد از رفع علت، کارهای Failed قدیمی را همان جا با فیلتر وضعیت حذف کنید. برای کوتاه کردن مدت نگهداری، این کد را در یک افزونه اختصاصی کوچک یا functions.php قالب فرزند بگذارید:
add_filter( 'action_scheduler_retention_period', function () {
return WEEK_IN_SECONDS;
} );
درخواست cart fragments و سبد کشویی قالب
cart fragments اسکریپتی در ووکامرس است که محتوای سبد کشویی سربرگ را با یک درخواست AJAX به روز نگه می دارد. این درخواست از کش صفحه عبور می کند. برای دیدنش تب Network مرورگر را با F12 باز کنید، فیلتر را روی Fetch/XHR بگذارید و صفحه اصلی را دوباره بار کنید. درخواستی با آدرس ?wc-ajax=get_refreshed_fragments یعنی این اسکریپت فعال است.
طبق وبلاگ توسعه دهندگان ووکامرس، از نسخه ۷٫۸ این اسکریپت فقط وقتی بار می شود که ابزارک سبد خرید (Cart widget) در صفحه نمایش داده شود. بعضی قالب ها مثل Storefront این ابزارک را مستقیم در فایل های قالب گذاشته اند و اسکریپت با آن ها همچنان بار می شود. اگر سبد کشویی لازم نیست، از تنظیمات قالب خاموشش کنید. اگر لازم است، ووکامرس بلوک Mini-Cart را پیشنهاد می کند که از cart fragments استفاده نمی کند. در LiteSpeed Cache هم تب WooCommerce گزینه Vary for Mini Cart را دارد.
WP-Cron را به کرون واقعی سرور بسپارید
WP-Cron با بازدید صفحه ها اجرا می شود و وردپرس در هر بارگذاری بررسی می کند کاری سر رسیده یا نه. صفحه ای که از کش تحویل داده می شود PHP را اجرا نمی کند، پس با کش فعال کارها دیرتر از موعد انجام می شوند و صف Pending در Action Scheduler بزرگ می شود.
اول در cPanel بخش Cron Jobs کرونی بسازید که wp-cron.php را صدا بزند. برای فروشگاه، فاصله پنج دقیقه انتخاب معقولی است:
*/5 * * * * wget -q -O /dev/null "https://example.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1
اگر wget روی هاست نیست، curl -s هم همین کار را می کند. مراحل با تصویر در راهنمای تنظیم کرون جاب در cPanel آمده است. بعد از ساخت کرون، این خط را در wp-config.php بالای خط That's all, stop editing اضافه کنید. اگر ترتیب برعکس شود، تا ساخت کرون سرور هیچ کار زمان بندی شده ای اجرا نمی شود.
define( 'DISABLE_WP_CRON', true );
تصاویر، قالب و افزونه های سنگین
عکس محصول معمولا بزرگ ترین فایل صفحه است. عکس چند هزار پیکسلی گوشی را مستقیم آپلود نکنید. ابعاد را به بزرگ ترین اندازه ای که قالب نمایش می دهد برسانید و فرمت WebP را ترجیح بدهید که وردپرس از نسخه ۵٫۸ آپلودش را پشتیبانی می کند. تصویر اصلی بالای صفحه محصول اغلب همان عنصر LCP است. lazy load را برای آن خاموش کنید تا مرورگر زودتر دانلودش را شروع کند و برای تصاویر پایین صفحه روشن بگذارید.
سنگینی افزونه ها را با داده Query Monitor بسنجید. قالب های چندمنظوره و صفحه سازها معمولا CSS و JS خود را روی همه صفحه ها بار می کنند و پنل های Scripts و Styles نشان می دهند روی سبد خرید چه فایل هایی می آید. برای آزمایش قطعی، روی نسخه آزمایشی افزونه ها را یکی یکی غیرفعال کنید و هر بار TTFB سبد خرید را با همان دستور curl بگیرید.
منابع بیرونی که از ایران کند یا قطع می شوند
دسترسی به بعضی سرویس های خارجی از داخل ایران کند یا گاهی قطع است و وضعیتشان هم ثابت نمی ماند. اگر قالب فونت را از Google Fonts یا فایل JS را از یک CDN خارجی می خواند و آن سرویس جواب ندهد، مرورگر تا پایان زمان انتظار صبر می کند و صفحه دیر نمایش داده می شود.
در تب Network گزینه Disable cache را بزنید، صفحه را دوباره بار کنید و با راست کلیک روی سرستون ها ستون Domain را اضافه کنید. درخواست هایی را که قرمزند یا مدت طولانی pending می مانند پیدا کنید. فونت ها را روی هاست خودتان بگذارید و کدهای خارجی بلااستفاده، مثل کد ردیاب قدیمی، را حذف کنید.
سمت سرور هم افزونه ای که لایسنسش را از سایت سازنده چک می کند، اگر جواب نگیرد تا timeout صبر می کند. این درخواست ها در پنل HTTP API Calls دیده می شوند و اگر لازم نیستند، از تنظیمات همان افزونه خاموش می شوند. وردپرس دو ثابت هم دارد که همه درخواست های بیرونی را جز دامنه های مجاز می بندد:
define( 'WP_HTTP_BLOCK_EXTERNAL', true );
define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.wordpress.org' );
در این حالت آدرس API درگاه پرداخت و سرویس پیامک را هم باید به فهرست اضافه کنید، وگرنه پرداخت و پیامک از کار می افتد. این روش را اول روی نسخه آزمایشی امتحان کنید.
درگاه پرداخت و پیامک در مسیر خرید
در فروشگاه ایرانی سایت از درگاه توکن می گیرد، خریدار به صفحه بانک می رود و بعد از برگشت، سایت تراکنش را از درگاه استعلام می کند. خیلی از افزونه های پیامک هم درست لحظه ای که وضعیت سفارش عوض می شود پیامک می فرستند. اگر API پیامک چند ثانیه دیر جواب بدهد، خریدار همان چند ثانیه را روی صفحه سفید بعد از پرداخت می گذراند.
روی نسخه آزمایشی یک سفارش با حالت آزمایشی درگاه ثبت کنید و زمان هر مرحله را در تب Network ببینید. اگر برگشت از بانک به سایت چند ثانیه طول کشید، این تغییرها معمولا اثر دارند:
- اگر افزونه پیامک گزینه ارسال در صف یا پس زمینه دارد، روشنش کنید.
- برای یک رویداد دو افزونه پیامک یا اطلاع رسانی را هم زمان فعال نگذارید.
- افزونه درگاه هایی را که استفاده نمی کنید کامل حذف کنید. بعضی از آن ها حتی غیرفعال هم فایلی به صفحه پرداخت اضافه می کنند.
- اگر سرور فروشگاه خارج از ایران است، از شرکت پرداخت بپرسید درخواست از IP خارجی را می پذیرد یا نه. بعضی درگاه های بانکی فقط IP ثبت شده سرور را قبول می کنند.
اگر خریداران فروشگاه داخل ایران اند، در صفحه هاست ووکامرس ایران درباره سرورهای دیتاسنترهای تهران و اتصال به درگاه های شاپرک توضیح داده شده است.
ترتیب کار برای افزایش سرعت ووکامرس
اگر نمی دانید از کجا شروع کنید، این ترتیب کمترین ریسک را دارد:
- TTFB صفحه محصول و سبد خرید را با curl بگیرید و یادداشت کنید.
- Query Monitor را روی سبد خرید و پرداخت باز کنید و افزونه های کند و درخواست های بیرونی را فهرست کنید.
- از دیتابیس بکاپ بگیرید، ترنزینت های منقضی و autoload را بررسی کنید و HPOS را اول روی نسخه آزمایشی فعال کنید.
- کرون سرور را بسازید و بعد WP-Cron را خاموش کنید.
- استثناهای کش را برای سبد خرید، پرداخت و حساب کاربری چک کنید و بعد سراغ تصاویر و فایل های قالب بروید.
- همان دستورهای curl را دوباره اجرا کنید و با عددهای قدم اول مقایسه کنید.
اگر بعد از این مراحل سبد خرید در ساعت های عادی هنوز کند است و Resource Usage به سقف می رسد، منابع هاست برای این فروشگاه کافی نیست. معیارهای خرید هاست جدید را در چک لیست انتخاب هاست وردپرس در ایران ببینید. برای جابه جایی فروشگاه هم مراحل انتقال سایت وردپرس به هاست جدید از بکاپ تا تغییر DNS نوشته شده است.