Svelte 5+ Wishlist

Svelte 5 is going to be huge, and I have a slightly-opinionated wishlist of features I would love to see in the future of Svelte and SvelteKit.

19 Sep 2023

7 min read

Svelte and SvelteKit are mainstays in my project toolkit. I have personally found that my development speed is much faster than it has been with other frameworks because of its simplicity and speed… and lack of JSX syntax.

Tomorrow (20 Sep., 2023), Svelte 5 will be teased to the world, and the hype train is quickly barreling down the tracks. We’ve gotten wild performance sneak peeks, enticing developer reactions, and even an official announcement page teasing “something magical.” Needless to say, I am pretty stoked.

I have a little list sitting on my computer of things that I would love to see in future Svelte and SvelteKit. These aren’t super fleshed out, nor are they too complex. However, they would make “Svelte: The Language” that much more magical, and “SvelteKit: The Framework” that much more powerful.

Svelte: The Language

{#switch} block

Rich Harris actually discussed this a while back, and came out pretty satisfied after playing around with the potential syntax:

<script lang="ts">"use strict";
let option;
</script>

{#switch option}
  <!-- default -->
	<p>{option} is scooped from a tub.</p>
{:case "chocolate"}
	<p>Chocolate is dispensed from the right nozzle on the soft-serve machine</p>
{:case "vanilla"}
	<p>Vanilla is dispensed from the left nozzle on the soft-serve machine</p>
{/switch}

A switch block would make conditional rendering just a little bit easier to do, and would even be ever-so-slightly more efficient for large workloads (i.e. thousands of instances of a component performing switch operations).

Reactive arrays via mutating functions

Despite Svelte’s overall similarity to JavaScript, it is still a language: it has its own special syntax. I think Svelte has every right to—and should—take advantage of its unique compilation step to allow for reactivity with array-mutating functions.

I have gotten tripped up multiple times because I have tried to react to an array’s mutation… only to see I’ve used arr.push(item) and not arr = [...arr, item]. Why not allow arr.push(item) to compile—behind the scenes—down to the spread syntax? Svelte is a language—if the user wants the length returned from the push() function, Svelte can just provide that when it compiles… while also triggering reactivity.

Of course, I can understand why this may also not be a great idea. The mental model of “reactivity via assignments” is simple to understand, even if a little forget at times.

fine-grained object property reactivity

If I’m not mistaken, I think this has been teased a little bit.

In svelte, reactivity on objects can be confusing because it is based purely on reassignment. If we have some object and update one property, every other property in that object will also be notified.

let obj = {
	x: "hello",
	y: "there",
}

obj.x = "howdy";

// this statement will run as we expect--we updated obj.x
$: console.log(obj.x);

// this will also update because obj.x triggers reactivity for the entire obj variable.
$: console.log(obj.y);

This can be especially frustrating when working with large scale stores, and I personally can’t bring myself to split my larger stores into many little stores that all update on their own with atom-sized chunks of data.

If a variable is comprised of properties, could reactivity instead treat those properties as the smallest form of data upon which to act (instead of the variable itself)?

decouple components from file structure

While this won’t be dropping in Svelte 5, it seems like allowing multiple components within a single file is coming! Given two similar—yet distinct—components, is it unreasonable to hope for a way to group these components in a single file?

Such a feature would ring pretty similar to Nue.js’ component export syntax:

// MediaModals.svelte

<section export="ImageModal" />

<section export="VideoModal" />

// +page.svelte

<script>
  import { VideoModal } from "$lib/MediaModals.svelte"
</script>

<VideoModal />

SvelteKit

Native WebSocket support

There’s an issue on the SvelteKit repo tracking this exact feature, and I am all for it! WebSockets are a huge feature that enable us to create real-time client/server event systems, which can be useful for building something like a custom application webhook.

// +server.ts
import type {RequestHandler, WebSocketRequestHandler} from "./$types";

export const POST: RequestHandler = async (request) => {
	// do stuff on a POST request
};

export const WS: WebSocketRequestHandler = async (request) => {
	// do stuff on a WebSocket message
};

typed fetch() response

SvelteKit has a powerful API endpoint system built right in, and I have found it absolutely invaluable in a number of my projects. Being able to bake in my own server API endpoints without needing to decouple from SvelteKit’s route-based system is very helpful.

Because Svelte itself is a compiled language, there is potential for types to be baked right into fetch requests.

We can write our API endpoints as we normally do:

// /api/post/+server.ts

import { error, json } from '@sveltejs/kit';

export const GET = ({request}) => {
	let availableScoops = {
		vanilla: 3,
		chocolate: 5,
		strawberry: 2,
		rocky_road: 40, // it's not good. stop pretending it's good.
	};

	return json(availableScoops);
};

Then, we can get the resolved or caught types when we fetch this endpoint:

// +page.svelte

{#await fetch("/api/post").then((res) => res.json())}
{:then scoops} // scoops is typed to @type {vanilla: number, chocolate: number, strawberry: number, rocky_road: number}

The biggest problem I see here is how the Svelte compiler would figure out what type to respond with… Our types could be wildly different based on where within a request we return a response.

TypeScript support in HTML content

This is secretly the one I want the most. SvelteKit already ships with fantastic TypeScript support, however HTML in Svelte notable lacks this TypeScript support.

<input type="text" />
<button on:click={(e) => {
  const el: HTMLInputElement = e.currentTarget.previousSiblingElement;
  let y = el.value;
  // ...
}}>Hi</button>

Svelte is a language—it already extends existing HTML features with use: and on: keywords. Why not further extend type safety outside of the typical JavaScript block?

Svelte is awesome

If there is one thing I hate about web development, it’s the never-ending increase in web frameworks. If there is one thing I love about web development, it’s the never-ending increase in web frameworks.

Being able to work with so many incredible tools and compare their strengths and weaknesses is a true freedom within this space—it’s not something I think many areas of development have access to. While it can be cumbersome and annoying to deal with the hype of new tools and frameworks, it is exactly this hype that incentivizes tools I love using—like Svelte and SvelteKit—to never stop getting better.

I am incredibly excited for what Svelte 5 has to offer, and I am 100% certain that what the crew working on Svelte has been cooking up is far better than anything I could think of!