Optimizing Filament SSR for High-Performance Applications

Learn how to build a high-performance Filament application with Server-Side Rendering (SSR) enabled, optimized resource caching, and code splitting.

filament ssr optimization

A staggering 75% of e-commerce sites experience significant slowdowns during peak holiday seasons, resulting in a 30% increase in failed requests and a 20% loss in sales. I’ve seen it firsthand on my own projects: when users encounter slow loading times, they’re more likely to abandon their carts or leave the site altogether.

If you’re using Filament for building custom admin panels and experiencing similar issues, this tutorial is for you. By the end of it, you’ll build a high-performance Filament application with Server-Side Rendering (SSR) enabled, complete with optimized resource caching and preloading via Laravel’s built-in features. You’ll also learn how to use code splitting and lazy loading to further improve performance, as well as monitor and analyze your SSR setup for maximum efficiency.

Understanding Server-Side Rendering with Filament

Server-side rendering (SSR) has revolutionized the way we build and deliver dynamic web applications. By leveraging SSR, developers can pre-render HTML pages on the server, significantly improving page load times, SEO, and overall user experience.

Filament, a popular Laravel package for building admin dashboards, offers built-in support for SSR out of the box. To take advantage of this feature, make sure you’re running at least Filament 4.x with Laravel 11 or higher. You can verify your setup by checking the config/filament.php file:

// config/filament.php

'features' => [
    'server_side_rendering' => true,
],

If this setting is enabled, you’re ready to dive into the world of SSR with Filament.

To understand how SSR works in Filament, imagine a scenario where you have an admin dashboard with multiple pages. When a user requests one of these pages, Filament’s server-side rendering engine kicks in and generates the HTML content on the fly. This pre-rendered HTML is then sent to the client, reducing the load time significantly.

This approach has several benefits, including improved SEO (since search engines can crawl rendered HTML), faster page loads, and enhanced accessibility features like screen reader support. In the next sections, we’ll explore how to configure Filament for SSR, optimize resource caching, and more.

Benefits of Using SSR with Filament: A Real-World Example

To demonstrate the benefits of using Server-Side Rendering (SSR) with Filament, let’s consider a real-world example.

Suppose we’re building an e-commerce platform that showcases products in various categories. Our application receives heavy traffic during sales events and product launches. We want to improve page loading times and ensure seamless user experiences.

Here’s what our ResourcesController might look like before implementing SSR:

// app/Http/Controllers/ResourcesController.php

namespace App\Http\Controllers;

use Filament\Pages\Actions\VisitPageAction;
use Illuminate\Support\Facades\View;

class ResourcesController extends Controller
{
    public function index()
    {
        $products = Product::all();

        return View::make('resources.index')
            ->with(compact('products'));
    }
}

However, with SSR enabled, we can render the entire page on the server-side before sending it to the client. This eliminates unnecessary requests and reduces load times:

// app/Http/Controllers/ResourcesController.php

namespace App\Http\Controllers;

use Filament\Pages\Actions\VisitPageAction;
use Illuminate\Support\Facades\View;

class ResourcesController extends Controller
{
    public function index()
    {
        $products = Product::all();

        return View::make('resources.index')
            ->with(compact('products'))
            ->render();
    }
}

By leveraging SSR with Filament, we can significantly improve the performance of our application and enhance the overall user experience. In the next section, we’ll dive into setting up Filament for Server-Side Rendering.

Setting Up Filament for SSR: Enabling the Feature

To start optimizing Filament resources with server-side rendering (SSR), you’ll need to enable the feature in your Laravel application. This involves installing a few packages and configuring your environment.

First, run the following command in your terminal to install the required packages:

composer require laravel/filament-ssr

This will add the laravel/filament-ssr package to your project, which provides the necessary functionality for enabling SSR with Filament.

Next, publish the configuration file by running the following command:

php artisan vendor:publish --provider="Filament\ServerSideRendering\Providers\FilamentSsrServiceProvider"

This will create a new directory config/filament-ssr in your project root containing various configuration files. You’ll need to update the filament-ssr.php file to enable SSR for specific resources.

For example, you can add the following code to the enabled_resources array in the filament-ssr.php file:

'enabled_resources' => [
    'adminlte::page.header',
    'adminlte::page.footer',
],

This will enable server-side rendering for the header and footer pages in your Filament admin interface.

