These posts are aggregated from Svelte GitHub Repository.
Hi, I have some language and API feature request regarding some concepts in svelte and also in sveltekit. I came across some parts when developing with sveltekit that were tricky to achieve with the current way svelte works.
Question: So can Snippets and Components actually just be one thing: Components only. This way you always know what you will end up with and perhaps even make a way to create components programmatically. This is very handy when building components libraries and generic components.
app.html vs an App.svelte The reason why I come up with this one is because in (nearly) every other frontend framework an App shell is just as well a component. In SvelteKit this is app.html. Now I do like the fact that it is all very vanilla but the use of placeholders like %sveltekit.head%, %sveltekit.body%, %sveltekit.assets% and the new %sveltekit.version% could have soo much more potential when they are capable of being used within svelte components just as much. That way you don't have to hack your way around getting the svelte version, asset directory base etc. and the hooks version of transformPageChunk becomes unnecessary.
API features in SvelteKit
When browsing the new features in the SvelteKit docs I saw the base
and resolveRoute
import from '$app/paths' was replaced with resolve
. This is absolutely awesome however, I had some situations where I needed base
as a variable to replace in a path. This may not be the best example but I would think a more preferred option is to either have a method that aside from resolve
returns the base path.
These features I tried hacking my way around but I keep finding myself copy-pasting alot of these "hacks" to make them work in other sveltekit projects so I thought they may be a great addition to be adopted natively.
I'm running into issues using Svelte 5 with esbuild when importing .svelte
files from another package.
This setup worked fine in Svelte 4, but in Svelte 5 I'm seeing the following error:
effect_orphan: `$effect` can only be used inside an effect
esbuild
with esbuild-svelte
and svelte-preprocess
.svelte
components directly from another package (uncompiled .svelte
files)$effect
internallyIn Svelte 4, this worked without problems. In Svelte 5, I consistently hit this effect_orphan
error — which seems to suggest that effects are not properly registered or that component code isn't being compiled in the expected context.
If I copy the component into my app instead of importing it from the package, it works.
Is there something special required to support $effect
/Svelte 5 reactivity when importing non-precompiled .svelte
files using esbuild?
Hi all,
I was wondering what the nicest way in Svelte 5 with runes of the following would be:
I have a let myState = $state("some string")
which is synced via websocket. When a websocket message is received, the value should be updated. I also want to be able to bind it to an input field. Whenever the user types in the field or some other logic on the UI updates the value, it should be sent to the backend via websocket.
Ideas I have considered:
$effect
If I use a $effect(() => sendViaWebsocket(myState)
, this triggers also after an incoming websocket message and sends the value back, although this is not neccessary :-(
untested pseudocode in a something.svelte.ts
file:
class MyStateWrapper<T> {
private readonly state = $state();
private copy: T;
constructor(initialValue: T) {
state = $state("some string");
copy = initialValue;
$effect(() => {
if (copy != state) {
sendViaWebsocket(state);
copy = state;
}
});
}
public updateFromWebsocket(value: T) {
copy = value;
state = value;
}
}
this just feels complicated, and I always have to write wrapper.state
instead of state
.
I could also just use a onchange
for the input field, update the state there and also send the websocket message.
However, then I loose the syntactical niceness of bind:value
...
I think syncing state via websocket is quite a common usecase. Therefore, does anyone have an idea on how to do this properly? Thanks in advance!
Hi, I have a problem that I've spent the past week thinking about/working on that I cannot find a solution for. I've asked a few parts of this piecemeal in the Discord, but haven't gotten responses or a complete solution.
I have built a component layout manager library that deals with generic components. A simplified example of how I am handling components is as follows:
interface ComponentContainer<T extends Component<any> = Component<any>> {
component: T;
props: ComponentProps<T>;
}
let components: ComponentContainer[] = $state([
{ component: Foo, props: { a: 1, b: 2, c: 3 }},
{ component: Bar, props: { a: 1, b: 2, c: 3 }},
{ component: Baz, props: { a: 1, b: 2, c: 3 }},
]);
And rendered as
{#each components as c}
<c.component {...c.props} />
{/each}
The problem I'm running into is the inability to support two way binding. My library supports persisting layouts, which provides unexpected results when bindable props aren't propagated back to the root layout structure.
The ideal approach to solving this problem is unsupported: Supporting the bind:
directive for prop spreads. I've seen this discussion goes back years without much movement so I'm not expecting it to be a viable solution.
On top of the lack of movement, the discussion I've seen also seems be lacking any way to selectively bind props - it's all or nothing. The proposals also seem to be mostly concerned with ergonomics, rather than enabling feature parity for generic components. Unlike with concrete components, this is no alternative to spreading with generic components.
The second approach is to bypass the svelte template syntax and use the imperative component API. The approach I've come it with for this is
Component<T>
typetype ComponentBindables<Comp extends Component<any, any, any>> =
Comp extends Component<any, any, infer Bindable> ? Bindable : never;
interface ComponentContainer<T extends Component<any> = Component<any>> {
component: T;
props: ComponentProps<T>;
+ bindings?: ComponentBindables<T>[];
}
bind:
behaviour by transforming each bound property into a { get; set; }
pair.{ get; set; }
pairs as needed.I have tested, in the most basic case, that this approach can work. However I have some issues, some minor and some blockers:
mount
is basically inferior to hydrate
and doesn't really have a use. From that, render
should be called on the server and inserted into the component anchor with {@html ...}
. And then hydrate
should be called on the client inside of the parent components onMount
callback.render()
it seems I can simply await itRenderOutput
may be incorrect, and also is not exportedhydrate()
I can't figure it out. When there is server rendered HTML inside of the anchor then hydrate will throw for async components.bind:
, despite being common from what I've gathered in other issues, is internal behaviour and not a publicly guaranteed contract that I would like to be depending onHave a missed a better approach? Or is this something that svelte just doesn't really support at the moment? Any help is appreciated.
I'm happy to provide more information or playground reproductions if it helps in any way.
Note: This requires Svelte **5.5.0** or newer
No ?
When using Bun with a SvelteKit application, you often need to run standalone scripts that reuse code from your app. But SvelteKit uses special module imports that don't work outside the SvelteKit context:
// In SvelteKit:
import { DATABASE_URL } from '$env/static/private';
// In Bun scripts:
const DATABASE_URL = process.env.DATABASE_URL; // or Bun.env.DATABASE_URL
This makes it hard to share utility functions between your SvelteKit app and CLI scripts without duplicating code or creating environment-specific wrappers.
I created a simple Bun plugin that resolves SvelteKit's virtual modules, allowing you to use the same imports everywhere:
$env/static/private
→ maps to Bun.env
$app/environment
→ returns { dev: true }
Now you can write shared code once and use it in both your SvelteKit app and Bun scripts without any modifications.
Not that anyone can really do anything about it, but if a Svelte 5 book does get released, it might drown amongst these.
So, I'm learning Svelte and Sveltekit, and I was wondering if anyone has success using it with bun as, svelte-adapter-bun seems to be abandoned and hasn't been updated for 2 years.
I'm at the point where I'm learning Postgres and if bun doesn't work, I should know to not invest in their SQL API and use a JP library, until (and if) a proper adapter fully merges.
The Svelte team has been hard at work on asynchronous rendering, with client-side support and remote functions as our first two efforts. It’s time for the third: SSR.
There are three core pieces to the async problem:
The interplay between these creates a number of challenges for anyone seeking to create a seamless end-to-end experience.
When asynchronously rendering on the server, any await
expressions not contained in a svelte:boundary
with a pending
snippet will block until their associated promise resolves. Await expressions behind a svelte:boundary
with a pending
snippet will not be reached — but more on that later. This means that if you write the following:
<div>{await delayed("Hey y'all!", 1000)</div>
The resulting HTML output will look like this:
<div>Hey y'all!</div>
…and if you had a boundary with a pending
snippet:
<div>{await delayed("Hey y'all!", 1000)</div>
<svelte:boundary>
<div>{await delayed("What's up?", 1000)</div>
{#snippet pending()}
<div>Loading...</div>
{/snippet}
</svelte:boundary>
…the output would look like this:
<div>Hey y'all!</div>
<div>Loading...</div>
Because we have cool compiler superpowers, we can also optimize your code. The following would take one second to render, not two:
<div>{await delayed("Hey y'all!", 1000)</div>
<div>{await delayed("What's up?", 1000)</div>
You can use await
everywhere — in component <script>
blocks, in $derived
expressions, in templates, and in normal modules and async functions.
When you render asynchronous content on the server, then send it to the client and hydrate it, one of two things will happen:
pending
snippet on the server, the client will kick off the asynchronous work, replacing the pending
snippet when the asynchronous work is donepending
boundary), that content will be “normally” hydratedThe latter behavior might raise some eyebrows. What it means, practically, is that this:
<div>I slept for {await sleep(Math.random() * 1000)} milliseconds!</div>
Would output something like this on the server:
<div>I slept for 567 milliseconds!</div>
…and then, on the client during hydration, we’d wait for another random amount of time and you’d see it change to:
<div>I slept for 243 milliseconds!</div>
This really isn’t very desirable behavior. During hydration, you typically want to stick with the stuff you rendered on the server unless it actually needs to change! What we need to be able to do is render something asynchronously on the server, then hydrate it synchronously on the client based on what we rendered on the server. This requires serialization at some point. Somehow, we have to get the data you’ve rendered over the wire in such a way that we can retrieve it on the client and hydrate it into reactive JavaScript.
React solves this problem by making the serialization boundary be the client component. Data passed from a server component to a client component has to be serializable so that it can be sent over the wire and used in hydration. The downside of this approach is that React has to live in two worlds, where some of your components are server components (and therefore only run on the server) and some of them are client components (and therefore run on both the server, for initial renders, and the client for subsequent client-side ones). Svelte has always been a very isomorphic framework — we believe the Svelte code you write should be able to run equally well on the server and the client. Keeping to these roots, we think the more logical place to put this serialization boundary is at the resource level — at the actual place you’re fetching the data.
Thankfully, we’ve already taken care of this problem for you with remote functions in SvelteKit. Given a setup like this:
export const getUser = query(v.string(), (id) => getUserFromDatabase(id))
<script>
import { getUser } from './get-user.remote.js';
import { page } from '$app/state';
</script>
<h1>Hi, {(await getUser(page.params.userId).name}</h1>
…when server rendering, the result of getUser
will be inlined into the resulting HTML, and during hydration, getUser
will simply return the data synchronously — no delays or additional requests involved.
“But Elliott, I don’t want to use SvelteKit!” That’s fine! Remote functions have been our exploration into what the best possible version of data-fetching in SvelteKit could be. Now that we’ve had that exploration, we’re working on bringing some of that goodness into Svelte core, so that other framework authors can build similar solutions, or you can make your own.
pending
snippets?The above behavior could be kind of annoying! It means that you have to send your server-rendered content to the browser, then kick off whatever asynchronous work needs to happen to render the non-pending contents of your boundary. We plan to fix this with streaming. In the future, this:
<div>{await delayed("Hey y'all!", 1000)</div>
<svelte:boundary>
<div>{await delayed("What's up?", 1000)</div>
{#snippet pending()}
<div>Loading...</div>
{/snippet}
</svelte:boundary>
will immediately render the pending
snippet, but start rendering the non-pending content in the background. This non-pending content can then be sent to the browser after the initial response. This is the best of both worlds, where you can de-prioritize nonessential content by rendering a skeleton without needing multiple server round trips to fully hydrate your application.
It’s out in the latest version of svelte
! Just set experimental.async: true
in your Svelte compile options. Once you’ve done this, await
ing or calling .then
on the result of render
will render your component asynchronously. If you’re using a framework, that framework will have to implement support. In the very near future, we’ll release an update to SvelteKit to pick up your compileOptions
and automatically use async server rendering if you’ve turned the experimental compile option on.