Things about Svelte. Sometimes weekly, sometimes not.
[Music]
Hello everyone. Welcome to another episode of Svelte Radio.
I'm Kevin, and today I'm joined by a guest who's been on before, I believe.
It was a while ago, right?
Yeah, that was a long while ago.
A long time ago, but yeah.
So I'm here with Dominik Gee of Vite and Svelte core teams, right, or maintainers.
I don't know what you call yourselves.
Well, you can call us whatever you like.
We basically maintain Svelte, and I help in Vite as well.
Core team is a big word.
Yeah, I guess that's only for the super small group that works on it all the time.
Well, no, I mean, it's like myself, I didn't contribute a lot to the Svelte 5 code base, for example.
But I'm still there doing adjacent work, like vite-plugin-svelte is my biggest work in the Svelte part.
On the Vite side of things, I do vite-ecosystem-ci and ts-conf-check,
which is the package that helps Vite find TS config files.
So you mentioned vite-ecosystem-ci. Sorry, what does that do?
Because I believe that's a pretty important project in terms of making sure that the ecosystem doesn't break.
Yes, exactly, that's what it is.
There's a Svelte version of it as well.
Basically what it does is it's a set of automation script that builds a PR and then executes downstream projects, tests, with that build.
So when we change something in Vite, we create a build of that, and then we run SvelteKit tests with that build.
And if something in Vite changed that breaks the SvelteKit tests, we will know that...
Something changed. Breaking change here probably.
It's a big possibility that this could break SvelteKit.
And then we collaborate with the maintainers of the different projects and find out why it happened,
if this is something that we have to change in the PR of Vite, if there was some reliance on internal behavior.
And we coordinate releasing in a way that our users don't experience this.
And this is a big contributing factor to the stability in the Vite ecosystem.
Yeah, okay, so it's funny that...
So Vite has this, but then Svelte also has it? Does SvelteKit also have it?
So is there like a chain of ecosystem CIs that just runs?
So for Svelte, I made only one.
In theory, yes, we could have a SvelteKit ecosystem CI and a Svelte ecosystem CI.
But our team is only so large and...
Also because Svelte and SvelteKit are so similar and belong to each other basically,
that a single ecosystem CI gives us enough feedback in that regard.
Because it would be kind of fun and cool if you could...
Like, something changes in Vite that runs some branch out on a tree,
like maybe super forms or something.
That would be fun to see.
Yeah, I actually have ideas about this, but time is a limiting factor.
But there is an idea of a generalistic ecosystem CI framework where projects can create their ecosystem CIs
and maybe even have a graph of CIs running in series,
but then it gets really tedious and also really compute-intensive
because let's not forget running hundreds or thousands of test cases doesn't come for free.
We actually checked the execution minutes Vite ecosystem CI took
and it's tens of thousands of minutes every year.
But then I also looked up what the typical energy consumption of a GitHub runner might be.
If you think about it long enough, it's like running a medium-intensive light bulb all year.
So it's an acceptable cost for the benefit it brings
because if it catches even just one bug, it saves so much time and compute elsewhere
that this compute that's been spent is okay.
But we still have to be mindful not just to run everything all over again.
Yeah, that's almost an argument for expanding it, I think.
Even for getting out there in all the branches and seeing things.
But yeah, it seems like it would be a lot of work to set it up as well.
So maybe for the listeners, we are here in person at JS Nation.
You did a talk yesterday.
Actually, you gave me the ticket even to the conference, so I'm very grateful for that.
Maybe you can tell us about your talk that you did.
Well, I'm here because I got invited and I'm very thankful for the conference to give me this opportunity.
They really are supportive of Veet
and wanted to know what the new major of Veet is going to bring.
So my talk was focusing on that.
The big topic for the next major of Veet that by the time you hear this episode
is probably already released, so it's Veet 6, is the environment API,
which is a new entity or abstraction inside of Veet
to simplify the internal architecture for hybrid application frameworks.
So Veet took the implementation of SvelteKit when SvelteKit was based on Snowpack still,
so in the alpha version a few years ago, and modeled its SSR support after it.
And the way it has been done is so that you have one dev server that has one module graph
that is shared between client and server modules, and you have to ask this one module graph,
give me the client module, give me the server module.
And so you have code that has a lot of branching, and you have to do some special casing,
if SSR, then this, then that.
So internally it's a little bit complicated.
On the outside it is super simple for users and projects,
and that's a big reason why people love it.
But during the last two, three years when all the frameworks were using it more,
we saw how they used it, and they were running into these limitations,
and plugin code is not always idiomatic.
Also in the plugin server there are a few places I would love to refactor,
and I'm finally going to be able to do that.
At this point in time I have to shout out to Björn, who has my back on Vite plugin Svelte right now
because I'm absent for a week.
These limitations, to solve them we need to separate these parts.
A while ago Vitesse invented Vite Node, which is the module runner they use to run your tests,
and that was added to Vite Core in version 5.1.
And this turned out to be a great fit to abstract environments.
An environment is basically a module runner and a transport layer between the dev server and the runner.
With that you can have a client environment and a server environment,
and they no longer share a module graph.
And I was talking about that, and this unlocks many possibilities in the Vite ecosystem
to build new environments that, for example, Dario of Cloudflare was already experimenting with it for SvelteKit.
You know MiniFlare, right?
The dev environment for Cloudflare.
The reason to use MiniFlare is because, if we explain what MiniFlare is,
it's basically a way to run Cloudflare proprietary stuff locally.
So if you're developing for a Cloudflare function.
If you want to access R2, there are key value stuff, you can do that through MiniFlare.
And during development you also need this available.
And right now you can only do that by shimming stuff.
The MiniFlare process runs next to your dev server,
and then you have to communicate between the two to make it work.
With the environment API, you can create a runner that is executed not outside of MiniFlare,
but basically MiniFlare is hosting the runner.
So it's a lot more like in production where your app is running inside the Cloudflare environment,
and you can just access the key value global stuff and all the other APIs as well.
That brings your code running in the dev server a lot closer to production.
And having environments that behave in dev like they behave in production is a goal to have.
At the same time, it simplifies the internal structure of plugins.
And you can also have more than two environments.
You can create environments for almost anything.
I'm really curious to see what people are going to come up with.
Something for Tauri, something for NativeScript or React Native.
I already had a discussion with Samuel from Inlang who had a question at the end of the talk.
If you could use environments as an abstraction for internationalization,
so you spin off separate environments per locale,
which would basically create a matrix of environments,
because if you have an application that has three environments and five locales,
you suddenly end up with 15.
So I was a little bit reluctant and said I'm not sure that scales well.
I'm also not sure how you bring everything back together into a single domain.
Yeah, because each bundle is built for the specific environment.
Yeah, but I'm not sure if I have the right hunch here,
because maybe someone makes it work and deploys to different domains like .de and .com,
and that is the right abstraction for them.
The point is that this is a very generic entity.
We have, of course, envisioned use cases for it.
Otherwise, it wouldn't have been built.
But that doesn't mean that somebody will not come up with even more cool stuff to do with it.
It wouldn't have been the first time in the video ecosystem,
because this is the most vibrant ecosystem I've been a part of.
Another example is that Storybook, who has done great work
in improving their story to build stories for Svelte.
A while ago, they changed to a generic common story format that was not Svelte.
You had to write JSX or JavaScript.
Now they have support for writing stories in Svelte again.
I've been talking with Jepel Reinhold from them.
They recently added a feature where they can have play functions on stories,
and then you can define actions that happen.
You see the component moving through different states.
They combine that with vTest.
You can have two or three lines of config,
and it generates a test case out of this play function.
So your stories suddenly double as tests.
That's amazing.
This is happening because Vite is so flexible and so open,
and so this environment API is another part of infrastructure Vite gives to the world.
I can't wait to see what's going to happen with it.
Yesterday, after the conference, we chatted for a bit about the environment system,
the two of us, Rich and Brady.
We were talking mostly about native stuff like iOS apps and Android apps and stuff like that.
Is that something that we might see?
Can you have one environment for the web and then another environment for iOS specifically?
Can you tie in other languages than JavaScript somehow?
Now I'm just speculating here. I have no idea.
So environments are not so much about languages than about runtimes.
But a native iOS runtime gives you access to some sensors maybe.
In the web, usually this abstraction is through web APIs that expose it to you.
But if they have native APIs that are exposed to the web somehow,
I can imagine that you create a dev environment for that.
Also at the conference, somebody asked me about React Native as well
because they want to be able to run test cases in unit tests on devices
because on device the environment might be different and they want to be there.
But they don't want to spin up the app and use a robot to touch stuff.
They just want to use the environment on that device.
Maybe that works. So they can have a unit test that is basically a headless test runner
that runs the tests on the device. It just works.
Environments. That makes me think of Node, for example.
There are now a bunch of these JavaScript-based environments like Deno and BUN.
Can one environment, I guess not compile,
but can you target different runtimes to see that your project works on these different--
So, for example, say that I want to check if my project works on BUN, Deno, and use different--
Is that a use case for environments or am I completely--
That's an interesting question. I haven't thought about that before.
Because BUN has, for example, SQLite support built in, right?
I assume that would be one way of--
Yes, so basically it makes sense to have a BUN environment and a Deno environment
because of their native features and differences they have from Node.
By the way, it also makes sense to have different Node environments
because you might note major versions are different over time.
So, if you want to use Node 22 on your developer laptop
but for some godforsaken reason that you should upgrade but didn't,
your production environment runs on Node 14.
You can have that if you want. You shouldn't.
You can quote me on that. If you run Node 14 in production in 2024,
do something about that.
But the point is you can describe these environments and use them,
but I'm not sure if using them for test metrics, dimensions,
makes the most sense because ultimately these are more like
to replicate the application runtime environment that you target.
Unless you have an application that has a part running in BUN
and a part running in Node, it might not make a lot of sense.
Maybe it can work.
Yeah, maybe it would be cool if you could specify specific functions
that run in different environments.
So, let's say you have an application
and then you have a very compute heavy part of the application
that needs like a GPU support and it needs to run in BUN
because BUN is much faster, whatever.
Or even like a Cloudflare worker.
Maybe you want to run it in the cloud on demand, right?
It would be cool if you could spit out both like the regular web app
and then Cloudflare ready function that you can then somehow use.
Is that the use case?
This is entirely possible, yes.
So, in package.json there are export conditions.
Most of the Edge runtimes have specific export conditions
or there's the worker decondition.
So, if you have a TypeScript file or a JavaScript file
in the monorepo package that targets these specific conditions
and you import that into your application
and you have an environment that supports this,
you can use them through that.
That's interesting.
So, I'm just imagining now how this would look like from,
for example, like a SvelteKit point of view.
Like you could have a--
There probably needs to be a lot of work if you wanted this to work,
but like you could have a server endpoint
that does some calculation that is deployed to Cloudflare
and does something in the Cloud
and then the rest of your application lives on a Node server somewhere
and then automatically you bind it together somehow using the--
Maybe that's--
Yeah, so this is a topic for SvelteKit 3
because right now SvelteKit is using this concept of adapters
and you can only have one adapter.
But the environment API is basically going to change
how all frameworks treat adapters
because when Cloudflare provides a Cloudflare environment,
adapters can just like use this
and they become very, very thin wrappers
over the Cloudflare provided Cloudflare environment,
which is great because when Cloudflare releases new stuff
and the wrangler.toml says compatibility date 2025.1.10,
the Cloudflare environment can check that and act accordingly.
Our adapters always need to be updated and follow along
and it's a lot harder to do that.
So this is going to save everybody across all frameworks
a lot of time in the future.
So the use case that I was thinking needs a lot of work
from the SvelteKit side probably.
And it also needs to somehow manage deploying automatically
and to different targets and stuff.
Yeah, you just signed up for doing it,
so thank you for your sacrifice.
I already need to implement this new client hook thing.
I don't know if you saw the discussion about that.
Yeah, I was part of that.
Yeah, right, right.
So at work I need a way to do some kind of stuff
before SvelteKit actually starts, right?
And there's no hook for that.
There's only on the server side,
so I'm going to try to write a new client hook.
We'll see how it goes.
Yeah, this is going to help a lot, so thank you.
Yeah, I haven't done it yet.
But really it is--
I've mostly used SvelteKit like the--
I don't know if you would call it the full SvelteKit,
if that makes sense, like as both a backend and a frontend, right?
And then if you do that,
you get access to all of the functionality, right?
But if you do it as an SPA,
you're really struggling a lot, I find at least.
You have to do a lot of workarounds to make things work.
One thing that I've noticed that is pretty irritating
is if you want to use the load function,
you sometimes need to--
like if you're relying on a package that only works on a browser,
you need to dynamically import it into load function
because the dev server runs--
the load function runs on the server when you're developing, I think.
Or if you're building, it's one of those.
Yeah, you probably have to disable prerendering
and then do some other stuff,
but I agree that if you want to do an SPA in SvelteKit,
that's not the primary use case you can,
but the ideal use case is use server-side rendering
and get the initial data,
and then the client-side router takes over.
Yeah, it could be a bit better, like smoother, I think.
Hopefully if Svelte 3 re-architects some stuff,
maybe we'll see if something happens there.
Yeah, SvelteKit 3 will definitely have a lot of new things.
First and foremost, it's not about changing things from each side,
but it's changing to Svelte 5 as well.
So instead of page stores, there will be a page state.
So you shouldn't hold your breath on SvelteKit 3 in 2024.
I mean, it's pretty close to the end of the year as well.
It's going to take a few weeks longer.
I'm a bit sad about that because we started a tradition
on doing 14th of December releases with it.
Oh, you've done that twice now then?
So for Svelte 1, I have no clue about the dates.
I'm just very happy when the new version is released.
But yeah, I'm excited about Svelte 3.
I'm hoping there will be a rework of the way you're loading data.
A bit more granular would be nice.
Maybe not the Svelte 4 thing.
I'm not sure we had bigger discussions
about redesigning the way the router works and the way load works.
But there has been an addition to Svelte 5 that is pretty exciting.
It has not been released yet.
That's error boundaries, which is a great feature to have in applications.
The way they are being implemented is pretty generic.
Dominic Kenaway is a genius.
He's doing awesome work on that regard.
What these boundaries are going to enable in the future
might also allow different load patterns.
That's interesting.
Yeah, I usually run into situations
where I want to just invalidate one small part of a load function.
Like if I'm fetching three different things,
maybe I just want to invalidate one thing.
You can do it today, but you have to use layout groups.
You can list it very deeply.
Or you have to use custom invalidation names.
That also works.
You can pass a string into invalidate.
Yes, but it will invalidate the whole load function, right?
What I want is I want one load function to be three load functions, really, in general.
Let's say I wanted to fetch posts, comments, and likes.
If I'm on the page, maybe every five seconds I want to invalidate the like number
so I get a new, fresh like number on some page.
Today, I have to do it using layout groups.
Yeah, it's not ideal.
But anyway.
Yeah, but at that point, maybe you don't need to load the likes from the load function.
You can just load them initially once and then put some client-side updates.
Yeah, create a server endpoint because the load function will use that behind the scenes anyway, right?
Yeah, all right.
Sveld, let's talk a bit about the migration script.
How are you finding it in general?
Well, so I actually am a freelancer by day and an open source developer by night.
One would think it's the other way around with how much you produce.
Yeah, depending on the time zone where my clients are, it's not far from the tooth.
But in general, I still work with cert4 a lot, so I haven't put the migration script through a lot of paces.
But in general, I've heard a lot of good things about it.
People are happy that it works the way it does.
There is a few kinks, things you have to keep in mind, though.
So, for example, one of the major reasons we came up with rules in the first place
was that the $ statement is a little bit of a mix-up of derived states and side effects.
So what's a side effect for people that are listening?
A side effect is when you invoke a function and it does something outside of the context of that function
that has lasting effect.
So even if you do a console log, that is a side effect because the browser console now has a new entry.
And in theory, somebody could be listening to console entries and do something based on that,
so you change the world and it's a side effect.
Calling play on a video element is a side effect.
Emitting an event can be a side effect.
Fetching data.
Fetching data can be a side effect.
Okay, yeah, so in Svelte 4, then, we had this reactive statement.
Then it both did side effects and derived state.
Yeah, so derived state is basically you have two numbers
and the sum of those two numbers is a derivation.
And every function you can call that always returns the same output
when you give it the same inputs can be a derivation, basically.
You can also have derivations that are more than just an expression.
Then you can use derived by.
But in general, you should try to use derived and an expression.
Functions are more like an escape hatch for it.
So the migration script, when it sees a dollar colon statement,
it can't always tell if it was using a derivation only
or if it was also using a side effect because in Svelte 4,
especially if you used the curly braces notation
and had multiple statements in a single one,
you end up doing both at the same time.
And the migration cannot untangle that for you.
So you have to do it yourself.
The migration creates a run function that is called to do the same
that the dollar colon statement would have done before.
So the behavior is almost unchanged.
But the run function shouldn't stay in the application code for a long term.
So once the migration script has finished,
it adds some comments to your code where you have to look,
and you should also look at all the run functions and refactor them.
There is one pretty important piece of advice that everybody should follow,
and that is don't overuse effect.
The rule you should be looking at first is derived
because everything you derive from one state
to have a derived state should be done with that.
Technically you can use the effect rule to do something similar,
but if you create effects that depend on state
and then modify that state inside that effect,
this modification triggers the effect again,
that triggers the modification again, that triggers the effect again,
and now we are running out of time in the episode
because I have to repeat that all over.
So you get the grift, right?
These effects are really for side effects,
for things that you cannot use derived for.
The rule of thumb is if you can do it with a derived, use the derived.
If you can't, then reach for effect.
I so rarely use effects on it personally because,
I mean, for example, when I build applications with Svelte,
I use SvelteKit so most of my loading and data interaction
happens with load and form actions, right?
So for me, I don't think I have used a single use effect.
Sorry, not use effect, that's React.
I haven't used a single effect rule in the new Svelte Society website,
for example, that I can think of, which is,
and it's quite a big website.
There's a whole admin dashboard.
There's interaction with like buttons and all sorts of stuff.
So I think if you're--
I agree with you that if you think you need to use an effect,
then you should probably think twice before you do it
because you probably don't need it, really.
But it depends on the application that you're writing.
If you're writing something very interactive,
maybe you do need it for some reason.
There's one tiny exception to the rule,
but this is like an obvious case of you need it.
That is like life cycle of the component itself.
So if you want to not use on mount anymore, you can.
On mount is not gone and it probably won't go away anytime soon.
But if you add an effect, you can use the cleanup function of the effect
to have the same functionality as on mount and on destroy
because if the effect depends on nothing else,
it will only be executed when the component is created
and when the component is destroyed.
Yeah, that's a good shout out, right?
Especially going back to our discussion about SPA versus full Svelkit.
I find that in SPA applications,
I usually need to do some stuff in on mount
more often than I would in a full Svelkit application
because the data is already preprocessed as I want it in the load function.
Specifically, data might not be something that you want to do in on mount.
Yeah, it depends.
Sometimes lazy loading on mount can be an escape hatch.
I'm not a fan of this because I don't think components
should be responsible for loading their own data all the time.
Pages are a good abstraction for that, in my opinion.
But others tend to build applications in different ways
and I don't want to stand in their way.
So I can recommend people to use the migration script
and use Svelte 5 because it's been great
and the learning experience you have is pretty low.
It's super simple to pick up.
I actually envy people picking up Svelte now a little bit
because they don't have to learn about dollar,
colon statements and the nuances.
It's a little bit clearer than before or even much clearer
and you get a faster runtime, you get smaller output.
It's overall a very good improvement.
Yes, it is.
I'm very happy how it turned out.
Especially our full-time maintainers, Rich, Dominik and Simon,
did a great job on implementing all of it.
All the others that contributed to it and all the users that gave feedback.
It's been a great community effort.
I know you're running a hackathon right now on it.
Yes.
I'm so excited about what's coming out of this.
The last hackathon brought us great stuff like Svelte Map Libre.
I used that with a client application.
Sorry, which one?
Svelte Map Libre.
Ah, right.
And also I think this Wolfenstein thing.
Yes, the CSS, HTML, the crazy thing.
Grisha Abbott did something with Threat, right?
Yes, some driving game, I think.
Trackmania or something?
Yes.
No, Trackmania is an actual game, I think.
It was called something similar.
Threatmania, probably.
So I can't wait what they come up with this time around.
Yes, last year was amazing.
We got so much good stuff out of it.
Like you mentioned, the mapping library superforms is a big one
that's used by almost everyone that is using SvelteKit, I think.
Maybe not everyone, but I use it all the time unless it's a very small form.
But it's nice.
The Wolfenstein thing is so crazy.
So for those that are listening that don't know or have seen it,
it's basically a clone of, is it called Castle Wolfenstein
or just Wolfenstein?
Return to Castle Wolfenstein.
Return to Castle Wolfenstein, yes.
But it's made completely in CSS and HTML in Svelte.
So there's no Canvas, there's no WebGL or something like that.
It's all just HTML elements that are transformed
and mutated on the screen as you turn around and stuff.
It's moving things.
It's a crazy project, honestly.
And if you go and look into the code, it's actually not that complicated.
I mean, obviously it would take some time to figure out how it works,
but there's components for a door and walls and all this stuff.
It's basically really crazy that it's a silly effort, of course,
but the result gives you a really throwback feeling.
I'm old as fuck and I remember playing the original.
It brings some of that old early-day 3D feeling
with some more than isometric but not really great stuff
and the 8-bit stuff.
The fact that the architecture is still component-based and declarative
and that it just works.
And it's so smooth as well.
It's like a fast, like it's not laggy or anything.
Part of that is due to the great Svelte language
and being able to express yourself in that way.
So Svelte is really suitable for all kinds of applications
like silly stuff, innovative stuff, but also boring corporate stuff.
All of it benefits from being concise, quick in building things,
getting runtime and migration support to the next major version.
It's really a joy to work with.
I can't imagine myself not working with it for a few years.
Yeah, I don't want to go back to working with React, for sure.
Yeah.
All right, anything else that you want to mention?
You mentioned you were freelancing.
Where can people find you?
Well, I've been freelancing for 10 years.
Obviously not all of it was Svelte, but for the last few years,
it's been a great tool.
Many of my clients use it.
And if you want to find me, the best way to do so is either the Svelte Discord.
I'm Dominic Gee with an orange Svelte logo to my name, so pretty obvious.
There's also an home page.
It's goepel.it.
Yeah.
There's a contact link.
I guess an email and stuff.
A list of the talks I gave on some conferences.
All right.
Speaking of conferences, there's a Svelte summit coming up, I've heard.
Oh, is there? I had no idea.
No, I'm kidding.
In May, on May 8th and 9th, there will be a Svelte summit in Barcelona,
which I'm very excited about.
I think you are excited about it as well.
It's a long time coming since the last in-person one was in 2022.
Yeah, I think it was 2022.
So it's going to be a lot of fun.
And we already have Rich Harris confirmed as a speaker.
Surprise.
So that's good.
I might send a proposal as well.
Yeah, you definitely should.
But conference-driven development is how we get shit done, right?
Yeah, yeah.
I mean, it was the case for Svelte 5, right?
I heard.
I'm not going to comment on that.
Okay, all right.
Okay, and with that, unless you have anything more to add,
then thank you for joining me for this interview.
Thanks for having me.
I'd like to invite everyone to try Svelte and have a really good time with it.
And probably check out the new environments API in Meet as well,
if you're interested in that stuff.
Of course.
All right, and to our listeners, thank you again for listening,
and you will hear from us again next week.
Hey, it's Kev here.
If you like the show, please drop a review on your favorite podcast player.
It would help out a lot.
Thanks.