If you’ve recently started working with Svelte/Sveltkit,
you’ve probably come across a few money signs ($
) here and there.
In this post we will get them demystified.
Table of contents
Reactivity
Variables
Reactivity is a fundamental concept in Svelte. It’s the way to have your dependant UI (or a certain variable) stay in sync.
For example, this total
depends on price
and tax
:
let tax = 0.1;
let price = 20;
let total = price * (1 + tax);
// sometime later ...
price = 30;
The total
is declared once and will not keep track of price
and tax
.
In order to keep this derived value in sync with both of them, we can make it “reactive”.
That is by telling Svelte
“Hey, take a special look at this variable and change it whenever one of
the variables it depends on price
and tax
are changed”.
If you’re coming from another front frame, walk in what used to a lot of shenanigans just to make something reactive,
like hooks or signals. But Svelte makes it fairly easy by prepending the line with a $
label.
let tax = 0.1;
let price = 20;
$: total = price * (1 + tax);
// sometime later ...
price = 30;
What’s a label you might ask? Well it’s just an obscure feature of JavaScript and is nothing special to Svelte.
This is an example of how it is typically used in JavaScript without any frameworks:
outer: for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
// do work
if (someCondition) {
break outer;
}
}
}
This example makes use of a label to indicate that the break
on the inner loop should break the outer loop.
The convention is to reserve the one special label $
to have a special meaning to the framework, that is reactivity.
You can name your labels any valid identifier, except $
when working with Svelte.
This explains the joke that every URL is valid JavaScript code, for example:
// this is not a syntax error
https://example.com
This is a line that starts with the https
label and immediately follows it by a comment //
.
Probably useless, but still valid code.
Stores
Stores are a built in mechanism in Svelte to have shared state.
Example:
Declaring a store:
// stores.ts
import { writable } from "svelte/store";
export const count = writable(0);
The using it on some component:
// App.svelte
<script>
import { count } from "./stores.js";
</script>
<h1>The count is {$count}</h1>
The store is writable, meaning other components can change its state, and that will be reflected in App.svelte
thanks to the auto subscription (notice the $
in $count
)
The special syntax takes care of the store life cycle, (subscribing and unsubscribing).
Generated files
Sveltkit makes heavy use of generated code. Whether that’s Typescript types or whole modules.
For example, this is a typical form handler in a src/routes/login/+page.server.ts
import type { Actions } from "./$types";
export const actions = {
default: async event => {
// handle form submission here
},
} satisfies Actions;
The Actions
type here is generated on the fly as our app is being built. There’s nothing special about a $
in the module name.
As per a module with actual values, if you put an API_KEY
in a .env
file, it will be loaded by Sveltkit during development
into $env
and can be imported (in type safe) manner in your code.
import { API_KEY } from "$env/static/private";
This way Typescript is made aware of the environment variables at build time and you can rest assured all of your environment variables are accounted for.
Another example is runtime variables, for example the browser
variable let’s your code know if you’re running on the client or the server.
// in some +page.svelte
import { browser } from "$app/environment";
if (borwser) {
window.setInterval(() => {
console.log("Ticking in the browser");
}, 1000);
}
It’s once again just a convention to denote a special meaning to the module.
If you’re curious where does that generated code live, you can peek at the hidden folder .svelte-kit
.
All of its contents are made available through the magic of Typescript aliases
Conclusion
$
doesn’t have to be intimidating. Remember when jQuery
’s $('body')
sounded like magic?
It turns out it was just a function named $
with some additional properties.
The same goes for Svelte and Sveltkit. The framework made some conventions to simplify your life and provide great DX.
This is probably not a comprehensive list of every $
in Svelte/Sveltkit, but it should give you good idea :)
:wq