Why you should consider Svelte for your next Laravel project.

Svelte is still thought of by some as the new kid on the block in the javascript world, but it's got some really endearing features, is stable and mature, and feels light and nimble to use.

I thought it would be criminal of me not to take you on a little tour of some of my favourite parts.

Most of the things i'm going to talk about are available if you're using Svelte on it's own, through InertiaJS or in SvelteKit, which is sort of like Next.js for Svelte.

It's fast! (and small)

Svelte isn't like React or Vue - it's a compiled framework, while React is an interpreted framework. This means that Svelte converts your code into optimized vanilla JavaScript at build time, rather than relying on the browser to interpret and execute it at runtime. This can make Svelte apps faster and more efficient, particularly on lower-end devices.

Also, it's small, this article outlines some of the differences in bundle size:

Svelte’s .gzip version has a size of 1.6 kilobytes. React.gzip, when combined with ReactDOM, has a total size of 42.2 kilobytes. The smaller bundle size of Svelte ensures faster loading speeds, better responsiveness, and lower bandwidth costs.

It's syntax is friendlier (proper if/else statements!)

If you're a JSX convert that's absolutely fine, but for me, i like writing HTML! And you know what I love the MOST about Svelte? The fact it has proper if/else blocks unlike other frameworks - a nice benefit of it being a compiled framework.

For example, in React you might see something like:


_10
<div>
_10
{name && (<p>{name}</p>)}
_10
{!name && (<p>Name Unknown</p>)}
_10
</div>

That's hard to read and... it just looks ugly. Here's Vue (which is actually way nicer & cleaner anyway):


_10
<div v-if="name">{{ name }}</div>
_10
<div v-else>No Name</div>

But here's Svelte's version:


_10
{#if name}
_10
My name is {name}
_10
{:else}
_10
This user has no name
_10
{/if}

Easy to read, parse, and clearly defined - they're conditionals like you would just use in normal JS or PHP.

Your 'state' is just variables 🤷‍♂️

You define your 'state' by declaring variables and...using them.


_18
<script>
_18
_18
const shouldShowWelcome = false;
_18
_18
const name = "Dave";
_18
_18
const showWelcome = () => {
_18
shouldShowWelcome = true;
_18
}
_18
_18
</script>
_18
_18
{#if shouldShowWelcome}
_18
<!-- Hi there Dave, how are you today? -->
_18
<p>Hi there {name}, how are you today?</p>
_18
{/if}
_18
_18
<button on:click={showWelcome}>Show Welcome</button>

'Props' are just variables too

You access props in Svelte by simply declaring them as exported member variables!

With a component like this:


_10
<TitleComponent title={'Hello There!'} />

You can access (and set a default), simply by writing your component like this:

TitleComponent.svelte
Copy

_10
<script>
_10
export let title = undefined;
_10
</script>
_10
_10
{#if title}
_10
<h1>{title}</h1>
_10
{/if}

Or set a default and get rid of the {#if}:

TitleComponent.svelte
Copy

_10
<script>
_10
export let title = "Welcome to my blog";
_10
</script>
_10
_10
<h1>{title}</h1>

Ooh look, there's that nice {#if} block again too 😉

Watch any variable or expression easily with Reactive Declarations

The $: statement in Svelte takes some getting used to - but it is IMMENSELY powerful. You use it to run expressions or functions that need to be re-ran when something changes.

For example:

Welcome.svelte
Copy

_14
<script>
_14
_14
// These are passed as props.
_14
export let firstName = '';
_14
export let lastName = '';
_14
_14
// Declare the var that will be filled in by the $: statement.
_14
let fullName;
_14
_14
// Build a full name from the two parts.
_14
$: fullName = firstName + ' ' + lastName;
_14
</script>
_14
_14
Hi there {fullName}!

This expression will now automatically re-run if firstName or lastName change!

There are some more superb examples in the offical tutorial.

It comes with transitions built in

For simple transitions like fades are included, and there are tonnes of ways to customise transitions including a JS options API and the ability to use CSS too.


_10
<script>
_10
import { fade } from 'svelte/transition';
_10
let visible = true;
_10
</script>
_10
_10
<p transition:fade>This block fades in and out!</p>

See the transitions section of the tutorial for a bigger overview.

Deal with promises in your templates with #await blocks:

Loading something in using a fetch() request or AJAX call using something like axios? let the template deal with it's state easily:


_20
<script>
_20
async function getData() {
_20
const res await fetch(`/my-api/endpoint`);
_20
const json = await res.json();
_20
if (res.ok) {
_20
return json;
_20
} else {
_20
throw new Error(json);
_20
}
_20
}
_20
let myDataCall = getData();
_20
</script>
_20
_20
{#await myDataCall}
_20
<p>...waiting</p>
_20
{:then json}
_20
Hi there {json.name}, how are you?
_20
{:catch error}
_20
<p style="color: red">{error.message}</p>
_20
{/await}

And A few other quick things:

Conditional classes are easy:


_10
<div class="first second" class:third={booleanCondition} class:fourth={!booleanCondition}>

The lifecycle hooks are well named and easy to use:


_11
<script>
_11
import {onMount, beforeUpdate, afterUpdate, onDestroy} from 'svelte';
_11
_11
onMount(() => {})
_11
_11
beforeUpdate(() => {});
_11
_11
afterUpdate(() => {});
_11
_11
onDestroy(() => {});
_11
</script>

Emitting custom events is super easy:


_10
<script>
_10
import {createEventDispatcher} from 'svelte';
_10
const emit = createEventDispatcher();
_10
emit('myEvent', {some:'Data',goes:'here'});
_10
</script>

and listening to them is easy too:


_10
<MyComponent on:myEvent={(event) => { let data = event.detail }}>

Binding an input to a variable is super easy:


_10
<script>
_10
let name = undefined;
_10
</script>
_10
_10
<input type="text" bind:value={name}>

So is binding regular events:


_10
<a on:click|preventDefault={() => { alert("clicked") }}>Click me!</a>

Fragments are super useful for when you don't want to add any additional markup for a slot:


_10
<Header>
_10
<svelte:fragment slot="title">
_10
Your Page Title Here
_10
</svelte:fragment>
_10
</Header>

You can also render HTML tag names dynamically using <svelte:element>:

Button.svelte
Copy

_10
<script>
_10
// If a URL is provided, we want this to be an anchor tag.
_10
// But if the URL is not provided, use a HTML button tag instead.
_10
export let url = undefined;
_10
export let text = "Click Me";
_10
</script>
_10
_10
<svelte:element this={url === undefined ? 'button' : 'a'} href={url}>{text}</svelte:element>