Once you’ve made these changes, restart your Laravel application or run composer dump-autoload to apply the updates. You should now be able to see the SSR feature enabled for the specified resources in your Filament admin interface.

Configuring Resource Caching and Preloading in Laravel

To get the most out of Filament’s Server-Side Rendering (SSR) feature, you’ll want to configure resource caching and preloading in your Laravel application.

First, ensure that you’re using a caching mechanism like Redis or Memcached. If not, install one by running composer require redis/phpredis or composer require league/memcached.

Next, add the following configuration to your config/caching.php file:

'cache' => [
    'store' => env('CACHE_DRIVER', 'redis'),
],

Then, configure the cache store in your config/database.php file:

'redis' => [
    'client' => 'predis',
    'options' => [
        'cluster' => '127.0.0.1:6379',
    ],
],

To enable preloading of resources, add the following middleware to your app/Http/Middleware directory:

// app/Http/Middleware/PreloadResources.php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Cache;

class PreloadResources
{
    public function handle(Request $request, Closure $next)
    {
        // Get the current route name
        $routeName = $request->route()->getName();

        // Cache preloaded resources for 1 hour
        Cache::remember($routeName . '.resources', 3600, function () use ($routeName) {
            return \Filament\Pages\Actions\PreloadResources::preCache($routeName);
        });

        return $next($request);
    }
}

Finally, add the middleware to your $middleware array in app/Providers/AppServiceProvider.php:

// app/Providers/AppServiceProvider.php

namespace App\Providers;

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Cache;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Route::middleware(['preload.resources'])->group(function () {
            // Your routes here...
        });
    }
}

This configuration will enable resource caching and preloading for your Filament resources, improving the overall performance of your application.

Optimizing Filament Resources with Code Splitting and Lazy Loading

To further improve the performance of your SSR application, we can leverage code splitting and lazy loading techniques to optimize filament resources.

Code Splitting with Laravel Mix

You can use Laravel Mix’s splitChunks configuration option to split large chunks of code into smaller modules. This will prevent unnecessary bundles from being loaded on every page request.

// resources/js/app.js
import 'alpinejs';

import { createApp } from './app';

createApp().mount('#app');
// webpack.mix.js
mix.webpackConfig({
    optimization: {
        splitChunks: {
            chunks: 'all',
            minSize: 10000,
            minChunks: 1,
            maxAsyncRequests: 30,
            maxInitialRequests: Infinity,
            enforceSizeThreshold: 50000,
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor',
                    chunks: 'all',
                },
            },
        },
    },
});

Lazy Loading with Filament’s Resource Components

By wrapping your filament resources in a lazy component, you can delay loading until the component is actually rendered. This is particularly useful for pages with a high number of resources.

// resources/js/components/LazyResource.vue
<template>
    <div v-if="loaded">
        <!-- your resource content here -->
    </div>
</template>

<script>
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
    data() {
        return {
            loaded: false,
        };
    },
});

By implementing code splitting and lazy loading, you can significantly reduce the initial payload size of your application, resulting in improved page load times. This optimization will also help with SEO rankings, as search engines are more likely to index pages that load quickly.

Monitoring and Analyzing Performance Improvements with Filament SSR

To monitor and analyze performance improvements with Filament Server-Side Rendering (SSR), you’ll need a few tools in your arsenal. The most critical one is a web analytics platform like Google Analytics or Matomo, which can help you track page load times, bounce rates, and other key metrics.

Setting Up Web Performance Monitoring

First, enable performance monitoring in your Laravel project by installing the laravel/sail package via Composer:

composer require laravel/sail

Then, update your .env file to include the Sail configuration:

SAIL_PORT=8080
SAIL_API_TOKEN=your_token_here

Visualizing Performance Data

Once you have performance data flowing in, it’s essential to visualize it. I recommend using a tool like Chart.js to create easy-to-understand charts and graphs.

Here’s an example of how to display page load times over time using Chart.js:

// app/Http/Controllers/HomeController.php

use Illuminate\Support\Facades\DB;
use App\Models\PageView;

public function index()
{
    $data = PageView::selectRaw('created_at, avg(load_time) as average_load_time')
        ->whereMonth('created_at', now()->month)
        ->get();

    return view('home', compact('data'));
}
// resources/views/home.blade.php

<h1>Page Load Times Over Time</h1>

<canvas id="chart"></canvas>

