Skip to content

Svelte 5 is Here!

Svelte 5 is Here!

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Svelte 5 was finally released after a long time in development. Fortunately, we've been able to test it for some time, and now it has a stable release. Let's dig into its features and why this is such a significant change, even though Svelte 4 code is almost 100% compatible.

Svelte syntax everywhere

This is one of my favorite additions. Previously, Svelte syntax was limited to a component <script> element. Refactoring code from a component and moving it to a JavaScript file worked differently. Now you can use the .svelte.js or .svelte.ts extension, which allows you to use the same syntax everywhere. It's important to note that it's a way to express that this is not just JS, and what you write may be compiled to something else, just like .svelte files are not just html even though they look very similar.

Runes

The introduction of runes is one of the most significant changes in Svelte. Many users felt attracted to variables being instantly reactive in previous versions.

let foo = 0; // foo is a reactive variable

There was, however, a lot of magic underneath and a considerable amount of work from the compiler to make it behave reactively.

$state

In Svelte 5, a reactive variable has to be explicitly declared using the $state rune, which brings a clear distinction between what is reactive and what isn’t.

let foo = $state(0); // foo is a reactive variable
let bar = 0; // bar is a not reactive

In the previous code, $state is not an actual function being called; it's a hint for the compiler to do something special with this declaration.

Rune names always start with a dollar sign ($) and do not need to be imported.

However, there’s much more to the changes than just the way we declare reactive variables. Runes bring a lot of new features that make Svelte 5 a great improvement.

In Svelte 5, objects or arrays use Proxies to allow for granular reactivity, meaning that individual properties in an object are reactive, even if they are nested objects or arrays. If you modify a property, it will only update that property and will not trigger an update on the whole object. It also supports triggering updates when methods like array.push are called. In previous versions, an assignment was required to trigger an update:

// Svelte 4
let myArray = [];
myArray.push(0);
myArray = myArray; // assignment triggers reactive update

// Svelte 5
let myArray = $state([]);
myArray.push(0); // no assignment needed

To have a similar behavior of svelte 4 (no deep reactivity), use the $state.raw() rune. This syntax of <rune>.* is common for related features of a rune:

$state.raw() will require an assignment to trigger reactivity.

// Svelte 5
let myArray = $state.raw([]);
myArray.push(0);             // not reactive
myArray = [...myArray, 0];   // reactive 

Because proxies are used, you may need to extract the underlying state instead of the proxy itself. In that case, $state.snapshot() should be used:

let foo = $state({bar:0});

handleFoo(foo); // foo is a Proxy

let foo2 = $state.snapshot(foo);
handleFoo(foo2); // foo2 is an object

$derived

We will use $derived and $derived.by to declare a derived state. The two runes are essentially the same, except one allows us to use a function instead of an expression, allowing for more complex operations to calculate the derived values.

let myState = $state(1);
let derivedState = $derived($state +1);
let derivedState = $derived.by(() => { return $state+1; }); // same thing as above, but we can use the function's body for more complex operations.

$effect

Effects are useful for running something triggered by a change in state. One of the things you'll note from the $effect rune is that dependencies don't need to be explicit. Those will be picked from reactive values read synchronously in the body of the effect function.

let foo = $state(0);
let bar = $state(0);

$effect(() => {
    doSomethingWith(foo); // foo is a dependency
	setTimeout(() => {
		doSomethingWith(bar);
		// bar is not a dependency because it is not read synchronously
	},0); 
})

Something to bear in mind is that these dependencies are picked each time the effect runs. The values read during the last run become the dependencies of the effect.

$effect(() => {
	let coin = Math.random();
	 if(coin > 0.5) {
		 doSomethingWith(foo); // foo is a dependency if condition is true
	 } else {
	     doSomethingWith(bar); // bar is a not dependency if condition is true
	 }
})

Depending on the result of the random method, foo or bar will stop being a dependency of the effect. You should place them outside the condition so they can trigger reruns of the effect.

Variants of the effect rune are $effect.pre, which runs before a DOM update, and $effect.tracking(), which checks for the context of the effect (true for an effect inside an effect or in the template).

$props

This rune replaces the export let keywords used in previous versions to define a component's props. To use the $props syntax, we can consider it to return an object with all the properties a component receives. We can use JavaScript syntax to destructure it or use the rest property if we want to retrieve every property not explicitly destructured..

// all valid syntax
let props = $props();
let { foo, bar } = $props();
let { foo, bar, ...otherProps } = $props();
let { foo = 1 } = $props();

$bindable

