6 راه سریع و آسان برای سرعت بخشیدن به وب سایت‌های لاراول

آفلاین
user-avatar
عرفان حشمتی
15 تیر 1400, خواندن در 12 دقیقه

تخمین زده می‌شود که اگر بارگیری وبسایت بیش از 3 ثانیه طول بکشد، 40 درصد از کاربران آن صفحه را ترک می‌کنند. بنابراین برای گرفتن رتبه بهتر بسیار مهم است که اطمینان حاصل کنید سایتتان زیر 3 ثانیه لود شود. من خودم هر زمان که کدی را برای پروژه‌های جدید لاراول می‌نویسم، سعی می‌کنم تا حدی که می‌توانم کد را در محدوده زمانی و آستانه تعریف شده بهینه کنم. بهتر است شما هم سعی کنید از این تکنیک‌ها برای بالا بردن سرعت اجرا به منظور بهبود تجربه کلی کاربران استفاده کنید.

در زیر برخی از تکنیک‌هایی که (یا به سایر توسعه دهندگان پیشنهاد می‌کنم) برای دستیابی به برخی از پیشرفت‌های سریع عملکرد وبسایت‌ها و برنامه‌های لاراول استفاده می‌کنم را ذکر کرده‌ام.

1. فقط فیلدهای مورد نیاز را در درخواست‌های پایگاه داده واکشی کنید

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

به عنوان مثال فرض کنید یک مدل کاربر دارید که شامل 20 قسمت مختلف است. حال تصور کنید که 10000 کاربر در سیستم خود دارید و سعی می‌کنید روی هر یک از آنها نوعی پردازش انجام دهید. کد شما ممکن است شبیه این باشد:

$users = User::all(); foreach($users as $user) {
    // Do something here 
}

کوئری فوق وظیفه بازیابی داده‌های با ارزش 200000 فیلد را دارد. اما تصور کنید که هنگام پردازش هر کاربر، فقط می‌توانید از قسمتهای id ، first_name و last_name استفاده کنید. بنابراین بدان معناست که از بین 20 فیلدی که در حال واکشی هستید، 17 مورد از آنها برای این قطعه خاص اضافه هستند. در نتیجه آنچه می‌توانیم انجام دهیم این است که به صراحت فیلدهایی را که در کوئری برگردانده می‌شوند، تعریف کنیم. در این حالت کد شما ممکن است شبیه به این باشد:

$users = User::select(['id', 'first_name', 'last_name'])->get(); 
foreach($users as $user) {
    // Do something here
}

با این کار میزان فیلدهای برگشت داده شده در درخواست را از 200000 به 30،000 کاهش خواهیم داد. اگرچه این کار احتمالا تأثیر زیادی در بارگذاری پایگاه داده نخواهد داشت، اما باعث کاهش ترافیک شبکه بین برنامه شما و دیتابیس می‌شود. دلیلش هم این است که داده‌های کمتری برای سریال سازی، ارسال و سپس غیرفعال سازی وجود خواهند داشت، نسبت به اینکه بخواهید همه قسمت‌های موجود را واکشی کنید. در نهایت با کاهش ترافیک شبکه و میزان داده‌هایی که باید پردازش شوند، به سرعت بالا آمدن سایت کمک می‌کنید.

لطفا توجه داشته باشید در مثال فوق ممکن است هرگز چنین کاری نکنید و بسته به شرایط از قطعه‌ها یا صفحه بندی استفاده کنید. مثال فقط برای نشان دادن یک راه حل آسان و قابل اجرا است.

این راه حل ممکن است در سایت یا برنامه‌های کوچکتر پیشرفت چشمگیری نداشته باشد. با این حال چیزی است که قطعا می‌تواند در کاهش زمان بارگذاری برنامه‌هایی در مقیاس بزرگتر مفید باشد. اگر جدولی را داشته باشید که دارای قسمت‌های BLOB یا TEXT باشد، ممکن است بهبود بهتری را نیز احساس کنید. این فیلدها می‌توانند داده را در خود نگه دارند و در نتیجه به طور بالقوه زمان رفت و برگشت کوئری را افزایش دهند. بنابراین اگر جدول مدل شما حاوی هر یک از این فیلدها است، برای کاهش زمان بارگذاری فقط آنهایی را که نیاز دارید، تعریف کنید.

