Jak zoptymalizować aplikację internetową PHP Laravel pod kątem wysokiej wydajności?

Sztuczki na przyspieszenie działania aplikacji Laravel

Laravel to rozbudowany framework, ale jego szybkość działania nie zawsze jest imponująca. Przyjrzyjmy się kilku technikom, które pomogą nam zwiększyć jego wydajność!

W dzisiejszych czasach trudno spotkać programistę PHP, który nie miałby styczności z Laravel. Albo są to juniorzy i mid-developerzy, doceniający szybkość tworzenia aplikacji oferowaną przez ten framework, albo bardziej doświadczeni programiści, którzy pod wpływem rynkowych trendów musieli nauczyć się Laravela.

Bez względu na powód, nie można zaprzeczyć, że Laravel odnowił ekosystem PHP. Osobiście, prawdopodobnie dawno opuściłbym świat PHP, gdyby nie istniał Laravel.

Fragment (nieco usprawiedliwionego) samouwielbienia Laravela.

Laravel robi wszystko, aby ułatwić nam pracę, ale to oznacza, że pod spodem wykonuje mnóstwo zadań, aby zapewnić nam komfortową pracę jako programistów. Wszystkie „magiczne” funkcje Laravela, które wydają się działać w sposób intuicyjny, mają złożoną strukturę kodu, która musi być aktualizowana za każdym razem, gdy funkcja jest uruchamiana. Nawet prosty wyjątek pokazuje, jak głęboko sięga błąd (od miejsca jego wystąpienia, aż do rdzenia frameworka):

W przypadku błędu kompilacji w widoku, mamy do prześledzenia 18 wywołań funkcji. Osobiście zdarzyło mi się spotkać sytuację, gdzie było ich 40, a może być ich jeszcze więcej przy użyciu dodatkowych bibliotek i wtyczek.

Chodzi o to, że te warstwy kodu domyślnie spowalniają działanie Laravela.

Jak wolny jest Laravel?

Szczerze mówiąc, nie da się jednoznacznie odpowiedzieć na to pytanie z kilku powodów.

Po pierwsze, nie istnieje żaden powszechnie akceptowany, obiektywny i sensowny standard mierzenia szybkości działania aplikacji internetowych. Szybciej czy wolniej w porównaniu do czego? W jakich warunkach?

Po drugie, szybkość działania aplikacji zależy od tak wielu czynników (bazy danych, systemu plików, sieci, pamięci podręcznej itd.), że mówienie o szybkości jako takiej nie ma większego sensu. Bardzo szybka aplikacja internetowa z bardzo powolną bazą danych będzie po prostu wolna. 🙂

Ta niepewność jest przyczyną popularności testów porównawczych. Nawet jeśli nie mają one większego znaczenia (zobacz ten i ten), stanowią pewien punkt odniesienia i pomagają nam zachować zdrowy rozsądek. Dlatego, traktując je z przymrużeniem oka, spróbujmy wyrobić sobie pojęcie o szybkości frameworków PHP.

Korzystając z tego dość popularnego repozytorium na GitHub źródło, prezentujemy porównanie frameworków PHP:

Możesz nie zauważyć Laravela (nawet jeśli mocno wytężysz wzrok), chyba że poszukasz go na samym końcu tabeli. Tak, moi drodzy, Laravel jest ostatni! To prawda, że większość tych „frameworków” nie jest zbyt praktyczna, ani nawet użyteczna, ale to pokazuje, jak powolny jest Laravel w porównaniu do innych, bardziej popularnych rozwiązań.

Zazwyczaj ta „powolność” nie jest odczuwalna w codziennych aplikacjach, ponieważ rzadko osiągają one duże obciążenie. Ale gdy już do tego dojdzie (powyżej 200-500 jednoczesnych połączeń), serwery zaczynają mieć problemy i mogą przestać działać. Wtedy nawet inwestycje w lepszy sprzęt nie pomagają, a rachunki za infrastrukturę rosną tak szybko, że Twoje ambitne plany dotyczące przetwarzania w chmurze legną w gruzach.

Ale nie martw się! Ten artykuł nie skupia się na tym, czego nie da się zrobić, ale na tym, co można zrobić. 🙂

Dobra wiadomość jest taka, że istnieje wiele sposobów, aby Twoja aplikacja Laravel działała szybciej. Nawet kilka razy szybciej. Tak, to nie żart. Możesz sprawić, że ten sam kod zacznie działać błyskawicznie i zaoszczędzisz setki dolarów na kosztach infrastruktury/hostingu każdego miesiąca. Jak? Przejdźmy do konkretów.

