Inertia’s SSR server (which runs in a NodeJS process) is pretty quick, but sometimes you’re trying to shave every millisecond possible off your render time. A common question we’ve encountered is whether you can simply cache the server response and speed things up even more. Good news: you can.
What makes this possible is a line in the ServiceProvider in the Inertia package inside the register
method:
$this->app->bind(Gateway::class, HttpGateway::class);
This binding is telling your app that when the Gateway
contract is called, use the HttpGateway
class. You can read up on the Laravel service container if you want to learn more about this behaviour, but for now, all you need to know is that you can override this binding and provide your own class to handle Inertia SSR HTTP requests. So let’s create our custom class.
Creating our custom implementation
First, let’s go to our app\Http
directory and create a new file called InertiaHttpGateway.php
. This is going to be based on the original Inertia file you can find at vendor/inertiajs/inertia-laravel/src/Ssr/HttpGateway.php
in your project. We only need to alter a few lines inside our try
block:
1<?php2
3namespace App\Http;4
5use Exception;6use Inertia\Ssr\Gateway;7use Inertia\Ssr\Response;8use Inertia\Ssr\BundleDetector;9use Illuminate\Support\Facades\Http;10use Illuminate\Support\Facades\Cache;11
12class InertiaHttpGateway implements Gateway13{14 /**15 * Dispatch the Inertia page to the Server Side Rendering engine.16 */17 public function dispatch(array $page): ?Response18 {19 if (!config('inertia.ssr.enabled', true) || !(new BundleDetector())->detect()) {20 return null;21 }22
23 $url = str_replace('/render', '', config('inertia.ssr.url', 'http://127.0.0.1:13714')) . '/render';24
25 try {26 $cacheKey = md5(serialize($page));27 $response = Cache::remember($cacheKey, 60, fn () => Http::post($url, $page)->throw()->json());28 } catch (Exception $e) {29 return null;30 }31
32 if (is_null($response)) {33 return null;34 }35
36 return new Response(37 implode("\n", $response['head']),38 $response['body']39 );40 }41}42
All we’re doing here is creating a hash of our $page
props (see line 26). This enables us to create a new cache entry for every individual request. You may want to check if a user is logged in here too and skip the cache layer (since a render with user data is likely highly variable) but for this example, we’ll keep it simple.
Next we use Laravel’s built-in caching facade to remember the response to the request (line 27). If we get the exact same request again, we can use the exact same response.
Binding our class to the service container
Finally, we need to tell our Laravel app to use our custom implementation instead of the default Inertia one. So find the register
function in your AppServiceProvider
and add the following line:
class AppServiceProvider extends ServiceProvider{ /** * Register any application services. * * @return void */ public function register() { $this->app->bind(Gateway::class, InertiaHttpGateway::class); }
}
Et voilla. Because we have our own class implementation, we can add logic to the caching layer precisely tailored to our needs. We may want to cache some pages longer than others, or only cache specific pages. Anything is possible.