Speed Up Laravel website - Step by Step

Speed Up Laravel website - Step by Step

Due to popularity Laravel Framework, Making a great website or web application with Laravel is increasing day by day. Laravel is a great choice for making a web application. The fact is it's not a CMS like WordPress, Drupal, Zoomla etc so we can't get ready-made plugins to improve our laravel application just in few clicks but Laravel has so much speed optimization features out of the box for speed up your website or web application. If you are looking for a step by step guide for boost up website speed then it's for you. In this post, I'll show you a full step by step guide for increasing your laravel website page speed & performance.

 

Steps for increase Laravel website speed

 

  1. HTML minification
  2. Route caching
  3. Query caching
  4. Configuration caching
  5. Bundle & Minify CSS/Js
  6. Optimize images
  7. Eager loading
  8. htaccess optimization
  9. Faster web hosting server
  10. Use a CDN

Note: Before doing these steps you can test your current laravel website page speed test via Google page speed, GT Metrix or Pingdom then you can compare the improvement before and after.

 

1. HTML minification

During HTML markup we keep a lot of white spaces for indentation and increasing code readability. Browser doesn't care about the spaces & indentation but it the spaces make our HTML file bigger and make an impact on page speed. We can easily reduce HTML page size by unifying the HTML using Laravel middleware. Let's do HTML modification using laravel middleware.

Run the command to make HTML minify middleware and do the code in the middleware for unifying the HTML on-page request.

php artisan make:middleware HtmlMifier
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Response;

class HtmlMifier
{
    public function handle($request, Closure $next)
    {
  
        $response = $next($request);

        $contentType = $response->headers->get('Content-Type');
        if (strpos($contentType, 'text/html') !== false) {
            $response->setContent($this->minify($response->getContent()));
        }

        return $response;

    }

    public function minify($input)
    {
        $search = [
            '/\>\s+/s',
            '/\s+</s',
        ];

        $replace = [
            '> ',
            ' <',
        ];

        return preg_replace($search, $replace, $input);
    }
}

Add the middleware into kernel.php file into the $routeMiddlewareGroup array

protected $routeMiddleware = [
  ...,
  ...,
  'HtmlMinifier' => '\App\Http\Middleware\HtmlMinifier',
]

Now we can use this middleware in our route file. For every request on our site, this middleware will automatically do HTML modification and response to the user.

Route::group(['middleware'=>'HtmlMinifier'], function(){ 
  
  Route::get('/', 'SiteController@home');
  Route::get('/{slug}', 'SiteController@postDetails');
  ...
  ...

});

 

2. Route caching

We can get more request-response speed by using Laravel route caching. To make route caching run the command given below.

php artisan route:cache

This command will cache you all routes into a file routes.php into bootstrap/cache directory. If you need to add more route later or edit then you must have to clear route-cache and re-generate it again.

php artisan route:clear

 

3. Query caching

Suppose we have 50 blog post in our site and every day 1 thousand visitors visit our website. In this situation, whenever visitor read a post, it hit the database for the post content and take time which is another slow query factor and your site get a little bit slower. We can easily recover this problem by caching our post. When any user read a blog post then it'll store in our cache and next for any visitor the post will serve from our cache instead of hitting to our database. So no more database request and get a faster response. That's cool! Let's do that.

// example.com/awesome-post-title
public function postDetails($slug){
	
	$post = Cache::rememberForever('posts.'.$slug, function($slug) use($slug) {
    	    return Post::where('slug',$slug)->first();
	});

	return view('frontend.posts.post-details',['post'=>$post]);
} 

Look here I'm passing the post slug which is unique for every post for SEO friendly URL. You can read the post for more about SEO friendly URL generation.

Stop thinking, You might be thinking if we update any post, our visitor still gets the older content from the cache. That's right but we can easily fix that by a little bit code in our model for cache management during post update and delete. Let's add a boot method inside the post model.

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
	
	public static function boot()
	{
	    parent::boot();

	    static::updating(function ($instance) {
	        // update cache content
	        Cache::put('posts.'.$instance->slug,$instance);
	    });

	    static::deleting(function ($instance) {
	        // delete post cache
	        Cache::forget('posts.'.$instance->slug);
	    });
	}
}

 

4. Configuration caching

In our laravel website, inside the config directory, all configuration stay. Laravel parse all the files for reading config value in run time. We can easily optimize the speed by making config cache. To make config caching in laravel run the command given below.

php artisan config:cache

This command will cache you all configuration into a file config.php into bootstrap/cache directory. If you need to add more configuration later or change then you must have to clear config-cache and re-generate it again. To clear config cache run the command given below.

php artisan config:clear

 

5. Bundle & Minify CSS/Js

Every site has a lot of CSS/Js file and every time the browser makes an HTTP request for every CSS/JS file. Think about, if our site has 20-25 different CSS/Js file link then it'll make more HTTP request to our server for load the resources and it's another site slower factor. We can make a bundle for CSS and minify the CSS files and Js file for removing extra white space and indentation via Webpack, Gulp, Grunt or any other bundler tools. It will help us to make all CSS file into a single file and all Js file into a single js bundle file. Now, this we help us by reducing the HTTP request and site get load faster than before. Here is an example of laravel mix.