Cztery poziomy optymalizacji

Moim zdaniem optymalizację można przeprowadzić na czterech różnych poziomach (w przypadku aplikacji PHP):

  • Poziom języka: Oznacza to korzystanie z szybszej wersji języka i unikanie konkretnych funkcji lub stylów kodowania, które spowalniają działanie kodu.
  • Poziom frameworka: To są kwestie, które omówimy w tym artykule.
  • Poziom infrastruktury: Dostrajanie menedżera procesów PHP, serwera WWW, bazy danych itp.
  • Poziom sprzętu: Przejście na lepszy, szybszy i bardziej wydajny sprzęt hostingowy.

Każdy z tych poziomów ma swoje znaczenie (na przykład optymalizacja PHP-fpm jest bardzo ważna i daje duże efekty). Jednak w tym artykule skupimy się na optymalizacjach dotyczących wyłącznie poziomu drugiego – frameworka.

Nawiasem mówiąc, numeracja nie ma żadnego uzasadnienia i nie jest powszechnie akceptowana. Po prostu ją wymyśliłem. Proszę, nigdy nie cytujcie mnie i nie mówcie: „Potrzebujemy optymalizacji typu 3 na naszym serwerze”, bo wasz lider zespołu mnie znajdzie i zabije. 😀

A teraz w końcu przejdźmy do meritum.

Unikaj problemu zapytań N+1

Problem zapytań N+1 często występuje podczas korzystania z ORM. Laravel posiada potężny ORM o nazwie Eloquent, który jest tak wygodny i elegancki, że często zapominamy o tym, co dzieje się pod spodem.

Rozważmy typowy scenariusz: wyświetlenie listy zamówień złożonych przez daną listę klientów. Jest to powszechne w systemach e-commerce oraz w interfejsach raportowania, gdzie musimy wyświetlić wszystkie encje powiązane z innymi encjami.

W Laravelu moglibyśmy sobie wyobrazić funkcję kontrolera, która wykonuje to zadanie w następujący sposób:

class OrdersController extends Controller 
{
    // ... 

    public function getAllByCustomers(Request $request, array $ids) {
        $customers = Customer::findMany($ids);        
        $orders = collect(); // new collection
        
        foreach ($customers as $customer) {
            $orders = $orders->merge($customer->orders);
        }
        
        return view('admin.reports.orders', ['orders' => $orders]);
    }
}

Fajnie! I co ważniejsze, elegancko i pięknie. 🤩🤩

Niestety, jest to fatalny sposób pisania kodu w Laravelu.

Dlaczego?

Kiedy prosimy ORM o znalezienie danych klientów, generowane jest następujące zapytanie SQL:

SELECT * FROM customers WHERE id IN (22, 45, 34, . . .);

Dokładnie tak, jak tego oczekujemy. W wyniku tego wszystkie zwrócone wiersze są przechowywane w kolekcji $customers wewnątrz funkcji kontrolera.

Następnie przeglądamy każdego klienta po kolei i pobieramy jego zamówienia. To spowoduje wykonanie kolejnych zapytań. . .

SELECT * FROM orders WHERE customer_id = 22;

. . . tyle razy, ilu jest klientów.

Innymi słowy, jeśli potrzebujemy pobrać dane zamówień dla 1000 klientów, całkowita liczba zapytań do bazy wyniesie 1 (aby pobrać dane wszystkich klientów) + 1000 (aby pobrać dane zamówień każdego klienta) = 1001. Stąd nazwa N+1.

Czy da się to zrobić lepiej? Oczywiście! Używając tak zwanego ładowania „eager loading”, możemy zmusić ORM do wykonania JOIN i zwrócenia wszystkich potrzebnych danych w jednym zapytaniu! Oto przykład:

$orders = Customer::findMany($ids)->with('orders')->get();

Otrzymana struktura danych jest oczywiście zagnieżdżona, ale dane zamówień można łatwo wyodrębnić. Wynikowe, pojedyncze zapytanie wygląda mniej więcej tak:

SELECT * FROM customers INNER JOIN orders ON customers.id = orders.customer_id WHERE customers.id IN (22, 45, . . .);

