Jerome Paulos

How to use Svelte with Inertia.js v1.0

The big new release of Inertia comes with server-side rendering support for Svelte, among other improvements. However, Svelte is a second-class citizen in the documentation. There are first-party versions of Laravel Breeze written in Vue and React that make it easy to get up and running with Inertia. Svelte users are not so lucky.

Installing Inertia

Start by installing Inertia’s Laravel adapter if you haven’t already.

composer require inertiajs/inertia-laravel

Create your app’s base template at resources/views/app.blade.php.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
    @vite('resources/js/app.js')
    @inertiaHead
</head>

<body>
    @inertia
</body>

</html>

Publish Inertia’s middleware.

php artisan inertia:middleware

Add the middleware as the last item in the the web middleware group in app/Http/Kernel.php.

// Add to the end of the array
'web' => [
    \App\Http\Middleware\HandleInertiaRequests::class,
],

Installing Svelte

Install a few packages, including Svelte itself (this isn’t mentioned at all in the documentation).

npm i -D svelte @sveltejs/vite-plugin-svelte @inertiajs/svelte

Create the resources/js/app.js file required by Inertia.

import { createInertiaApp } from '@inertiajs/svelte';

createInertiaApp({
    resolve: name => {
        const pages = import.meta.glob('./Pages/**/*.svelte', { eager: true });
        return pages[`./Pages/${name}.svelte`];
    },
    setup({ el, App, props }) {
        new App({ target: el, props });
    }
});

Make the following changes to vite.config.js:

  1. Change laravel( to laravel.default(
  2. Add svelte() to the array, after Laravel

Add "type": "module" to your package.json file

{
    "private": true,
    "type": "module",
    "scripts": {...},
    "devDependencies": {...}
}

If you don’t make this change, you might encounter this error:

Failed to resolve entry for package “@sveltejs/vite-plugin-svelte”. The package may have incorrect main/module/exports specified in its package.json: No known conditions for ”.” entry in “@sveltejs/vite-plugin-svelte” package

Bonus: Adding Tailwind

Add @vite('resources/css/app.css') to app.blade.php.

Install Tailwind and its dependencies.

npm i -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Edit tailwind.config.cjs.

/** @type {import('tailwindcss').Config} */
 module.exports = {
     content: [
         './resources/**/*.{php,js,svelte}'
     ],
     theme: {
         extend: {}
     },
     plugins: []
 }

Add the three Tailwind directives to resources/css/app.css.

@tailwind base;
@tailwind components;
@tailwind utilities;

Bonus: Adding Typescript

Install a few packages.

npm i -D @tsconfig/svelte svelte-preprocess typescript

Edit vite.config.js and add this import.

import * as sveltePreprocess from 'svelte-preprocess';

Add the following object as the first parameter to svelte().

{
    preprocess: sveltePreprocess.default()
}

Create tsconfig.json with the following contents.

{
    "extends": "@tsconfig/svelte/tsconfig.json",
    "include": [
        "resources/js/**/*"
    ],
    "exclude": [
        "node_modules/*",
        "public/*"
    ]
}

Now, you can add lang="ts" to any Svelte <script> tag.