ondrejsanetrnik's avatar

Slow view rendering when using Blade components

I have been hitting this strange performance issue with Laravel Blade when using components. I usually have between 10 - 200 components on each view. I see the same issue in production as well as on my local machine, on all of my apps running both Laravel 7 and 8. I am running PHP 7.4 with Nginx 1.14.0.

Each component slows down the rendering of the view. Rendering this simple view with 100 empty components takes around 0.2s:

<!DOCTYPE html>
<html lang="en">

<head>
</head>
<body>
    @foreach (range(0, 100) as $i)
      <x-test />  <!-- empty component -->
    @endforeach
</body>

Rendering it without any components takes around 0.005s I have tried:

Caching my views - no effect

Using different Blade syntax @include('components.test') - no effect

Creating components via artisan command - no effect

Different environments and Laravel versions - no effect

Not using Blade components and writing out contents of the component straight into the view improves performance, but that would mean repeating myself quite often.

Any ideas what may cause this? Thanks in advance.

This is a copy of https://stackoverflow.com/questions/67968084/slow-view-rendering-when-using-blade-components

0 likes
15 replies
rodrigo.pedra's avatar
Level 56

In a recent project if lots of blade components I faced some slow rendering issues.

What made a difference on that project was:

  • Use traditional layout directives, instead of blade components for layout
    • @\extends, @\yield, @\section, @\stack and @\push (slashes added to avoid mentions)
  • Make sure every blade component have a class

Looking at the framework's code, for every anonymous blade component (e.g. a component without a class) Laravel creates am instance of Illuminate\View\AnonymousComponent class for it. So, in practice, every component is expected to have a companion class, and if they don't have one, Laravel will use this AnonymousComponent class instead.

Not sure why this slows down code execution, but for that project, both Memory consumption and render time dropped by a lot.

I know it is not very convenient to create a lot of classes if you already have a bunch of class-less components. Believe me when I started seeing noticeable differences I created a ton of them. But it solved my problems then, maybe it could help you out.

Good luck!

5 likes
ondrejsanetrnik's avatar

Thank you very much for your insight! I tried replacing my anonymous components with proper classes and using traditional Blade layout. Sadly, that did not lead to a performance improvement in my case.

1 like
ondrejsanetrnik's avatar

I have all my views cached. It surprises me though that the view caching has zero effect on performance. (Zero or close to zero, I was not able to see any difference when running my tests)

1 like
Snapey's avatar

do you have any view composers?

ondrejsanetrnik's avatar

Yes, I use a view composer, but it is limited to a temlplate and few views. I run my tests outside of the template, so the view composer is not initialized.

view()->composer(['components.master', 'masters.show', 'orders.create'], function ($view) {
            $view->with('cart', Item::findMany(array_keys(session('cart') ?? [])));
        });

@rodrigo.pedra Your solution works! I was able to reduce the rendering time using components with classes instead of anonymous components. It made no difference when there is no data passed to the component, but with data, rendering time is reduced significantly!

View:

@foreach ($products as $product)
        <div></div>                              // Rendering 100 of these takes 0.004s
@endforeach

@foreach ($products as $product)
        @include('test-with-class')          // Rendering 100 of these takes 0.2s
@endforeach

@foreach ($products as $product)
        <x-test-with-class />                        // Rendering 100 of these takes 0.2s
@endforeach

@foreach ($products as $product)
        <x-test-anonymous />                // Rendering 100 of these takes 0.2s
@endforeach

@foreach ($products as $product)
        <x-product-with-class :product='$product' />       // Rendering 100 of these takes 0.3s
@endforeach

@foreach ($products as $product)
        <x-product-anonymous :product='$product' />    // Rendering 100 of these takes 0.8s
@endforeach

Test components:

<div></div>

Product components:

<div>{{$product->title}}</div>

Still, I was not able to reduce the time it seems to take to load the component itself, and I would be better of just repeating the contents all over the code instead of packing them into components. (see difference between empty div and a component containing nothing but an empty div)

Any ideas?

4 likes
twols's avatar

I do have the same or at least very similar problem: Rendering tree of comments/replies (recursive) and using components for that. First of all: Recursive loading coasts time. Loading many comments, like 50, takes also about 40 ms.

Is there any way to speed up components?

ondrejsanetrnik's avatar

@twols Sadly, I still have not found the solution to this problem. 3 months after I still do not use components in case the component is loaded too many times.

twols's avatar

@ondrejsanetrnik I've started rewriting some parts of the template, ended up replace components by "includes". I was really happy using components, but they seem to be no the most performant part of laravel..

rodrigo.pedra's avatar

@seewhy sure.

Mostly Firefox' s developer tools network tab, and Laravel debug bar response times.

Hope this helps =)

angus_mcritchie's avatar

I encountered slow rendering on my pages after breaking down my blade components, resulting in a range of 500 to 2,000 components on each page.

Unfortunately, I didn't realise how much this was slowing down my project so that rendering was taking longer than my database queries!

I thought the view:cache command would've made them almost instant to render, but that was just a flawed assumption.

However, I created a blade directive package called @boost that halved most of my page load times.

I'd highly recommend you give it a go!

Happy coding ❤️

2 likes

Please or to participate in this conversation.