Pojedyncze zapytanie jest zdecydowanie lepsze niż tysiąc dodatkowych zapytań. Wyobraź sobie, co by się stało, gdybyśmy musieli przetworzyć 10 000 klientów! Albo, co gorsza, gdybyśmy chcieli wyświetlić wszystkie pozycje w każdym zamówieniu! Pamiętaj, nazwa tej techniki to „eager loading” i prawie zawsze jest dobrym pomysłem.

Korzystaj z buforowania konfiguracji

Jednym z powodów elastyczności Laravela jest bogactwo plików konfiguracyjnych. Chcesz zmienić sposób lub miejsce przechowywania obrazów?

Po prostu zmień plik config/filesystems.php (przynajmniej w momencie pisania tego tekstu). Chcesz korzystać z wielu sterowników kolejek? Możesz je zdefiniować w pliku config/queue.php. Po sprawdzeniu, okazało się, że istnieje 13 plików konfiguracyjnych dla różnych aspektów frameworka, więc niezależnie od tego, co chcesz zmienić, nie będziesz zawiedziony.

Biorąc pod uwagę naturę PHP, za każdym razem, gdy pojawia się nowe żądanie, Laravel budzi się, uruchamia wszystko i analizuje wszystkie pliki konfiguracyjne, aby określić, jak tym razem ma zadziałać. To bez sensu, jeśli nic się nie zmieniło od kilku dni! Przebudowywanie konfiguracji przy każdym żądaniu jest stratą czasu, której można (a nawet trzeba) uniknąć. Rozwiązaniem jest proste polecenie Laravela:

php artisan config:cache

Polecenie to łączy wszystkie dostępne pliki konfiguracyjne w jeden i zapisuje go w pamięci podręcznej, skąd można go szybko pobrać. Następnym razem, gdy pojawi się żądanie, Laravel odczyta ten pojedynczy plik i przystąpi do działania.

Warto jednak pamiętać, że buforowanie konfiguracji jest delikatną operacją, która może się nie udać. Największym problemem jest to, że po wykonaniu tego polecenia, funkcja env() wywoływana z dowolnego miejsca poza plikami konfiguracyjnymi zwróci wartość null!

Ma to sens, gdy się nad tym zastanowić. Korzystając z buforowania konfiguracji, mówisz frameworkowi: „Uważam, że wszystko jest dobrze skonfigurowane i jestem pewien, że nie chcę niczego zmieniać”. Innymi słowy, zakładasz, że środowisko pozostanie statyczne, a do tego służą pliki .env.

Biorąc to pod uwagę, oto kilka żelaznych zasad buforowania konfiguracji:

  • Rób to tylko na serwerze produkcyjnym.
  • Rób to tylko wtedy, gdy jesteś naprawdę pewien, że chcesz zamrozić konfigurację.
  • Jeśli coś pójdzie nie tak, cofnij ustawienia za pomocą php artisan cache:clear
  • Módl się, żeby szkody nie były zbyt duże!

Ogranicz liczbę automatycznie ładowanych usług

Aby być użytecznym, Laravel ładuje wiele usług podczas uruchamiania. Są one zdefiniowane w pliku config/app.php w tablicy 'providers’. Spójrzmy, co mam w swoim przypadku:

/*
    |--------------------------------------------------------------------------
    | Autoloaded Service Providers
    |--------------------------------------------------------------------------
    |
    | The service providers listed here will be automatically loaded on the
    | request to your application. Feel free to add your own services to
    | this array to grant expanded functionality to your applications.
    |
    */

    'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        IlluminateAuthAuthServiceProvider::class,
        IlluminateBroadcastingBroadcastServiceProvider::class,
        IlluminateBusBusServiceProvider::class,
        IlluminateCacheCacheServiceProvider::class,
        IlluminateFoundationProvidersConsoleSupportServiceProvider::class,
        IlluminateCookieCookieServiceProvider::class,
        IlluminateDatabaseDatabaseServiceProvider::class,
        IlluminateEncryptionEncryptionServiceProvider::class,
        IlluminateFilesystemFilesystemServiceProvider::class,
        IlluminateFoundationProvidersFoundationServiceProvider::class,
        IlluminateHashingHashServiceProvider::class,
        IlluminateMailMailServiceProvider::class,
        IlluminateNotificationsNotificationServiceProvider::class,
        IlluminatePaginationPaginationServiceProvider::class,
        IlluminatePipelinePipelineServiceProvider::class,
        IlluminateQueueQueueServiceProvider::class,
        IlluminateRedisRedisServiceProvider::class,
        IlluminateAuthPasswordsPasswordResetServiceProvider::class,
        IlluminateSessionSessionServiceProvider::class,
        IlluminateTranslationTranslationServiceProvider::class,
        IlluminateValidationValidationServiceProvider::class,
        IlluminateViewViewServiceProvider::class,

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        AppProvidersAppServiceProvider::class,
        AppProvidersAuthServiceProvider::class,
        // AppProvidersBroadcastServiceProvider::class,
        AppProvidersEventServiceProvider::class,
        AppProvidersRouteServiceProvider::class,

    ],

