💡 This post will serve as a collection of ongoing notes.
💡 Read part 1 of this series on simpler shared runed state, derived state and more.
General Learnings
From studying the migration guide and current GitHub issues for Svelte / Svelte 5 we learn that:
-
actionsstill exist (e.g. for event modifiers) -
tickstill exists -
eventhandling is now more „native“- write handler functions that accept an
eventobject, and handle as intended in the Event API - this is even more important for event modifiers that relied on syntactic sugar like
event|preventDefault
<script> const handleEvent(e) => e.preventDefault() </script> <button onclick={handleEvent} /> - write handler functions that accept an
Notes on JSDoc Types & IntelliSense
- Reminder: there is a component annotation / documentation pattern with
@component
- unlike JSDoc typing, it must be within the markup / HTML section
- but it seems you can just put it at the top of the file before the very first
<script>tag:
<!--
@component
@slot default - The map container with image, vector, and text annotations
-->
<script>
import { getContext } from 'svelte'
import { fade } from 'svelte/transition'
// ...
</script>
<div>your markup</div>
-
TBC: if types can be defined / imported / exported here instead of within
-
JSDoctypes can be recycled - exported / imported - when defined in<script module />(Maintainer comment)- define in one component
// $lib/ComponentA.svelte
<script module>
/** @typedef {"myType"} MyType */
</script>
<script>
// your logic
</script>
- import and recycle in another component
// $lib/ComponentB.svelte
<script>
/** @import { MyType } from "$lib/ComponentA.svelte" */
/**
* @param {MyType} x
*/
function stuff(x) {
}
</script>
- you can even import in utility libraries /
.jsfiles (that probably includes.svelte.jsfiles)
// $utils/+utils.js
/** @import { MyType } from "$lib/ComponentA.svelte" */
/**
* @param {MyType} x
*/
function stuff(x) {
}
Notes on $effect
$effectandonMountare not the sameonMount()is only run when the component is mounted.$effectis run when- the component is mounted
- when any of the tracked dependencies are changed
$effect.preruns before changes are applied to the DOM
observation: it’s unclear ifonMountis supposed to be deprecated or not (probably a Svelte 6 thing)$effectis not encouraged (Docs, GitHub Issue by Core Maintainer, Tweet by Core Maintainer)$effectdoesn’t run on the server$deriveddoes
$effect.once()doesn’t exist yet (svelte@5.1.2), but can be simulated with
import { untrack } from 'svelte';
$effect(() => {
untrack(async () => {
await fetch("/");
})
});
asyncwithin$effectis discouraged (Maintainer)asyncwithinonMountis discouraged (example)
Notes on $props()
- to only extract specific properties and collect the rest
let { foo, bar, ...rest } = $props();
- to collect / preserve all properties: don’t destructure
let props = $props();
- pass to child
<Button {...rest} />
<Button {...props} />
// Button.svelte
<script>
let props = $props();
</script>
<button {...props}>
click me
</button>
$bindablecan have a default
let { item = $bindable("default") } = $props()
Reactive Built-Ins: Set, Map, Date, URL, URLSearchParams with Svelte 5
- these so called “built-ins” aren’t reactive off the shelf
- instead, there’s a collection of reactive “built-ins” in
svelte/reactivity(Docs)
💡 as of svelte@5.1.3:
SvelteDateSvelteMapSvelteSetSvelteURLSvelteURLSearchParams
TODO / WIP: Standalone modules / UMD / ES6 / IIFE with Vite & Svelte 5
💡 if you don’t know what this means, what this Svelte Summit Talk by Jesse Skinner: https://www.youtube.com/watch?v=uWxkaDdqfpI
TL;DR: Svelte is a compiler; you can compile Svelte components to regular standalone JavaScript modules and mount them wherever you can run JavaScript. You can even pass functions as props and expose component methods to the mounting scope.
- in Svelte 5 components are functions - before, they were Classes (e.g.
new SvelteComponent()) - mount with either
mountorhydratehydratepicks up server-rendered HTML- you can preserve the CSS with a compiler option:
css: 'injected' - options now include an
events: {eventType: callback()}property tbc:$statemight be used in the instantiating scope- only in .svelte / .svelte.js
- there’s
unmountfor destroying - see working example for a server-side-rendered Svelte component using Bun and the Svelte compiler: https://github.com/fubits1/bun-svelte-ssr
What I don’t understand yet
$state.snapshot
💡 why and how and what for?
$effect( () => {
// Get a snapshot :
const data = $state.snapshot(config);
// Save data
// ...
console.log(data);
});
- level or granularity of shared / bindable reactivity (example GitHub issue)
- migration guide: „accessors option is ignored“
“Setting the accessors option to true makes properties of a component directly accessible on the component instance. In runes mode, properties are never accessible on the component instance. You can use component exports instead if you need to expose them.” (Svelte 5 Migration Guide)
💡 to be continued