If you want to mutate a prop so that the change flows back to the parent, you can use the $bindable prop to make it work in both directions. A parent component can pass a value to a child component, and the child component is able to modify it, returning the data back to the parent component.

let { twoWay = $bindable() } = $props();

$inspect

The $inspect rune only works in dev mode and will track dependencies deeply. By default, it will call console.log with the provided argument whenever it detects a change. To change the underlying function, use $inspect.with():

let foo = $state(0);

$inspect(foo);           // console.log(foo) everytime it changes
$inspect(foo).with(myFn) // myFn(foo)

$host

The host rune gives access to the host element when compiling as a custom element:

<!-- set component as a custom element -->
<svelte:options customElement="my-element" />

<script>
	function onButtonClicked() {
		$host().dispatchEvent(new CustomEvent(“boom”));
	}
</script>

<button onclick={() => onButtonClicked()}>Click me! </button>
<my-element onboom={() => {console.log(“boom”);}}>

Other changes

Another important change is that component events are just props in Svelte 5, so you can destructure them using the $props() rune:

// Child component
let { doSomething } = $props();

// Parent component
<Child doSomething={() => {}} />

A special children property can be used to project content into a component instead of using slots. Inside the components, use the [@render[(https://svelte.dev/docs/svelte/@render) tag to place them.

// MyComponent
<script>
    let {children} = props();
</script>
<div>
{@render children?.()}
</div>

Optional chaining (?.) prevents from attempting to render it if no children are passed in.

If you need to render different components in different places (named slots before Svelte 5, you can pass them as any other prop, and use @render with them.

Snippets

Snippets allow us to declare markup slices and render them conveniently using the render tag (@render). They can take any number of arguments.

{ #snippet boldNumber(number)}
<b>{number}</b>
{/snippet }

<div>
{@render boldNumber(1)}
</div>

<div>
{@render boldNumber(2)}
</div>

Snippets can also be passed as props to other components.

<!-- Parent.svelte -->
<script>
	import Thing from './Thing.svelte';
</script>

	{#snippet simpleSpan()}
		<span>I'm a snippet</span>
	{/snippet}

<Thing additionalContent={simpleSpan}></Thing>

<!-- Thing-svelte -->
<script>
	let { additionalContent } = $props();
</script>

<div>
	<p>not a span</p>
	{#if additionalContent}
		{@render additionalContent()}
	{/if}
</div>

Conclusion

Some exciting changes to the Svelte syntax were introduced while, at the same time, maximum compatibility efforts were made. This was a massive rewrite with numerous improvements in terms of performance, bundle size, and DX. Besides that, a new CLI has been released, making the whole experience of starting a project or adding features delightful. If you haven't tried Svelte before, it's a great time to try it now.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

Svelte 4: Unveiled Speed Enhancements and Developer-Centric Features cover image

Svelte 4: Unveiled Speed Enhancements and Developer-Centric Features

Svelte 4: Unveiled Speed Enhancements and Developer-Centric Features Svelte, a widely favored framework for building user interfaces, unveiled its much-anticipated version 4 on June 22. This major release, while paving the way for future advancements, brings a plethora of remarkable enhancements. Focusing on enriching the development experience and boosting performance, Svelte 4 is indeed reshaping the landscape of frontend development. In this post, we'll delve into the specifics of this exciting release, covering the significant performance boosts, enriched developer tools and features, revamped websites, and simplified migration guide. A Deeper Look at Performance Enhancements Svelte 4 delivers remarkable improvements in performance, focusing on shrinking the Svelte package size, and enhancing hydration efficiency. Streamlined Svelte Package Svelte 4 has substantially slimmed down, reducing its overall package size from 10.6 MB to a sleek 2.8 MB - a 75% decrease. This reduction in dependencies from 61 to 16 not only lightens Svelte but also optimizes SvelteKit, significantly accelerating the REPL experience and npm install times. For instance, npm install times have been trimmed from over 5 minutes to less than a minute, a leap in quality that any developer will appreciate. NPM I Before: NPM I After: Bundle Size Before: Bundle Size After: Optimized Hydration and Performance Scores Alongside the impressive package size reduction, Svelte 4 offers more efficient code hydration, reducing the generated code size for the SvelteKit website by nearly 13%. This leaner codebase contributes to higher performance on benchmarks like Google Lighthouse. The performance score for the new Svelte 4 starter on starter.dev has soared from 75% to a near perfect 95+%. Overall, the performance enhancements introduced with Svelte 4 mean a faster, more efficient, and smoother developer experience. Before: After: Enhanced Developer Experience in Svelte 4 Localized Transitions Transitions in Svelte 4 are local by default, preventing potential conflicts during page loading. ` Improved Web Component Authoring Web Components authoring is simplified with the dedicated customElement attribute in svelte:options. ` Stricter Type Enforcement Svelte 4 introduces stricter types for createEventDispatcher, Action, ActionReturn, and onMount. ` These changes collectively offer a streamlined, robust, and efficient coding experience. Revamped Svelte Websites With Svelte 4, the team has also revamped its main website, offering an improved and more user-friendly experience. The Tutorial Website The Svelte tutorial website has been overhauled for an enhanced learning journey. New improvements include a visible file structure, fewer elements in the navbar, smoother navigation between sections, and a new dark mode. The Svelte Website The primary Svelte website received a makeover too, including better mobile navigation, improved TypeScript documentation, and a handy dark mode. These website updates aim to provide a more engaging, intuitive, and user-friendly experience for all Svelte users. A Smooth Migration to Svelte 4 Transitioning from Svelte 3 to Svelte 4 is designed to be as straightforward as possible. The Svelte team has provided an updated migration tool to simplify this process. Here is a step-by-step guide for the transition: 1. Run the Svelte migration tool. ` 2. Remove Svelte 3 packages. ` 3. Update your eslintrc.json configuration file. ` 4. Upgrade Storybook related packages to the latest v7. Note: as of the publishing of this article, the latest version is 7.0.26. ` Do note that the minimum version requirements have changed. You will now need: - NodeJS 16 or higher - SvelteKit 1.20.4 or higher - TypeScript 5 or higher For more detailed instructions and information, please refer to the official Svelte 4 migration guide or you can take a look at our Svelte 4 starter kit on starter.dev. The focus is to ensure a hassle-free transition, allowing developers to take advantage of the new features and enhancements Svelte 4 offers without significant obstacles. Conclusion Svelte 4, with its performance enhancements and streamlined development process, offers a new pinnacle in the realm of JavaScript frameworks. If you're keen on shifting from Svelte 3 to Svelte 4, a comprehensive migration guide is provided to facilitate a smooth transition. For a quick start with Svelte 4, check out our ready-to-use Svelte Kit with SCSS Starter Kit. In addition, we've developed two showcases demonstrating Svelte 4's power: 1. Svelte Kit with SCSS & 7GUIs - A comprehensive demo showcasing various UI challenges. 2. GitHub Replica Showcase - A clone of the popular code hosting platform, GitHub, demonstrating the potential of Svelte 4 in building complex and high-performance web applications. In conclusion, Svelte 4 brings numerous performance improvements and enriches the development experience, thereby increasing developer productivity and enabling the creation of more efficient applications. Its thoughtful design, alongside the streamlined migration process, is set to expand its adoption in the web development community....

State of Svelte Wrap-up cover image

State of Svelte Wrap-up

In this State of Svelte event, our panelists discussed updates, LTS releases, and APIs, with Node.js maintainers, technical steering committee members, and collaborators. In this wrap-up, we will take a deeper look into these latest developments, and explore what is on the horizon for Svelte. You can watch the full State of Svelte event on the This Dot Media YouTube Channel. Here is a complete list of the host and panelists that participated in this online event. Hosts: - Tracy Lee, CEO, This Dot Labs, @ladyleet - Rob Ocel, Team Lead & Software Architect, @robocell Panelists: - Scott Spence, Svelte Society, Developer Relations Engineer at Storyblok, @spences10 - Brittney Postma, Founder Svelte Sirens & Software Engineer Design Systems at Provi, @BrittneyPostma - Geoff Rich, Senior Software Engineer, Ordergroove | Svelte Core Team, @geoffrich_ - Simon Holthausen, Software Engineer at Vercel | Full-time Svelte maintainer, @dummdidumm_ - Kevin Åberg Kultalahti, Co-founder & Technical Community Builder at Svelte Society, Main Organizer at Svelte Summit, @kevmodrome Svelte 4 The chat got off to a great start with a discussion about Svelte 4, and what we can expect with that release. Simon spoke about how it will be more of a maintenance update than anything else. This version of Svelte will raise the minimum required Node version and use newer versions of Typescript as well. There will also be other minor breaking changes, but the release will mainly be focused on internally updating the repository by converting it to a mono-repo. As soon as these updates are done, Simon said they will immediately begin work on Svelte 5. Typescript and Svelte Scott brings up the reasons for not using Typescript in Svelte. Simon said a decision was made to transition the Svelte repository from using Typescript to using Javascript. There were questions about why types and type safety were being taken away from the repository. Simon clarified that the repository will be getting rid of .TS files, but they are not getting rid of type checking with Typescript, and the code will still be fully typed checked at the same level as before. The plan is to do it through JS Docs. JS Docs provides the same level of type safety you get through Typescript, but there is no longer a need for a compile step when using JS Docs. There is also no need to ship any Source Maps, and it should be easier to debug. Kevin also wanted to be clear that Typescript can still be used when building a Svelte app. Why Svelte? Rob notes that the official release of Svelte happened about 4 months ago, and asks the panelists how the launch has been going so far. Kevin goes first, talking about how everyone with whom he has talked about it has been very excited about it. He talks about how the form actions and data loading are very popular. In other frameworks, you have to attach event listeners, and then do the fetching on clients. Svelte simplifies all of that, and allows you to get rid of a lot of code by using the features in Svelte. Svelte REPL Kevin talks about the Svelte REPL, and how it plays into why Svelte is getting so big. Svelte isn’t just easy, it’s the fact that it is social in the fact that you can share a REPL and show someone how to do something with Svelte. If you have an issue, you can usually find a solution in the Svelte REPL. Server and Client Geoff talks about this aspect of Svelte. He says that they were treated as two separate entities, and there was talk about how to make them more interconnected so that it’s easier to use the server data, and get it into components. In SvelteKit, you have a load function in a separate file that defines how that data is loaded. Svelte also calls a JSON endpoint and then that component in the JSON data. State Management Geoff brings up the simple state management model that Svelte has, and they really don’t want to give that up by implementing too many things like short syntax. Simon adds that there is no real reason to bloat the syntax in the Svelte files. He doesn’t want the interoperability that Svelte currently offers. Signals vs Store A question is brought up about Signals vs Store, and if they are the same. Simon talks more about how they are related, but they are not necessarily the same. He explains that the API for Store is a little more settled right now where the API for Signals is a little more in exploration. Usability is also different because Signals is more primitive, and everything is composed of functions which you call in a certain way. With Stores, you wrap a store and map the values that are pushed into something different. How the panelists found out about Svelte The latter part of this event focused on how each panelist found Svelte and got involved with it. It was a very interesting part of the conversation to hear the backgrounds of each panelist, and why they got more and more involved with Svelte and everything that was going with it. It went very in depth, and would be worth exploring more by watching the conversation unfold on the event video. Conclusion The panelists were very engaged, and there was a lot of dialogue about Svelte and the exciting things being done. The panelists also finished by bringing up ways to get involved with the Svelte community. You can watch the full State of Svelte event on the This Dot Media Youtube Channel....

What is Cypress Studio? cover image

What is Cypress Studio?

Introduction Cypress Studio has been around for some time. It was introduced in Cypress v6.3.0, removed in v10, and reintroduced in v10.7.0. This blog post will dive into its current state and how to use it today. What is Cypress Studio Cypress Studio is a tool built on top of Cypress. It offers an interface for creating tests as if you were using your site without requiring code to be written. It adds functionality to query elements and to add assertions from the interface. It's important to note that Cypress Studio is still under an experimental flag and lacks support for Component Testing (another feature of Cypress). Creating an app to test We first need a working app because the tool we will use is meant for end-to-end tests. I'll pick Svelte and Vite for this demo, but you can choose any framework. Cypress is agnostic in that matter. ` Make sure to select the Svelte and Typescript options to follow along. Now open your project location, install dependencies, and start your app to ensure everything works correctly. ` Installing and setting up Cypress Studio Now it's time to add Cypress to our dev dependencies. ` With our dependency installed, let's launch it so we can start configuring it. But first let’s add an entry under scripts in our package.json file. ` ` A new window will open that will guide us through the initial setup. Select the "E2E Testing" option to create the required configuration files. Then, you can close the window. A new folder called cypress and a configuration file cypress.config.ts are created at the root of our project. To enable Cypress Studio, we must open the newly created configuration file and add the experimentalStudio property. ` For this project, we need to ensure that TypeScript is configured properly for Cypress when it runs, as it conflicts with the one in our root folder. We will extend the original typescript configuration and override some properties. Create a new tsconfig.json file inside the' cypress' folder. ` You can find more information on setting up TypeScript with Cypress in their documentation Creating tests Now that our setup is complete let's write our first test. We will create a folder called e2e and a new test file. ` Open the new file and create an outline of your tests. Don't add anything to them. I initialized my file with a few tests. ` There is an option to create spec files from the interface, but it will contain some initial content that you most likely remove. There’s third option to scaffold multiple specs files, these can serve as a learning resource for writing tests as it contains many different scenarios tested. Make sure your app is running and, in another terminal, start cypress. ` Select E2E testing and Chrome. You should now see a list with all your test files. Click on home.cy.ts. Your tests will run and pass because we have not made any assertions. This looks the same as if we haven't enabled Studio, but there's a new detail added when you hover on any of the tests: a magic wand that you can click to start recording events and adding assertions directly in the UI. Let's start with our first tests and check what assertions we can make. The first step is to navigate to a page. This interaction will be recorded and added to the test. To make assertions, right-click on an element and select the ones you want to add. After we complete our test, let's review our generated code. Go to the test file and see the changes made to it. It should look something like this. ` Cypress Studio will attempt to pick the best selector for the element. In this case, it was able to choose button because it is unique to the page. If there were more buttons, the selector would've been different. You can interact with elements as if you were using the page regularly. Note that Studio supports a limited set of commands: check, click, select, type, and uncheck. Let's record our second test and verify that the button will increase its count when clicked. That was quick. Let's review our generated test. ` So far, our tests have been very accurate and didn't need any modifications. However, take Studio as a helper to write tests visually and their selector as suggestions. Let's take the bottom link with the text "SvelteKit" as an example. It will generate the assertion: ` This selector is accurate, but modifying the elements' structure or order would break the tests. We don’t want tests to break for reasons that do not affect our users. A change in order does not have the same impact for the user as changing the text of a button or changing the url of a link. These selectors should be as specific as possible, but rely as less as possible on implementation details. Selecting images by its alt attribute it’s a way to find a specific element and at the same time ensure that element is accessible. (Accessibility has a direct impact on users) As a counterpart, when clicking any of the logos above, we will get very interesting selectors (and assertions). ` With these assertions, we check that our images have an alt attribute set and are tied to a specified link. Conclusion As with any other automated tool, check the output and solve any issues that you may find. Results depend on the structure of the page and Cypress Studio's ability to choose an adequate selector. Overall, this tool can still help you write complex tests with plenty of interactions, and you can later modify any selectors. Besides the selector, I found it helpful in writing the assertions. If you’re new to Cypress or e2e testing, it can be of great help to go from an idea to a working test. Reviewing these tests can be a great way to learn how these tests are built....

What does it actually look like to build software with AI today? Not in theory, but in practice. cover image

What does it actually look like to build software with AI today? Not in theory, but in practice.

What does it actually look like to build software with AI today? Not in theory, but in practice. At the Leadership Exchange, this was the question at the center of the Developer Panel, where leaders from across the industry unpacked what’s really changing inside engineering teams and what organizations need to do right now to keep up. The Developer Panel at the Leadership Exchange explored the cutting edge of AI in software engineering and examined what organizations should focus on today to prepare for the future. Moderated by Jeff Cross, Co-Founder & CEO at Nx, the panel featured Victor Savkin, Cofounder & CTO at Nx, Alex Sover, Vice President of Engineering at OpenAP, Brent Zucker, Senior Director of Engineering at Visa, and Jonathan Fontanez, AI Engineering Lead at This Dot Labs. Panelists shared insights into how AI is transforming the software development lifecycle and how teams can adopt tools effectively while preparing for organizational change. Panelists discussed emerging workflows, including CI-in-the-loop, agentic healing, and context engineering. They examined how validation, code reviews, and PRDs are evolving alongside AI capabilities and how teams are integrating external sources such as production traces to improve quality and reliability. The discussion also covered what the next generation of agentic tools might look like and how these capabilities will shape engineering practices in the near future. Adoption of AI comes with challenges. Teams often rely on plugins or extensions without foundational understanding, and individual contributors may fear displacement. Panelists emphasized that education, governance, and skill-building are essential for teams to manage AI agents effectively while maintaining quality. They also highlighted the need to standardize workflows and ensure organizational alignment to fully leverage AI capabilities. The conversation extended beyond technical challenges to organizational implications. Panelists discussed how teams can avoid issues like Conway’s Law, manage distributed teams effectively, and evolve engineering practices alongside AI adoption. Leadership and management strategies play a crucial role in ensuring that AI integration delivers meaningful outcomes while maintaining efficiency and alignment with business objectives. Key Takeaways - AI workflows require both technical and organizational preparation. - Education, governance, and skill development are essential for successful implementation. - Forward-looking teams are rethinking validation, CI pipelines, and context management to fully leverage agentic AI. The discussion highlighted that adopting AI at the cutting edge is not just about new tools - it is about rethinking processes, workflows, and organizational culture. Companies that embrace this holistic approach are most likely to succeed in leveraging AI to its full potential. Are you interested in more conversations like this? Message us for an invite to the next, or for a private discussion around these topics. Tracy can be reached at tlee@thisdot.co....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co