2. از eager loading در هر کجا که امکان دارد استفاده کنید

هنگامی که مدلی را از پایگاه داده واکشی می‌کنید و سپس هر نوع پردازش را روی روابط مدل انجام می‌دهید، مهم است که از eager loading استفاده کنید. این نوع بارگیری به طور ساده با استفاده از لاراول انجام می‌شود و اساسا مانع از مواجهه با مشکل N + 1 در داده‌ها می‌گردد. این مشکل به دلیل ایجاد N + 1 نمایش در پایگاه داده است و N تعداد مواردی است که از پایگاه داده واکشی می‌شود. برای توضیح بهتر این موضوع و ارائه برخی نکات، بیایید مثال زیر را بررسی کنیم.

فرض کنید که شما دو مدل (Comment و Author) دارید که بین آنها رابطه یک به یک وجود دارد. حال تصور کنید که صد کامنت دارید و می‌خواهید روی آنها یک حلقه بزنید و نام نویسنده را استخراج کنید.

بدون eager loading، کد شما ممکن است به این شکل باشد:

$comments = Comment::all();
foreach ($comments as $comment ) {
    print_r($comment->author->name); 
}

کد بالا منجر به 101 درخواست به پایگاه داده می‌شود. اولین کوئری واکشی همه کامنت‌ها است و صد کوئری دیگر هم برای گرفتن نام نویسنده در هر تکرار حلقه اجرا می‌شود. بدیهی است که این امر می‌تواند باعث مشکلات عملکردی و کند شدن برنامه شما شود. اما چگونه این را بهبود بخشیم؟

با استفاده از eager loading، می‌توانیم کد را اینگونه تغییر دهیم:

$comments = Comment::with('authors')->get();
foreach ($comments as $comment ) {
    print_r($comment->author->name);
}

همانطور که مشاهده می‌کنید، با کد قبل تقریبا یکسان به نظر می‌رسد و همچنین خواناتر است. با افزودن ::with('authors') همه کامنت ها را واکشی می‌کند و سپس کوئری دیگری بلافاصله برای واکشی نویسنده انجام می‌دهد. بنابراین بدان معنی است که ما درخواست را از 101 به 2 کاهش داده ایم.

برای کسب اطلاعات بیشتر، مستندات لاراول در مورد eager loading را بررسی کنید.

3. از شر هر پکیج غیرضروری یا ناخواسته خلاص شوید

فایل composer.json را باز کرده و به هر یک از وابستگی‌های خود نگاه کنید. برای هر یک از وابستگی‌ها از خود بپرسید "آیا من واقعا به این پکیج نیاز دارم؟" اکثرا پاسخ مثبت است، اما ممکن است برای بعضی‌ها اینگونه نباشد.

هر بار که کتابخانه کامپوزر جدیدی را در پروژه خود بگنجانید، به طور بالقوه کدی را اضافه کرده‌اید که ممکن است بی مورد اجرا شود. پکیج‌های لاراول معمولا شامل سرویس دهنده‌هایی هستند که بر اساس هر درخواست که ثبت می‌کنند، اجرا می‌شوند. بنابراین اگر 20 پکیج لاراول به برنامه خود اضافه کنید، احتمالا حداقل 20 کلاس ایجاد می‌شود و بر اساس هر درخواست اجرا می‌گردد. اگرچه این کار تأثیر زیادی روی عملکرد سایتها یا برنامه‌هایی با میزان بازدید زیاد ندارد، اما قطعا خواهید دید که در برنامه‌های بزرگتر تفاوت ایجاد می‌کند.

راه حل این مسئله این است که تعیین کنید آیا واقعا به همه پکیج‌ها نیاز دارید یا خیر. شاید شما از پکیجی استفاده می‌کنید که طیف وسیعی از ویژگی‌ها را ارائه می‌دهد اما شما فقط از یک ویژگی کوچک آن استفاده می‌کنید. از خود بپرسید "آیا می‌توانم خودم این کد را بنویسم و ​​کل پکیج را حذف کنم"؟ البته به دلیل محدودیت زمانی، نوشتن کد همیشه امکان پذیر نیست؛ زیرا مجبورید کد را بنویسید، تست کنید و سپس آن را نگهداری کنید. حداقل با استفاده از پکیج‌ها از پروژه‌های متن باز استفاده می‌کنید تا آن کارها را برای شما انجام دهند. اما اگر به راحتی می‌توانید کدی بنویسید که به جای پکیج‌ها قرار بگیرد، حتما آنها را حذف کنید.