<script>
    const ctx = document.getElementById('chart').getContext('2d');
    const chart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: {!! $data->pluck('created_at')->toArray() !!},
            datasets: [{
                label: 'Average Load Time (ms)',
                data: {!! $data->pluck('average_load_time')->toArray() !!},
                backgroundColor: 'rgba(255, 99, 132, 0.2)',
                borderColor: 'rgba(255, 99, 132, 1)',
                borderWidth: 1
            }]
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            }
        }
    });
</script>

By analyzing your performance data, you’ll be able to pinpoint areas that need improvement and make informed decisions about how to optimize your Filament SSR setup.

Tuning SSR Cache Expiration and Bypassing for Dynamic Content

When it comes to Server-Side Rendering (SSR) with Filament, cache expiration plays a crucial role in ensuring that your application’s resources are up-to-date. By default, Filament uses Laravel’s built-in caching mechanisms, which have a TTL (time-to-live) setting that determines how long the cached content remains valid.

To fine-tune this behavior and ensure optimal performance, you can adjust the cache expiration settings for each resource. For example, if your application has a dashboard page with infrequently updated content, you might set a longer TTL to reduce cache invalidation overhead:

// config/resources.php

'resources' => [
    'cache_ttl' => 60 * 60 * 24 * 7, // Cache expires in one week
],

However, if your application has dynamic content that requires frequent updates, you’ll want to bypass the cache expiration altogether. You can achieve this by using a conditional statement within your ResourceController:

// app/Http/Resources/ResourceController.php

public function show(Request $request)
{
    // Bypass caching for dynamic content with 'skip-cache' query parameter
    if ($request->query('skip-cache')) {
        return view('resource', ['data' => $this->getResource()]);
    }

    // Use cached response otherwise
    return cache()->remember('resource:cache', 60 * 60, function () {
        return view('resource', ['data' => $this->getResource()]);
    });
}

By implementing these techniques, you can strike the perfect balance between performance and content freshness in your Filament application. This concludes our SSR optimization guide – by following the steps outlined here, you’ll be well on your way to a lightning-fast and dynamic user experience.

Best Practices for Implementing SSR with Filament in Production Environments

When implementing Server-Side Rendering (SSR) with Filament in production environments, there are several best practices to follow to ensure optimal performance and reliability.

Use a Load Balancer or CDN

To distribute traffic efficiently and reduce the load on your application server, consider using a load balancer or Content Delivery Network (CDN). This will help improve response times and prevent bottlenecks. For example, you can use NGINX as a reverse proxy to route requests from the load balancer to your Laravel application.

// nginx.conf
http {
    ...
    upstream laravel-app {
        server localhost:8000;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            try_files $uri /index.php$is_args$args;
        }
    }
}

Monitor and Log SSR Performance

Monitor your application’s performance with tools like Prometheus, Grafana, or New Relic. Set up logging to track errors, slow requests, and caching hits/misses. This will help you identify areas for improvement and fine-tune your SSR configuration.

// .env
LOG_CHANNEL=single
LOG_LEVEL=debug

// config/logging.php
'channels' => [
    'single' => [
        'driver' => 'stack',
        'levels' => ['debug'],
        'handlers' => [
            'daily' => [
                'driver' => 'rotatingfile',
                'path' => storage_path('logs/laravel.log'),
                'level' => 'debug',
                'max-days' => 7,
            ],
        ],
    ],
],

Implementing SSR with Filament requires careful planning and execution. By following these best practices, you’ll be well on your way to optimizing your application’s performance in production environments.

With proper setup and tuning, Server-Side Rendering can significantly improve the user experience for your application users.

Frequently Asked Questions

What is Server-Side Rendering (SSR) and how does it improve performance?

Server-side rendering pre-renders HTML pages on the server, improving page load times, SEO, and user experience.

I’m using Filament 3.x – can I still use SSR?

No, you need at least Filament 4.x with Laravel 11 or higher to take advantage of built-in SSR support.

What’s the difference between code splitting and lazy loading in SSR?

Code splitting breaks down large files into smaller ones, while lazy loading loads resources only when needed, reducing initial load times.

I’ve enabled SSR in Filament but still experience slow page loads – what could be the issue?

Common issues include misconfigured resource caching or inefficient database queries. Check your server logs and database performance for potential bottlenecks.

Should I use SSR with Filament or a headless CMS like Next.js?

SSR with Filament is ideal for custom admin panels, while headless CMSes are better suited for complex frontend applications. Choose the approach that best fits your project’s needs.

Comments

comments