«

How to add SSR to an InertiaJS Laravel project

Written by Jorge on 
5 minute read
#Laravel#Forge#InertiaJS#SSR

In this post, I’m going to show you how I add Server-side rendering to this website.

I’m still not sure if I will keep using InertiaJS, but I thought having my site SSR enabled would be a great addition to make it easier for search engines to index my site. So let’s get started.

To begin with please consider that I’m currently using Laravel v9.45.1 with InertiaJS v1.0.0.

Introduction

Server-side rendering (SSR) is a crucial technique in modern web development that involves rendering web pages on the server before sending the content to the browser. This approach helps to enhance website speed and performance, delivering a seamless and efficient user experience.

By rendering content on the server-side, web pages can be loaded and displayed faster, which is particularly essential for high-traffic websites and those with a significant amount of data. Moreover, SSR is an effective tool for optimizing search engine rankings, as it provides search engines with more complete and accessible content.

Overall, SSR is a valuable technique that can help businesses build a more efficient and effective web presence.

Install dependencies.

Accordingly to the documentation, this is only necessary for the Vue adapters.

npm install @vue/server-renderer

Also, make sure you have the latest version of the Inertia Laravel adapter installed:

composer require inertiajs/inertia-laravel

Add the server entry-point

Next, I created a resources/js/ssr.js file with the following content:

import { createInertiaApp } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import { renderToString } from '@vue/server-renderer'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';
import { createSSRApp, h } from 'vue'

const appName = 'Portfolio';

createServer(page =>
    createInertiaApp({
        page,
        render: renderToString,
        title: (title) => `${title} - ${appName}`,
        resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
        setup({ App, props, plugin }) {
            return createSSRApp({ render: () => h(App, props) })
                .use(plugin)
                .use(ZiggyVue, {
                    ...page.props.ziggy,
                    location: new URL(page.props.ziggy.location),
                });
        },
    }),
)

I used the resources/js/app.js as a reference, as you also need to add to that file any plugin or custom mixins that your app needs. As my site is very small it doesn’t have too much difference from the app.js file.

Here’s my app.js file just for reference:

import './bootstrap';
import '../css/app.css';

import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';

const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        return createApp({ render: () => h(App, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .mount(el);
    },
    progress: {
        color: '#4B5563',
    },
});

Setup Vite

Next, I updated my vite configuration. Edit the file vite.config.js and add the ssr property to the Laravel plugin.

export default defineConfig({
    server: detectServerConfig(host),
    plugins: [
        laravel({
            input: ['resources/js/app.js', 'resources/css/filament.css'],
            ssr: 'resources/js/ssr.js',
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

Update npm script

I updated the build script in my package.json file to build the new ssr.js file.

"scripts": {
  "dev": "vite",
  "build": "vite build && vite build --ssr"
},

Laravel Forge

To allow Forge to work with this new setup, I created a new Daemon like this:

Once the Daemon is created it will look like this:

And lastly, I modified the Deploy script of my site to add the restart of the ssr daemon:

And that’s it.

Copyright 2025. All rights reserved