4. کش (حافظه نهان)

لاراول با بسیاری از روش‌های ذخیره سازی همراه است. این موارد باعث می‌شوند سرعت وبسایت یا برنامه شما بدون نیاز به ایجاد تغییر در کد، افزایش یابد.

Route Caching

به خاطر روشی که لاراول اجرا می‌کند، این فریمورک را boot کرده و فایلهای مسیرها را بر روی هر درخواستی که انجام می‌شود تجزیه می‌کند. این مستلزم خواندن فایل، تجزیه و تحلیل محتوای آن و سپس نگه داشتن آن به روشی است که برنامه شما بتواند از آن استفاده کند و آن را درک کند. بنابراین لاراول دستوری را ارائه می‌دهد که می‌توانید با استفاده از آن یک فایل route واحد ایجاد کنید که با تجزیه و تحلیل سریعتر انجام می‌شود:

php artisan route:cache

لطفا توجه داشته باشید که اگر از این دستور استفاده می‌کنید و مسیرهای خود را تغییر می‌دهید، باید مطمئن شوید که کد زیر را نیز اجرا کنید:

php artisan route:clear

با این کار فایل مسیرهای ذخیره شده حذف می‌شود تا مسیرهای جدیدتر ثبت شوند. بنابراین ارزش دارد که این دو دستور را به اسکریپت دیپلوی شده خود اضافه کنید. اگر از اسکریپت دیپلوی استفاده نمی‌کنید، ممکن است پکیج Laravel Executor برای کمک به شما مفید باشد.

Config Caching

مشابه route caching هر بار که درخواستی انجام می‌شود، لاراول بوت شده و هر یک از فایل‌های پیکربندی پروژه شما خوانده و تجزیه می‌شوند. بنابراین برای جلوگیری از رسیدگی به هر یک از فایل‌ها می‌توانید دستور زیر را اجرا کنید تا یک فایل پیکربندی کش شده ایجاد کند:

php artisan config:cache

دقیقا مانند کش مسیر، لازم است به یاد داشته باشید هر بار که فایل env. یا فایل‌های خود را به روز می‌کنید، دستور زیر را اجرا کنید:

php artisan config:clear

قبلا می‌دیدم که بسیاری از توسعه دهندگان پیکربندی خود را در محیط توسعه محلی ذخیره می‌کنند و سپس زمان زیادی را سپری می‌کردند تا بفهمند چرا تغییرات فایل env. نشان داده نمی‌شود. بنابراین توصیه می‌کنم فقط پیکربندی و مسیرهای خود را روی سیستم‌هایتان کش کنید تا در چنین وضعیتی قرار نگیرید.

در کد برنامه لاراول خود می‌توانید مواردی را برای بهبود عملکرد وب سایت ذخیره کنید. به عنوان مثال فرض کنید عبارت زیر را دارید:

$users = DB::table('users')->get();

برای استفاده از کش با این کوئری می‌توانید کد را به صورت زیر تغییر دهید:

$users = Cache::remember('users', 120, function () { 
    return DB::table('users')->get(); 
});

کد بالا از متد remember() استفاده می‌کند. آنچه که اساسا انجام می‌دهد این است که بررسی می‌کند کش شامل مواردی با users اصلی است. اگر این کار را انجام دهد، مقدار cached را برمی‌گرداند. اگر در حافظه پنهان وجود نداشته باشد، نتیجه کوئری DB::table('users')->get() بازگردانده می‌شود و همچنین کش می‌شود. در این مثال خاص، آیتم به مدت 120 ثانیه کش می‌شود.

کش داده‌ها و نتایج کوئری از این دست می‌تواند یک روش واقعا موثر در کاهش فراخوانی‌های پایگاه داده، کاهش زمان اجرا و بهبود عملکرد باشد. با این حال لازم به یادآوری است که اگر آیتم دیگر معتبر نیست، گاهی اوقات لازم است آن را از حافظه پنهان حذف کنید.