Ponownie policzyłem i na liście jest 27 usług! Możesz ich wszystkich potrzebować, ale jest to mało prawdopodobne.

Na przykład, w tej chwili tworzę REST API, co oznacza, że nie potrzebuję dostawcy usług sesji, dostawcy usług widoku itp. A ponieważ robię wiele rzeczy po swojemu i nie trzymam się domyślnych ustawień frameworka, mogę wyłączyć dostawcę usług uwierzytelniania, dostawcę usług paginacji, dostawcę usług tłumaczeń i tak dalej. W sumie, prawie połowa z nich jest mi niepotrzebna.

Przyjrzyj się uważnie swojej aplikacji. Czy potrzebuje wszystkich tych usługodawców? Ale na litość boską, proszę, nie komentuj ślepo tych usług i nie wysyłaj tego na produkcję! Przeprowadź wszystkie testy, sprawdź ręcznie na maszynach programistycznych i testowych i bądź bardzo ostrożny, zanim wdrożysz to na produkcję. 🙂

Rozsądnie korzystaj ze stosów middleware

Kiedy potrzebujesz niestandardowego przetwarzania przychodzącego żądania HTTP, naturalną reakcją jest utworzenie nowego middleware. Kuszące jest otwarcie pliku app/Http/Kernel.php i umieszczenie middleware w stosie web lub api; w ten sposób staje się on dostępny w całej aplikacji, nawet jeśli nie robi nic nadzwyczajnego (np. rejestrowanie lub powiadamianie).

Jednak wraz z rozwojem aplikacji, ta kolekcja globalnych middleware może stać się sporym obciążeniem dla aplikacji, jeśli wszystkie (lub większość) z nich są wykonywane przy każdym żądaniu, nawet jeśli nie ma ku temu uzasadnienia biznesowego.

Innymi słowy, bądź ostrożny, gdzie dodajesz/stosujesz nowe middleware. Dodanie czegoś globalnie może być wygodne, ale na dłuższą metę spadek wydajności będzie duży. Wiem, ile wysiłku kosztuje selektywne stosowanie middleware za każdym razem, gdy pojawia się nowa zmiana, ale jest to wysiłek, który chętnie podejmę i tobie go polecam!

Unikaj ORM (czasami)

Chociaż Eloquent sprawia, że wiele interakcji z bazą danych jest przyjemnych, odbywa się to kosztem szybkości. Będąc mapperem, ORM musi nie tylko pobrać rekordy z bazy danych, ale także utworzyć instancje obiektów modelu i wypełnić je danymi z kolumn.

Tak więc, jeśli wykonasz proste $users = User::all() i masz powiedzmy 10 000 użytkowników, framework pobierze 10 000 wierszy z bazy danych i wewnętrznie wykona 10 000 instrukcji new User() i wypełni ich właściwości odpowiednimi danymi. To ogromna ilość pracy wykonywanej w tle, a jeśli baza danych jest wąskim gardłem Twojej aplikacji, dobrym pomysłem może być ominięcie ORM.

Jest to szczególnie prawdziwe w przypadku skomplikowanych zapytań SQL, gdzie trzeba skakać przez wiele przeszkód i pisać zamknięcia w zamknięciach, aby uzyskać wydajne zapytanie. W takich przypadkach lepiej użyć DB::raw() i napisać zapytanie ręcznie.

Z tego badania wynika, że nawet przy prostych operacjach wstawiania, Eloquent jest znacznie wolniejszy wraz ze wzrostem liczby rekordów:

Wykorzystuj buforowanie w jak największym stopniu

Jedną z najlepiej strzeżonych tajemnic optymalizacji aplikacji internetowych jest buforowanie.

Dla niewtajemniczonych, buforowanie polega na wstępnym obliczaniu i przechowywaniu wyników kosztownych operacji (zarówno pod względem wykorzystania procesora, jak i pamięci), a następnie po prostu zwracaniu ich, gdy to samo zapytanie jest powtarzane.