//css bundle
mix.styles([
'public/css/vendor/bootstrap.min.css',
'public/css/style.css'
], 'public/bundle/app.css');


//js bundle
mix.scripts([
  'public/js/vendor/jquery-2.1.4.js',
  'public/js/vendor/bootstrap.min.js',
  'public/js/functions.js'
], 'public/bundle/app.js');
npm run production

Now link the app.css and app.js file in your site template instead of adding every single CSS and js file.

 

6. Optimize images

Image is very important for every website. It takes more byte than text content. We have to aware of using the image and its format. Images have more impact on Google page speed insights reports. We can use TinyPng, Cloudinary, Squoosh to get better-optimized images for our website. The optimized images can save our site bandwidth and also load our website fast.

An example of an optimized image

image-optimization.png

We can lazy load our website images. It's a beneficial technique because with this technique only the images load which are currently visible to the viewport. When the user scrolls the page, then it will load the rest of the images so webpage load faster. To implement a lazy load image just add  lazy="loading" attribute to your img tag.

 

7. Eager Loading

Eager loading is very efficient for loading data from the database with less database operation. It solves the N+1 query problem. Get our desire data with less database interaction with optimized query running is very helpful to improve the site or web application performance. Let's see an example.

Suppose we have a Post model and it has a one-many relationship with a comment model.

class Comment extends Model
{
    public function post()
    {
      return $this->belongsTo(Post::class);
    }
}

class Post extends Model
{
    public function comments()
    {
      return $this->hasMany(Comment::class);
    }
}

 

Without Eager Loading

Now if we run loop to a Post eloquent collection, behind the scenes it'll execute N+1 query without eager loading which is performance killer if the collection is so big.

$posts = Post::all();
   
foreach ($posts as $post) {
    echo $post->name;
   
    $comments = $post->comments;
    foreach($comments as $comment){
    	// do something
    }
}

This code generates N+1 and database interaction. If our post table has 100 posts then it will generate 100+1 queries. 1 for getting posts from posts table and another 100 queries for each post comment.

# query for N number of post

SELECT * FROM posts;

# For each N post it will run also

SELECT * FROM comments WHERE post_id = 1
SELECT * FROM comments WHERE post_id = 2
SELECT * FROM comments WHERE post_id = 3

..... 

 

With Eager Loading

Now if we use Eager loading feature then it will run an optimized query for us.

$posts = Post::with('comments')->get();
   
foreach ($posts as $post) {
    echo $post->name;
   
    $comments = $post->comments;
    foreach($comments as $comment){
    	// do something
    }
}

Now with eager loading, it'll run only two queries like below.

# First query
SELECT * FROM posts;

# Second query
SELECT * FROM comments WHERE post_id IN (1, 2, 3, 4, 5, ...);

 

 

8. htaccess optimization

Laravel htaccess optimization can be helped for increasing your website page speed by image caching, HTML compression, Gzip Compression, Enable Browser Caching, Expires headers to leverage browser caching. Open your htaccess file and add the code snippet given below at the end of your site.

Note: htaccess file is very important for server and it's very powerful for impacting your Linux web server. Before any changes please keep a backup first.

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType application/javascript "access 1 month"
ExpiresByType application/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 2 days"
</IfModule>

# GZIP COMPRESSION
# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript

# compress HTML
<files *.html>
SetOutputFilter DEFLATE
</files>
# GZIP COMPRESSION

 

9. Faster web hosting server

By doing everything, we have to deploy our website into web hosting. A faster web server has a big impact to serve webpages to your visitor quickly. So we have to keep in mind about this fact. Choose VPS or dedicated web hosting server for your website if it's affordable for you or use a good shared hosting. You must have to very concern about choosing a web hosting for your website. To get reliable web hosting for your website at a reasonable price, you can choose one of the hosting provider given below.

 

10. Use a CDN

If your site has high traffic from a different region then use a CDN (Content Delivery Network). It will deliver your website content with low network latency. A little bit summary, suppose you have a website and its hosting server is located to the USA and you visitors from the USA, and most the visitors from Europ and Asia. For users who are far away from your server, website load time gets higher because the information travels long distance for reaching to your visitor. In this situation you can use a CDN server for you Europ, Asia visitors to get quick website content delivery. If you want to use CDN for your website then these could be the best option for you given below

  • MaxCDN
  • Cloudflare

 

I have tried with my best to write this step by step process for making a super-fast optimized laravel website that will help you to increase your laravel website speed. If you implement these techniques with the proper way, then you can see a noticeable performance in your Laravel made website. I hope this post will help you to learn a lot of tricks and technique to improve your site speed & how to increase laravel website speed. If this post helpful to you, then please share this post with other so that they can be helped for making a super-fast laravel website!


Share

Related Post


Laravel Simple Filemanager

Repository Design Pattern in Laravel

Laravel desktop application using Electron Js

Top 10 question-answer for New Laravel developer

Laravel Excel import export

Laravel 7 authentication tutorial