با توجه به مثال بالا فرض کنید که ما کوئری users را در حافظه پنهان داریم. حال تصور کنید که کاربر جدیدی ایجاد، به روز یا حذف شده است. آن نتیجه کوئری حافظه پنهان دیگر معتبر نیست. برای رفع این مشکل می‌توانیم از observer مدل لاراول برای حذف این مورد از حافظه پنهان استفاده کنیم. این بدان معناست که دفعه بعد اگر سعی کنیم به متغیر users$ دست پیدا کنیم، یک کوئری جدید به پایگاه داده اجرا می‌شود و نتیجه به روزشده را به ما می‌دهد.

5. از آخرین نسخه PHP استفاده کنید

با انتشار هر نسخه جدید PHP، عملکرد و سرعت بهبود می‌یابد. Kinsta تست‌های زیادی در چندین نسخه PHP و فریمورک‌ها و CMSهای مختلف (به عنوان مثال لاراول، وردپرس، دروپال، جوملا) انجام داد و به این نتیجه رسید که PHP 7.4 بهترین عملکرد را ارائه می‌دهد.

اجرای این مورد در مقایسه با سایر نکات بالا ممکن است کمی دشوارتر باشد، زیرا برای اطمینان از اینکه می‌توانید با خیال راحت به جدیدترین نسخه PHP به روزرسانی کنید، باید کد خود را تغییر دهید.

6. از صف‌ها استفاده کنید

انجام این نکته ممکن است کمی بیشتر از موارد بالا طاقت فرسا و زمان‌بر باشد. با این وجود از نظر تجربه کاربری احتمالا یکی از جالب‌ترین‌ها خواهد بود.

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

برای درک بهتر، این مثال را ببینید:

class ContactController extends Controller
{ 
    /**
     * Store a new podcast.
     *
     * @param Request $request
     * @return JsonResponse 
     */ 
    public function store(ContactFormRequest $request)
    {
        $request->storeContactFormDetails();
        Mail::to('[email protected]')->send(new ContactFormSubmission); 
    
    return response()->json(['success' => true]);
    } 
}

در کد بالا وقتی متد ()store فراخوانی می‌شود، جزئیات فرم تماس را در پایگاه داده ذخیره می‌کند، سپس برای اطلاع رسانی ارسال فرم جدید به آدرس مشخص شده یک ایمیل می‌فرستد و پاسخ JSON را برمی‌گرداند. مشکل کد این است که کاربر باید قبل از ارسال ایمیل منتظر بماند تا آن را در مرورگر وب دریافت کند. اگرچه این ممکن است تنها چند ثانیه باشد، اما به طور بالقوه می‌تواند بازدید کنندگان را معطل کند و باعث شود صفحه را ترک کنند.

برای استفاده از سیستم صف می‌توانیم کد را به صورت زیر تغییر دهیم:

class ContactController extends Controller
{
    /**
     * Store a new podcast.
     *
     * @param Request $request
     * @return JsonResponse
     */ 
    public function store(ContactFormRequest $request)
    { 
        $request->storeContactFormDetails();
        dispatch(function () {
            Mail::to('[email protected]')->send(new ContactFormSubmission); 
        })->afterResponse();
        return response()->json(['success' => true]);
    }
}

کد بالا در متد ()store اکنون جزئیات فرم تماس را در پایگاه داده ذخیره می‌کند، سپس برای ارسال در صف قرار می‌گیرد و پاسخ را برمی‌گرداند. پس از ارسال پاسخ به مرورگر وب کاربر، ایمیل به صف اضافه می‌گردد تا پردازش شود. این کار به این معنی است که نیازی نیست منتظر ارسال ایمیل بمانیم تا اینکه پاسخ را دریافت کنیم.

برای کسب اطلاعات بیشتر در مورد نحوه تنظیم صف‌ها در برنامه لاراول خود، مستندات آن را بررسی کنید.

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
عرفان حشمتی @heshmati74
مهندس معماری سیستم های کامپیوتری، طراح و توسعه دهنده وب سایت
دنبال کردن

گفتگو‌ برنامه نویسان

بخشی برای حل مشکلات برنامه‌نویسی و مباحث پیرامون آن وارد شو