Na przykład, w sklepie internetowym może być 2 miliony produktów, ale zazwyczaj klienci są zainteresowani tymi, które są świeżo dostarczone, w określonym przedziale cenowym i dla określonej grupy wiekowej. Wysyłanie zapytań do bazy danych, aby uzyskać te informacje, jest stratą czasu, ponieważ zapytania nie zmieniają się często. Lepiej jest przechowywać te wyniki w miejscu, do którego mamy szybki dostęp.

Laravel ma wbudowane wsparcie dla wielu typów buforowania. Oprócz korzystania z sterownika buforowania i tworzenia systemu buforowania od podstaw, możesz skorzystać z pakietów Laravel, które ułatwiają buforowanie modeli, buforowanie zapytań itd.

Pamiętaj jednak, że poza pewnymi prostymi przypadkami użycia, gotowe pakiety pamięci podręcznej mogą powodować więcej problemów niż rozwiązywać.

Preferuj buforowanie w pamięci RAM

Kiedy buforujesz coś w Laravel, masz kilka opcji, gdzie przechowywać wyniki. Opcje te są znane również jako sterowniki pamięci podręcznej. I chociaż możliwe i całkowicie rozsądne jest używanie systemu plików do przechowywania wyników buforowania, nie jest to tak naprawdę buforowanie.

Najlepiej jest używać pamięci podręcznej w pamięci RAM (w całości znajdującej się w pamięci RAM), takiej jak Redis, Memcached, MongoDB itp. Dzięki temu, przy większym obciążeniu, buforowanie będzie spełniać swoją funkcję, a nie samo w sobie stanie się wąskim gardłem.

Możesz pomyśleć, że dysk SSD jest prawie tak samo szybki jak pamięć RAM, ale to nieprawda. Nawet nieformalne porównania pokazują, że RAM jest 10-20 razy szybszy niż SSD, jeśli chodzi o szybkość.

Moim ulubionym systemem buforowania jest Redis. Jest niesamowicie szybki (zwykle wykonuje 100 000 operacji odczytu na sekundę), a dla bardzo dużych systemów pamięci podręcznej można go łatwo przekształcić w klaster.

Buforuj trasy

Podobnie jak konfiguracja aplikacji, trasy nie zmieniają się często i są idealne do buforowania. Jest to szczególnie przydatne, jeśli nie lubisz dużych plików i dzielisz web.php i api.php na kilka mniejszych plików. Pojedyncze polecenie Laravela zbiera wszystkie dostępne trasy i przechowuje je, aby uzyskać do nich dostęp w przyszłości:

php artisan route:cache

A gdy skończysz dodawać lub zmieniać trasy, po prostu wykonaj:

php artisan route:clear

Optymalizacja obrazów i CDN

Obrazy są sercem i duszą większości aplikacji internetowych. Jednocześnie są największym obciążeniem dla przepustowości i jedną z głównych przyczyn wolnego działania aplikacji/stron internetowych. Jeśli po prostu, bez zastanowienia, przechowujesz przesłane obrazy na serwerze i przesyłasz je w odpowiedziach HTTP, tracisz ogromną szansę na optymalizację.

Pierwsza rekomendacja to nie przechowywanie obrazów lokalnie. Istnieje ryzyko utraty danych, a transfer danych może być bardzo powolny, w zależności od lokalizacji klienta.

Zamiast tego wybierz rozwiązanie takie jak Cloudinary, które automatycznie zmienia rozmiar i optymalizuje obrazy w locie.

Jeśli to nie jest możliwe, użyj Cloudflare do buforowania i udostępniania obrazów, gdy są przechowywane na serwerze.

A jeśli nawet to nie jest możliwe, niewielka modyfikacja oprogramowania serwera WWW w celu kompresji zasobów i nakazania przeglądarce odwiedzającego buforowanie rzeczy, robi dużą różnicę. Oto fragment konfiguracji Nginx:

server {

   # file truncated
    
    # gzip compression settings
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;

   # browser cache control
   location ~* .(ico|css|js|gif|jpeg|jpg|png|woff|ttf|otf|svg|woff2|eot)$ {
         expires 1d;
         access_log off;
         add_header Pragma public;
         add_header Cache-Control "public, max-age=86400";
    }
}

