Improving Pagespeed Insights Score from 0 to 75+ with Laravel

Recently I had a client contact me asking me to improve the load times of their website. After some analysis I found that the pagespeed score was a big fat 0, and there was one contributing factor.

Bet you can't guess what it was. 

If you work with websites every day like I do, this isn't going to be news to you. It was images.

Images made up 20MB of the page's total size, which adversely affected load time. Unfortunately this isn't an uncommon occurrence, with images being one of the most prevalent things found on the web and websites.

Fortunately there's a relatively easy fix, and if you're working with Laravel it's pretty much wrapped up in a package and tied off with a bow.

Introducing Intervention Image

From their website:

Intervention Image is an open source PHP image handling and manipulation library. It provides an easier and expressive way to create, edit, and compose images and supports currently the two most common image processing libraries GD Library and Imagick.

Intervention has a lovely Laravel Package which you can find here: https://github.com/Intervention/image 

What we're going to use Intervention for is to create a thumbnail version of your full size image to display in places which don't actually need to display the full version of the image.

The basic premise is that once a user uploads a file, you need to also generate a thumbnail for that image and store it alongside the image.

This is done using Intervention's fit method, as seen below:

    // Store the image
    $imagePath = request()->file('image')->store('images', 'public');
        // Generate a thumbnail path (There are better ways)
    $thumbPath = str_replace('images', 'images/thumbnails', $imagePath);
    // Thumbnail the image
    $thumbnail = \Image::make($imagePath))->fit(250, 150)->encode();
    // Store the thumbnail
    Storage::disk('public')->put($thumbPath, $thumbnail);
    // Store path in the database
    if (($imagePath) && ($thumbPath)) {
        $model->update([
            'image' =>  $imagePath,
            'thumbnail' =>  $thumbPath,
        ]);
    }

For things like avatars and cover photos, you can even opt to overwrite the existing image, as seen below:

        
    // Store the image
    $imagePath = request()->file('image')->store('images', 'public');
    // Thumbnail the image
    $image = \Image::make($imagePath)->fit(800, 600)->encode();
    // Overwrite the existing image
    $image = \Storage::put($imagePath, $image);
    // Store path in the database
    if ($imagePath) {
        $model->update([
            'image' =>  $imagePath,
        ]);
    }

As a footnote here, you can also use Laravel's Storage Facade to generate a URL to the image and store that in the database if you prefer. Read more about that here: https://laravel.com/docs/master/filesystem#file-urls

All that's left to do really is to make your front end respect that you wish to show thumbnailed versions of the same image in certain places. 

Let's say you have a blade file called card.blade.php which you include within foreach loops in multiple places. All you need to do is replace the reference to $model->image with $model->thumbnail and you should be good to go!

For bonus points, you could also use a lazy load implementation to make images load only when necessary.

Available for Freelance Work

If you'd like to work with me on your project, please get in touch by emailing me[at]mikeylicio.us, clicking the envelope in the footer, or clicking the button below.