DEV Community

Cover image for Maximizing Laravel Performance: Essential Optimization Strategies for Web Developers
MK
MK

Posted on • Originally published at techtales.blog on

Maximizing Laravel Performance: Essential Optimization Strategies for Web Developers

When it comes to websites, performance of applications/websites have an impact on user experience and rankings across search engines. When developing with Laravel, a PHP framework, you get features and techniques included in the framework to optimize your site for speed and efficacy. In this post we will discuss laravel optimization using effective caching strategies, efficient databases querying and lazy loading vs eager loading along with some other techniques to improve performance.

Caching Strategies

Caching is used to reduce the load on database and speed up the response. Laravel has many caching backends like Memcached and Redis. These are pretty straightforward to implement in Laravel.

// Cache a query result for 60 minutes
$posts = Cache::remember('posts', 60, function () {
    return Post::all();
});
Enter fullscreen mode Exit fullscreen mode

This code checks for posts and if not then fetches them and adds them to cache for 60 minutes.

use Illuminate\Support\Facades\Cache;

$popularPosts = Cache::remember('popular_posts', 1440, function () {
    return Post::with('author', 'comments')
               ->where('views', '>', 1000)
               ->orderBy('views', 'DESC')
               ->take(10)
               ->get();
});
Enter fullscreen mode Exit fullscreen mode

This query caches top 10 popular posts along with their associated authors and comments for 1440 minutes (24 hours). This query uses with to minimize the number of queries executed.

Database Query Writing for Laravel Optimization

We always try to improve our database queries but Laravel provides Eloquent ORM that makes it easy to write complex queries in simple way but it’s most important to know how to write an efficient query.

// Instead of fetching all columns, specify only the needed ones
$users = User::select('id', 'name', 'email')->get();
Enter fullscreen mode Exit fullscreen mode

This query is small and specific and reduces the unnecessary load on database. It only fetches what’s needed.

$postsWithActiveAuthors = Post::whereHas('author', function ($query) {
    $query->where('active', 1);
})->get();
Enter fullscreen mode Exit fullscreen mode

This snippet uses whereHas method to fetch the posts that have active authors (very useful). It makes the query efficient by avoiding loading all posts.

Lazy Loading vs Eager Loading

Laravel gives you options on how to load related models. Lazily which means that related models load on-demand and Eagerly that loads elated models all at once. Eager loading is most of the time the preferred way unless you have very specific case for Lazy loading.

// Lazy loading (inefficient)
$books = Book::all();
foreach ($books as $book) {
    echo $book->author->name;
}

// Eager loading (efficient)
$books = Book::with('author')->get();
foreach ($books as $book) {
    echo $book->author->name;
}
Enter fullscreen mode Exit fullscreen mode

Eager loading fetches related models in single query and avoids the N+1 problem of lazy loading.

Inefficient: Here each user’s posts are not fetched untill they are accessed inside loop leading to multiple queries.

$users = User::all();
foreach ($users as $user) {
    // This will execute a new query for each user to get their posts
    foreach ($user->posts as $post) {
        echo $post->title;
    }
}
Enter fullscreen mode Exit fullscreen mode

Efficient: with('posts') ensures that all the posts are loaded in single query. It reduces the number query to just one making it more efficient.

$users = User::with('posts')->get();
foreach ($users as $user) {
    // All posts are loaded along with users in a single query
    foreach ($user->posts as $post) {
        echo $post->title;
    }
}
Enter fullscreen mode Exit fullscreen mode

Other Optimization Techniques

Implementing following Laravel optimization techniques also contribute in enhancing application performance significantly.

Optimize your assets:

Laravel Mix provides clean and fluent API for webpack build steps. We can use it to minify and combine CSS and JavaScript files. This reduces the number HTTP requests.

// webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
   .minify('public/js/app.js');

mix.sass('resources/sass/app.scss', 'public/css')
   .minify('public/css/app.css');
Enter fullscreen mode Exit fullscreen mode

This example compiles JS and SASS files and minifies them resulting in much smaller files and faster load time.

Database Indexing:

Use Index for columns that are frequently searched or used as foreign keys. This enhances database query performance and Index can be added via Migrations.

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('posts', function (Blueprint $table) {
    // Create an index for the 'title' column
    $table->index('title');

    // Create a unique index for the 'slug' column
    $table->unique('slug');

    // Foreign key index
    $table->foreign('user_id')->references('id')->on('users');
});
Enter fullscreen mode Exit fullscreen mode

Route Caching:

Route caching increases website performance and especially if you have large number of routes.

php artisan route:cache
Enter fullscreen mode Exit fullscreen mode

Here we create a route cache file for faster route registration. Note that any new route additions require running this command again.

Queue Workloads for laravel optimization:

For tasks that are time consuming, e.g. sending emails or some sort of image processing, it’s beneficial to run these tasks in background. Laravel’s queue system is designed to queue certain tasks and process them asynchronously.

First, generate a new job.

php artisan make:job ProcessImage
Enter fullscreen mode Exit fullscreen mode

Next, add job’s behaviour

// app/Jobs/ProcessImage.php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessImage implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $image;

    public function __construct($image)
    {
        $this->image = $image;
    }

    public function handle()
    {
        // Process the image here
    }
}
Enter fullscreen mode Exit fullscreen mode

Now Dispatch the job.

ProcessImage::dispatch($image);
Enter fullscreen mode Exit fullscreen mode

This snippet sends the image processing job to the default queue and Laravel handles the rest.

Wrapping Up

Optimizing a Laravel application involves a combination of caching strategies, efficient database operations, and smart loading of resources. By implementing these techniques, you can significantly reduce load times and resource usage, leading to a smoother user experience and potentially higher SEO rankings.

Here are some resources to dive deep in Laravel Optimization and Performance.

Laravel official documentation: https://laravel.com/docs/10.x/readme

Laracasts: https://laracasts.com/browse/all

The post Maximizing Laravel Performance: Essential Optimization Strategies for Web Developers appeared first on TechTales.

Top comments (1)

Collapse
 
loyaldev profile image
k. Fidèle Eklou

I really appreciate this post. I find it useful.