Zdaję sobie sprawę, że optymalizacja obrazów nie ma nic wspólnego z Laravelem, ale jest to tak prosta i potężna technika (i tak często zaniedbywana), że nie mogłem się powstrzymać.

Optymalizacja autoloadera

Automatyczne ładowanie to przydatna i stosunkowo nowa funkcja w PHP, która prawdopodobnie uratowała język przed zagładą. Proces wyszukiwania i ładowania odpowiedniej klasy poprzez analizę danego ciągu przestrzeni nazw jest czasochłonny i można go uniknąć w środowiskach produkcyjnych, gdzie wydajność jest najważniejsza. Laravel ma rozwiązanie tego problemu: proste polecenie:

composer install --optimize-autoloader --no-dev

Wykorzystuj kolejki

Kolejki są sposobem przetwarzania zadań, gdy jest ich wiele, a ukończenie każdego z nich zajmuje kilka milisekund. Dobrym przykładem jest wysyłanie e-maili – często spotykane w aplikacjach internetowych jest wysyłanie powiadomień e-mail po wykonaniu pewnych działań przez użytkownika.

Na przykład, przy nowym produkcie możesz chcieć, aby menedżerowie (około 6-7 adresów e-mail) byli powiadamiani, za każdym razem, gdy ktoś złoży zamówienie o określonej wartości. Zakładając, że Twój serwer poczty odpowiada na żądanie SMTP w 500 ms, mówimy o 3-4 sekundowym opóźnieniu w potwierdzeniu zamówienia dla użytkownika. Słaby UX, zgodzisz się ze mną.

Rozwiązaniem jest przechowywanie zadań w miarę ich pojawiania się, informowanie użytkownika, że wszystko jest w porządku i przetwarzanie ich (kilka sekund) później. Jeśli wystąpi błąd, zadania w kolejce mogą być ponawiane, zanim zostaną uznane za zakończone niepowodzeniem.

Kredyty: Microsoft.com

Chociaż system kolejkowania nieco komplikuje konfigurację (i dodaje trochę obciążenia związanego z monitorowaniem), jest niezbędny w nowoczesnej aplikacji internetowej.

Optymalizacja zasobów (Laravel Mix)

W przypadku wszystkich zasobów front-end w aplikacji Laravel, zadbaj o to, aby istniał potok, który kompiluje i minimalizuje wszystkie pliki zasobów. Osoby, które czują się komfortowo z systemami pakującymi takimi jak Webpack, Gulp, Parcel itp., nie muszą się tym przejmować, ale jeśli jeszcze tego nie robisz, Laravel Mix to solidna rekomendacja.

Mix to lekkie (i urocze, szczerze mówiąc!) opakowanie Webpack, które zajmuje się wszystkimi plikami CSS, SASS, JS itp. w środowisku produkcyjnym. Typowy plik .mix.js może być tak mały i nadal czynić cuda:

const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

Automatycznie zajmuje się importem, minimalizacją, optymalizacją i całą resztą, gdy przygotowujesz aplikację do produkcji i uruchamiasz npm run production. Mix obsługuje nie tylko tradycyjne pliki JS i CSS, ale także komponenty Vue i React, które możesz mieć w swojej aplikacji.

Więcej informacji tutaj!

Podsumowanie

Optymalizacja wydajności to bardziej sztuka niż nauka – wiedza o tym, jak i ile trzeba zrobić jest ważniejsza niż to, co konkretnie trzeba zrobić. Nie ma końca tego, co i ile możesz zoptymalizować w aplikacji Laravel.

Jednak bez względu na to, co robisz, chciałbym dać Ci jedną radę na pożegnanie – optymalizację należy przeprowadzać, gdy jest ku temu solidny powód, a nie dlatego, że brzmi to fajnie lub dlatego, że martwisz się wydajnością aplikacji dla 100 000 użytkowników, podczas gdy w rzeczywistości masz ich tylko 10.

Jeśli nie jesteś pewien, czy musisz optymalizować swoją aplikację, nie musisz wnikać w szczegóły. Działająca aplikacja, która wydaje się powolna, ale robi dokładnie to, co ma robić, jest znacznie bardziej wartościowa niż aplikacja, która została zoptymalizowana pod kątem nie wiadomo jakiego obciążenia, ale od czasu do czasu się psuje.

A jeśli chcesz zostać mistrzem Laravela, sprawdź ten kurs online.

Niech Twoje aplikacje działają dużo szybciej! 🙂