Today’s issue: Abstraction-themed game shows, where Web Components shine, and solving data fetching issues with Tom Bombadil.
Welcome to #334.
Did somebody say runes?
And that’s saying something, considering Svelte prides itself on how it has “changed less than any other major framework since 2019.”
But last week’s v5 release signaled the beginning of a new era, and it looks like Svelte is officially hitting Framework Puberty™️. Let me explain.
How we got here: You’ve probably seen that Khaby Lame meme about how much simpler state management is in Svelte vs React. This is largely because Svelte’s compiler historically did all the heavy lifting for you – so you could just write let count = 0;
and be good to go.
But this compile-time reactivity would often break down as your application got more complex, and as you left the compiler-aided .svelte
files for regular JavaScript files.
So Rich Harris & Co. decided to “rethink reactivity” again, and introduced the world to runes – an explicit mechanism for declaring reactive state.
And after 18 months of work, they finally made their debut in Svelte 5. Let’s take a closer look:
Runes are symbols that use function syntax to influence the Svelte compiler – so to declare a piece of reactive state, you use the $state
rune like so, let count = $state(0);
.
Values are no longer reactive by default, but this change allows you to easily see which values are reactive and which aren’t, no matter how big and complex your app gets.
Runes can be used in .svelte.js
and .svelte.ts
modules, in addition to .svelte
components – so you can create reusable reactive logic using a single mechanism.
Svelte’s new approach to reactivity is powered by the very old idea of using signals for fine-grained reactivity, popularized by Knockout back in 2010.
The difference is that Svelte 5 uses signals as an “under-the-hood implementation detail”, rather than something you interact with directly. This gets you all of the efficiency, with a much nicer DX.
Bottom Line: OG Svelte-heads might not love seeing Svelte become more React-like in its approach, but it’s important to remember that our bodies frameworks change as they grow up – and that’s nothing to be ashamed of.
Mfw my Sentry dashboard tells me everything is broken
You probably know Sentry as the error monitoring tool that pretty much everyone uses – Disney, GitHub, Cloudflare, blah blah blah.
And yeah, that’s true and very cool for them, but we’re more interested in all the off-menu stuff that Sentry has been cooking up lately.
We’re calling this stuff the Sentry Director’s Cut:
Their brand new Open-Source Pledge has already guilted encouraged dozens of companies to commit millions of dollars a month to support OSS maintainers.
Their updated Performance & Profiling suite reduces debugging time by taking a unique, domain-specific approach to traditional APM (see docs) .
Their educational content is genuinely good, like this in-depth guide to debugging microservices & distributed systems, which goes way deeper than you’d expect.
Try out Sentry’s 14-day free Business plan trial – because the platform is great and the company itself is even better.
Their free tier now comes with 10 free Postgres databases, so you can build all your projects on their fully managed Postgres platform that’s designed to help you ship fast.
const products = {
SKU12345: { name: "Laptop", price: 999, discount: 0.1 },
SKU67890: { name: "Phone", price: 499, discount: 0 },
SKU54321: { name: "Tablet", price: 299, discount: 0.05 },
};
function printFormattedProductDetails(products) {
for (const product in products) {
const { name, price, discount } = product;
let finalPrice = price;
if (discount) {
finalPrice = price - price * discount;
}
console.log(
`Product: ${name}, Price: ${finalPrice.toLocaleString("en-US", {
style: "currency",
currency: "USD",
})}`
);
}
}
printFormattedProductDetails(products);
Fernando Cardenas wrote an article called That’s not an abstraction, that’s just a layer of indirection – which just so happens to be the title of my favorite Japanese game show.
Turso just announced Vegas Blackout, which lets you remove one full day of usage per month for any reason 🔮. Just in case your app accidentally reads a trillion rows one day and starts sending your next bill to the moon – or you got DDoS’d by the Blue Man Group after refusing to pay them for that private show they gave you at Circus Circus. Turso doesn’t judge, they just forgive. [sponsored]
Expo Router v4 is now in Beta with new features like DOM components, streaming fetch, and a life-sized Lego Superman built from scratch.
Dave Rupert wrote about where Web Components shine, and yes, the article has more than 3 sentences.
Netlify joined the “Open Next” initiative along with Cloudflare, SST and others in their quest to take down the ▲ empire. Billion-dollar corporations are so cute when they fight.
Sengun Adebayo released Chakra UI v3.
JetBrains just made WebStorm free for non-commercial use. This is probably not great news if you’re sick of being told to “use a real IDE”.
Brian Morrison wrote a very in-depth guide on the Expo blog on How to build a daily workout tracker from scratch with Expo, Clerk, and Convex. [sponsored]
React Native released a new architecture that enables both synchronous and asynchronous rendering.
Sebastian Markbåge wrote about the Next.js team’s journey with caching. The story gets pretty weird after the hobbits leave the shire and run into a data fetching issue on the server the size of Tom Bombadil.
The for ... in
loop iterates over the keys of the object, not the values. This results in name, price and discount being undefined. To fix this, we need to access the value of the key in the object.
const products = {
SKU12345: { name: "Laptop", price: 999, discount: 0.1 },
SKU67890: { name: "Phone", price: 499, discount: 0 },
SKU54321: { name: "Tablet", price: 299, discount: 0.05 },
};
function printFormattedProductDetails(products) {
for (const product in products) {
const { name, price, discount } = products[product];
let finalPrice = price;
if (discount) {
finalPrice = price - price * discount;
}
console.log(
`Product: ${name}, Price: ${finalPrice.toLocaleString("en-US", {
style: "currency",
currency: "USD",
})}`
);
}
}
printFormattedProductDetails(products);