Reading List
The most recent articles from a list of feeds I subscribe to.
Dan Abramov: The two Reacts
Frontend frameworks often use the mental modal that a component (or entire UI) is the result of running state through a pure function. Dan Abromov shares his thoughts on the current state of React with server components.
UI = f(data)(state)
Here's how I interpret it: in the mental model we're used to, a component is a pure function that returns UI based on its props. In this case, a Greeter is rendered on the client.
function Greeter(props) { return <p>Hello, {props.name}!</p>;}
Say we have a server component that know who needs to be greeted before the code hits the client. In that case, the name will come from data available on the server.
function Greeter(data) { return function () { return <p>Hello, {data.name}!</p>; }}
The outer function is executed on the server, the inner on the client.
The true power lies in mixing and matching the paradigms. Say you want to read a translation string on the server, and greet a name on the client.
function Greeter(data) { return function (props) { return <p>{data.translations.hello}, {props.name}!</p>; }}
Feedback
Before I launched Svelte by Example, I called for early access testers in this newsletter. I don't ask for feedback often, I had to push myself to do this.
Sometimes I'm scared of receiving feedback that I'll agree with, but would push back the release when I want to get it out. Sometimes I'm scared of receiving feedback that could invalidate the entire idea. Sometimes I know there are problems but hope they'll magically go away if I ignore them, feedback might resurface them. Sometimes I'm overconfident and don't think it's worth getting another opinion.
No good excuse to be found. These are fears, and it's worth getting over them. Because if any of them are rooted in truth, they'll com back and haunt me rather sooner than later.
A few people responded to my request (thank you!), and it quickly became clear the ask was worth it. The first version of Svelte by Example became way better because of it. The examples became more consistent, the design improved, a bunch of typos were edited out. I didn't process all feedback. Sometimes it doesn't match what you have in mind, and that's fine.
I've learned my lesson: time to get over myself and ask for feedback whenever I can.
Svelte 5 preview review
The Svelte team set up a miniature documentation site highlighting the new features coming to Svelte 5. Here's a quick review of my three favorites: runes, events, and snippets.
Runes
The star of the release will be runes. Currently, Svelte uses existing language features like export and labels for its reactive features.
<script> // A prop export let name; // A reactive statement $: console.log(name);</script> <p>Hello, {{ name }}!</p>
Svelte 5 is a departure from this setup, and has more explicit "runes" instead. Runes are function calls that get transformed by the compiler, and can be recognized by their $ prefix.
<script> // A prop let { name } = $props(); // A reactive statement $effect(() => { console.log(name); });</script> <p>Hello, {{ name }}!</p>
I personally liked the (mis)use of existing JavaScript syntax for reactivity. However, it did come with weird edge cases which runes will iron out, and having one "system" for all reactivity features does make Svelte look more consistent. So all in all I understand why the team decided to pursue this direction, and I'm looking forward to trying it out.
Events
Event handles in Svelte have previously been prefixed with on:. This prefix has been removed and replaced with a syntax that mirrors props.
<!-- Svelte 4 --><button on:click={() => …}> …</button> <!-- Svelte 5 --><button onclick={() => …}> …</button>
This makes component events more straightforward too as events are handled by callback props.
<!-- Svelte 4 --><Todo on:complete={() => …} /> <!-- Svelte 5 --><Todo complete={() => …} /> <!-- Todo.svelte --><script> let { complete } = $props();</script> <input type="checkbox" oninput={complete} />
This opens up a world of possibilities, as you can now dynamically spread props and events on a component, which is something I sorely miss coming from React.
We often use form objects in projects that hold form state, and have methods to bind form values, handlers, and errors on a field component in a type-safe way. This is finally possible in Svelte.
<script> let form = createForm({ name: 'Sebastian' });</script> <TextField {...form.field('name')} />
Snippets
This is an interesting one I haven't seen in other frameworks yet, but solves a problem I've had in other templating languages. Snippets allow you to reuse an HTML snippet within the same component file.
Here's an example that would be relevant to my blog: I have a PostHeader component that's used on the index page and post page. On the index page, the title should be wrapped in an h2 tag, on the post page in an h1.
{#if onPostPage} <h1><a href="{{ permalink }}">{{ title }}</a><h1>{:else} <h2><a href="{{ permalink }}">{{ title }}</a><h2>{/if}
This is a small example, but grows increasibly difficult to maintain as the inner contents of the dynamic tag grows. In Svelte 5, you can extract the inner contents to a snippet.
{#snippet title()} <a href="{{ permalink }}">{{ title }}</a>{/snippet} {#if onPostPage} <h1>{@render title()}<h1>{:else} <h2>{@render title()}<h2>{/if}
Now there's no more repetition of the snippet contents.
There's more on the horizon for Svelte 5, read through the preview documentation for an introduction to all new features. Or if you're new to Svelte and want an introduction, check out Svelte by Example. (Which I'll update for Svelte 5 when it's released!)
How not to update every package in existence, break your local environment, and spend the afternoon dealing with things you did not want to deal with when installing a package with Homebrew
Friendly reminder that you can disable Homebrew's default auto update behaviour with HOMEBREW_NO_AUTO_UPDATE=1.
HOMEBREW_NO_AUTO_UPDATE=1 brew install git-secret
If you want to set and forget the setting, add it to your ~/.bashrc or ~/.zshrc.
export HOMEBREW_NO_AUTO_UPDATE=1
The CSS scroll-margin property
Last week I remembered the scroll-margin property existed.
I was adding anchors to the headings of a page so visitors can directly link to a section. However, when that link was visited, the heading was glued against the top of the viewport. I prefer some margin between the browser chrome and the text to let it breath.
There's a CSS property for that: scroll-margin. It does nothing in most cases, but when you visit a URL that points to an anchor on the page, it will offset the element from the viewport.
h2 { scroll-margin-top: 1rem;}
You can read all about scroll-margin in the MDN docs.