Why Svelte is the most loved JS framework
Creator Rich Harris is back to teach us what's possible with Svelte and SvelteKit in 2023.
Links & Resources
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of "Learn With Jason," today on the show, we're bringing back Rich Harris. Rich, thank you so much for being here.
RICH: Thank you for having me.
JASON: I'm thrilled to have you back on the show. It is always a pleasure to talk to you. I love the way that you have approached kind of building for the web in general, so it's always a treat to get a chance to pick your brain directly. But for folks that aren't familiar, do you want to give us a bit of a background on yourself, who you are, what you do?
RICH: Sure. My name's Rich. I am I work at open source full time for a living, living the dream. I work for Svelte, I do Svelte full time. Svelte is a user interface framework that I've been working on for the last six years, seven years, coming up on seven years.
RICH: Made a bunch of friends, have been building it for a very long time now. And it's something that I built in a prior career as a visual journalist, so that I could do very quick turnaround interactive graphics in a news context. But it turns out if you've built something that works well in that environment, then you can build anything you like. So, Svelte and SvelteKit are these projects that allow us to build anything we want on the web, and I get to build it full time. It's what I do.
JASON: Yeah, so, I think I've heard a lot of people kind of explain, they've tried to articulate what it is they love about Svelte. I know early on the thing that I heard all the time was just the first class support for things like animations and transitions. You said you were doing that as part of building out visual journalism tools. It very clearly is more than an animation library by the way that people talk about it, and just seeing what it's been used to build these days. But I guess a question that I've always had is a lot of times what I've noticed when using tools is that a tool feels like it was built for a purpose, and then everything else got shoe horned in after the fact, right. And I get the sense that people don't feel that way about Svelte. That they feel very much like Svelte is the right tool for the job in a lot of different ways, and, so, I'm just curious. How did you approach designing Svelte, so it didn't feel like this is an animation framework that can be used for other things?
RICH: You know, the short answer is that we are really good at saying no. The shoe horning effect, it's real, it's very real, and I think what happens is and I experienced this firsthand. I very much used to respond this way to feature requests. You build an open source project, and you release it to the world, and you get your first users, and you're like, fuck yeah, open source. Then the feature requests start coming in. Hey, so, this thing is pretty cool, but it would be really cool if it did X. And, you know, we are kind of hard wired to seek approval. Sure, we can add that. I guess it makes the API a tiny bit weird, like it's a little bit after special case, but it's not that big a deal. We're just going to meet this feature request. And then another one comes along, and doesn't quite work with the other feature request. They are slightly at odds or you've needed to expand your API surface area, because you didn't come up with an API that can serve both use cases. If you do that enough times, you end up with a jury rigged monstrosity. I've done that in my own projects, seen it happen time and time again. It's really hard to turn around to people who are taking the time to engage with your project on GitHub, and who, you know, as far as you can tell, lovely people who, you know, you want to be friendly to. And say, no, we're not going to do that. But if you do open source for a long enough time, you will develop a little bit of a thick skin about this stuff, and you will learn the value of saying I understand why this is important to you, and I understand that what you're proposing seems like the most natural solution to your problem, but actually we're not going to do it this way. We're going to take this as feedback and input, and we're going to let it swirl around with all the other feedback that we get. And after a while, and it could be, you know, a week, it could be a couple of years, we will have an approach that we think solves this problem in a way that is coherent with the rest of the framework. And that is how we've approached design. It's a combination of saying no, and also just I think there is just an element of taste. We design APIs that we are kind of aesthetically drawn to. And, so, I think that's why it has that sense of things sort of feeling cohesive and fitting together opposed to being a mismatch of different ideas bolted together.
JASON: Yeah, I think that resonates with me on kind of like a philosophical level, right. I think one of the hardest skills to learn in any profession or vocation or calling is, like, when is the right time to edit this. Because there's so many ways to add ideas, and to think of new things, and to expand and expand and expand. But to make something good, you have to edit it. You have to cut things, right. There's that classic saying for writing of kill your darlings. And I think when it comes to API design or building software, a lot of times we forget how important it is to recognize that, like, a tool is built to accomplish a set of tasks, and if you make it too big, it kind of becomes a Swiss army knife where it's unwieldy and theoretically does everything, but hard to hold, doesn't do any of those things particularly well. You're like I'd rather get the purposeful tool. So, I feel like that is a good reminder to all of us to look at what are we actually trying to build. And why are we trying to accomplish things we're trying to accomplish, and, you know, does the thing that we're being asked to do now line up with the long term vision, and how do we get there in a way we don't break the long term vision for short term happiness and so on and so forth.
RICH: Yeah, the kill your darlings quote is a good one. It reminds me of a similar quote in the design field, I'm going to butcher this probably, but great design is not when there's nothing more to add. It's when there's nothing more to take away. When you've whittled it down to the bare essentials, which is not saying... not an argument for minimalism. It's an argument for breaking things down to like the smallest surface area that meets the goals. Yeah, a lot of times, like that's not what happens. But we, you know, we try to reject anything like beyond what we need.
JASON: Yeah. And, you know, according to the feedback at large, it seems to be going pretty well, because Svelte was, I think for the second year in a row, crowned the most loved developer framework out there. And, you know, we got to go with some caveats on the data, it's a small data set, biased dataset, et cetera, et cetera. It's pretty unanimous. I've never heard anybody say I hate using Svelte.
RICH: I have.
JASON: There's people that don't use it, but you don't hear people say this API sucks or whatever. I mean, granted, I'm sure you're very close to it, probably hear the worst of the worst.
RICH: I hear that all the time. You know, Svelte is, in a way, quite a divisive framework. We don't try to read too much into the data, because we are still quite small. And, you know, in the scheme of... so, like the top four frameworks, there's React... I forget which is second between Vue and Angular. Those are at the top. Then Svelte way down here, then another big gap, and then a bunch of others. We're one of the big four frameworks but not one of the big three frameworks. We're a pretty small user space. That naturally is reflected in the numbers, like the satisfaction among people who have chosen to use your thing is going to be higher among the satisfaction of people whoogot a job and is forced to use your thing. There absolutely are people who look at Svelte, I want nothing to do with this. And that's fine. We just have a slightly different philosophy on how these tools should look and behave to some of the other frameworks. And because of that, we are meeting a need that is not being met by other frameworks.
JASON: Yeah, as you're kind of seeing this come in, that is a good point, right. This is something that I've talked about in the past, and you've articulated much more quickly than I would about a lot of times what you see reflected in the hype cycle is a bunch of people who are choosing to learn something new, choosing to try something, and that agency gives them the ability to remain very excited about it. They'll suffer through things for the sake of their own exploration and curiosity. But if you take that same code and hand it to somebody, this is your job now, maintain this, they are going to have a completely different outlook, because their agency was removed, right. They are now being told you've inherited this pile of code. You didn't write it, don't know why it was chosen. You just keep it running because that's what you're paid to do.
JASON: I've watched that happen. We've watched that cycle happen a few times. I remember watching it happen with jQuery, with Grunt, Gulp, most recently Webpack. People were excited, then they inherited projects, I hate this, I'm going to change it to the thing I'm excited to try. They had high satisfaction ratings for that before they handed it off to the next person. I hate this, no, I want to try the thing I wanted to try. I guess there's an industry in this of rebuilding everything every few years, because everybody decides they want to try the hotness. So, you know, I think the thing that is interesting, okay, you said you've been working on Svelte for seven years now. How have you seen, like, are you seeing any of that, are people inheriting Svelte projects and struggling with it? Are you seeing that people are having an easier time, a harder time, picking up Svelte when they inherit a project down the road?
RICH: You know, we haven't heard a lot of horror stories, at least I haven't heard a lot of horror stories, about people forced to use Svelte on projects where they would have chosen to use a different stack. Candidly, I don't know that it's been around a lot that there are a lot of mature projects that people are coming into. It's still, if not individuals, then at least teams making the decision having looked at all the different frameworks that Svelte and SvelteKit are what they want to use. But, you know, it will happen. And we are prepared for that psychologically, and in terms of providing people with the materials that they need to understand how to operate. Like, we've spent a lot of time investing in interactive documentation, for example, so that people can quickly get on their feet if they are dropped into a SvelteKit codebase. And the entire framework is designed to be as self explanatory as possible. Numerous points we've made decisions that favor your understanding of the codebase, like over a period of time, over, like, the things that might get someone excited immediately and lead them to adopt the framework. We value retention over adoption, if that makes sense. We value people's long term happiness over, like, the GitHub star count or whatever it is.
JASON: Got you.
RICH: So, when it happens, it's not something that I think is going to phase us necessarily.
JASON: Yeah, yeah, that totally makes sense. So, the last time that we had you on the show, I think we were still a ways away from SvelteKit 1.0. I don't remember which version of Svelte we were working with. So, a lot has changed since then. And, I guess, this I'm not going to have you read the change log or anything, but what are some of the highlights for you that are new in the last, I think, year and a half, two years, since you were on the show?
RICH: So, it's been so long, I can't remember if we had started on SvelteKit at that point or we were talking about.
JASON: I think we had gotten past like SvelteKit was the thing, it wasn't Sapper anymore.
RICH: Right, right.
JASON: It was I think right around that point.
RICH: So, yeah, quick recap for anyone who doesn't know what these things are. Svelte is a user interface framework similar to, you know, React, Vue, whatever. Operates slightly different under the hood, but essentially solving the same problem. SvelteKit is an application framework, like Next for React, or Nuxt and Vue. It answers the what now question. You've got your component framework, but now you need to figure out server side rendering, structure, deployment story, how to deal with environment variables, how to set up a server, all that crap is taken care of for you by SvelteKit. Prior to SvelteKit we had a project called Sapper, which was aimed at doing the same thing, but we realized a couple years into it it was heading down the wrong path, so we started building on top. So, SvelteKit is our answer to the question how do you build an application with Svelte. It does all the things I just listed, and does so in we think a nice way. We think SvelteKit gives you a tip top development experience and also lets you build applications that are very fast, very robust, very resilient. And maintainable and pleasurable to work in. That's what new since we last talked. We have that, an application framework built by the same people building the underlying UI framework. So the two things fit together really closely, and we can sort of take advantage of the fact that we're developing these things in parallel. As opposed to them being two related but distinct projects.
JASON: Yeah, yeah, it is very cool to see that it's sort of like the same, like the same set of maintainers, right. You're kind of designing these things in tandem. Which is different, right. I don't think we've seen that in other frameworks.
RICH: It's becoming increasingly common in a way. If you look at Next, for example, people building it include React core team members. Andrew, Sebastian, Josh. There's communication between the React team, the Next team at Vercel, everyone is going in the same direction. The other end of the scale, Solid has Solid Start, although you sort of get the impression they were kind of goaded into building Solid Start, because Ryan is like I'm primitives, not building frameworks, but I guess here's a framework. So, there's like different positions on the spectrum, but I think we were maybe the first meta framework that was built by the same people as the underlying framework. Qwik is another example, Qwik and Qwik City built by the same people. Certainly wasn't the norm. And I think it is increasingly becoming the norm. Part of the reason is Vite makes it easier to do some of this stuff, because it abstracts a way a lot of the plumbing you would have to do otherwise. Everyone can build on top of Veet. So there's a lot we would have to do if building it from scratch that we just don't.
JASON: Yeah, yeah, that's absolutely true. To me that's exciting. Okay, I think we've decided as a community that this set of problems doesn't really need to be solved again. We can take this, we all agree that these are good APIs, let's roll. It felt Vite did the same thing around building frameworks, it unified everybody. This is great. We don't need to do too much to do this. Obviously, that's not all inclusive. There are other tools similar to Vite, and that innovation is still pushing in a lot of directions, but it was interesting to see how quickly people really did unify around Vite. No, this is a great way to build a framework, let's roll.
RICH: Solves so much decision fatigue. It's kind of a no brainer. It's not to say Vite is perfect or unimprovable, but it's so good that why would you bother doing all that yourself? Nowadays, if you're deploying your full stack, air quotes, because some people get squishy about that term. If you're building to one of the big platforms, Vercel, Netlify, CloudFlare, all of these places, you're using web standard APIs, like the fetch API, request and response, all of these things. You're using the same APIs you would have been using in the browser, you're not having to learn platform specific ways of doing things. Across the board we're seeing people consolidate on a shared set of primitives and differentiating on things like performance, developer experience, and all of these other things.
JASON: This is my favorite phase in the development cycle, we go around and around on this, right, but it seems like we have this moment where everybody converges on a set of ideas and then you get this sort of explosion of what we can do now that we're not wasting brain energy solving this one set of core problems, and then we spread out, and we say, okay, now let's argue about all the different ways we're solving this new set of problems that we had energy to think about now, then we'll come back together, somebody will come up with the abstraction we all agree on, and get the next layer of explosion. Feels like we're in that moment right now, where we're seeing a new huge swath of innovation spaces on the web that previously we were arguing about how to get things on the web, but it feels like with the advent of these really mature meta frameworks, things like Vite, platforms that just take away the thoughts of how do I put this on the Internet. Put it to Git, it's up, it's live. Don't worry about it anymore. And the lowered cost of serverless is free on just about every platform now, and getting a database is free on a bunch of platforms. There's so many ways for somebody to just have an idea and go try. It feels like we've sort of hit the next tier where everybody goes, okay, there's really no excuse not to try this. Then you build, and we're going to see a new kind of wave of, oh, I didn't think you could do that on the web. I feel like these are always the moments that are really interesting before we see something that kind of changes the game forever. I'm really looking forward to finding out what that is.
RICH: Yeah, there's a lot of whacky stuff at the moment about client server communication, or do we do client server communication. Some of that stuff makes me personally scratch my head a little bit, but as you say, it's an explosion and so many truly fascinating things happening, that you're absolutely right. Some of these are going to pan out, some of them not. This is just how we do it now. I'm just excited for you had Sunil on recently. We can start thinking deep thoughts about, like, how do we integrate real time into this stuff, because before you spent so long just getting to, you know, the bare minimum of what you needed, that you didn't have any energy left to think about realtime beyond bolting it on in a few special cases, but maybe that's the thing we can start designing frameworks around. So, yeah, it's a pretty great time to be a web developer.
JASON: It does feel like with the work that Sunil and companies like PartyKit are going to be doing, this thing that has become a big differentiator for a lot of companies, like Figma where their shared cursors and kind of real time collaboration, apps like Miro, so on and so forth. It's becoming... I think that's going to become less and less of a major differentiator and as you said, part of a framework. We see a way to throw together a collaborative app as easily right now as NPM create, whatever the framework is called, the way that we do it with Next, Svelte, or whatever. And I'm so looking forward to the chaos that's going to allow, because, you know, the ability to do things in real time and then to just play, right. It's going to open a whole can of worms in terms of safety and keeping people from completely abusing these systems. And it is also going to open up this huge world of play. And fun, and connectedness, that I think we kicked off out of necessity in the pandemic, in spaces like video calling, remote collaboration. Now let's take it further. What can it mean to really do live music over an Edge connection. What's it mean to play games that's solo latency like the same as I was sitting next to you. All of those things. We're this close.
RICH: Can I just point out two things. Number one, I don't know if you're paying attention to the Twitch chat, but Dax just raided you.
JASON: What's up, thank you so much.
RICH: Number two, we've been talking excitedly about innovation on the web for the last few minutes, and we haven't mentioned AI, how refreshing is that?
JASON: Yes. I mean, cool, I love some of the things that AI unlocks, but I definitely don't think that, like, there's so many things that we can do that don't require whatever they are called, LLMs. We can do so many cool things and have so much fun on the web and all it takes is imagination, not AI. And I'm very, very excited that folks like you and folks like Sunil, and, yeah, all these folks are building these primitives so I don't have to ever think about how do I set up realtime, how do I compile this component into something that works on every browser. All these problems that I used to have to think, you know, I'm not going to build that site. That's too much work.
RICH: Eliminate fatigue all together.
RICH: Here's the thing, there's two different types of developers. People like, apparently, you and I, although as a framework author, I don't know if I can include myself in this constituency, but developers that just want to build things that are fun. Then there's developers who really care about the nuts and bolts. Like yesterday, an internal refaction PR made the number one spot on the Hacker News, because internally rewriting same thing from the users perspective, exactly the same outcome, but people just love to get into the weeds of how this stuff is implemented. So, you know, it doesn't matter how many layers you compress into the foundations. There will always be people who just want to build all of this stuff from scratch. And I don't know if we can satisfy them, but that's probably not the audience that we're building for.
JASON: Yeah. I think, you know, as somebody who is formerly one of those, like I'm going to build this from scratch, I think that as I've gotten older, what I've realized is that the thing that I really enjoy is making something and watching people use it. And, so, I've started to categorize building in two ways. There's what I've started calling undifferentiated labor, which is the idea that I have to lay the foundation, get it on the Internet, set up CI/CD. All these things, exactly the same for every app. Got to have data up somewhere, a server up somewhere, code has to render in browsers. Nothing different about that. I could spend a lot of time putting effort into that, but what I'd rather spend time on is unique value, I want to build the feature set that I have in my brain that necessitated laying this foundation in the first place. And every minute that I'm spending doing something that I've done 100 times before, because I've built a lot of websites, I'm not building the unique value of this particular website. So, I'm really embracing this idea of, like, I don't ever want to do undifferentiated labor again. If I never have to read a Docker file, figure out how to get something scaling on Kubernetes or how to route an API gateway through a lambda to my database, I don't care about any of that. It doesn't differentiate my app. It's just plumbing.
RICH: Here's the question. What if the framework that you have chosen to do all of that undifferentiated labor on your behalf does some things in a way that you don't approve of? Do you at that point just live with it? Or do you try and get the framework changed, or do you just say, ah, this isn't what I had in mind, I'm going to reinvent some stuff after all?
JASON: I think that always comes down to tradeoffs, right. If they do something that is difficult for me to work with, or, you know, is against my morals, that's very different than if they did some change internally that I'm like I wouldn't have done it like that. Right. And I think there's a pretty big spectrum there between, like, I dislike the way that they've decided to change this internal that has no impact on the external API, versus they just broke my workflow, versus, you know, the founders did something that I cannot, like, I can't endorse. Right. So, depending on how you fall on any of those spectrum, then I think you, you know, you've got to make that choice individually. But for me at least, if I see a path to help, I do love to tinker, right. And if I see a way to actually improve the foundation of something, and it's not something that will take me months to wrap up on I know at one point I was trying to contribute to Jest, because there was a thing I needed. If I can put this in the core, that would really help. I could not figure out that codebase. You know, this was years ago. I don't know if it's been cleaned up since then, but it was so opaque I was like I don't have time to learn the whole codebase, so I ended up not testing that thing that I was trying to test. But in other cases, you know, I've looked at ways that documentation is a big one. I'm always down to try oh, just figured out a weird thing, I'll write some docs. But early on in codebase I love to do PRs when it's small enough and doesn't have the edge cases covered and abstractions in place where I don't know how any of that works.
JASON: To answer your question, it's a big giant "it depends," right.
RICH: It absolutely is. So the thing that I think you discover when you try and build something as reaches into as many different pockets of the developer experience as an application framework is that you simply cannot meet everyone's preferences. There will always be some aspects of the developer experience that some people are just I don't want this, this is not how I would do it. I wish those people well, because they'll go to a different framework and it will be something else that they don't agree with. Maybe you make things sufficiently flexible, everyone can bend it in their own way, but the flexibility kind of runs counter to the point of having the strong conventions and learnability of a framework. So, that's kind of the interesting phase that we find ourselves at building SvelteKit, is that because it does so much, some of the things it does, it does in a way that not everybody loves. But if we changed it, it would be to the overall detriment, because more people would not like the one thing that you changed. So, that's like a fascinating phenomenon that happens at this stage of development.
JASON: And I think so, one of the things that I noticed when I was at IBM is I was working with, you know, dozens of teams, and we were trying to change the internal culture toward different best practices. We had a microservices thing that was kind of multiple parallel monoliths and trying to clean this up. It required everybody to shift the way that they built a little bit. What I noticed was there were people who had just decided they were done learning and didn't want to learn anymore. No matter what we did, they were going to be unhappy. Some were happy, they understood the value, willing to put the work in, and then there was this group in the middle that I don't really have a good name for how to classify them, but the behavior that I noticed was that they didn't really like the work, and they didn't really want to build the thing that they were on the hook to build. So, they would really zero in on technical decisions as a way of procrastination. And I've noticed this across a lot of communities, where people will spend a huge amount of energy arguing opinions or arguing about minutia in frameworks or websites or whatever. Not because they actually care, but because it's more fun for them to argue about minutia than it is to actually go and build the thing that they are on the hook to build. And I think the hard part is trying to understand, or differentiate, as an author of a framework or as a creator of a tool, whether you are dealing with somebody who has a legitimate problem that is, you know, they are very excited to build and they are actually struggling, or if it's somebody who's just there to complain because they'd rather complain than work.
RICH: You just described the tailwind phenomenon.
RICH: Like a magnet for angry people on both sides.
JASON: Exactly, yeah, one of the things I repeat here a lot. Let's not worry about it. Go out and build fun stuff, because if you hand me Tailwind and that's what everybody chose for the project, I'm going to use it. If I make my own choices, probably not going to use it. Tech itself is fine, I just don't prefer that versus just writing CSS. But it's not because of some deep held moral belief. Whatever, preferences. Preferences are the sort of things that are worth having before they prevent getting work done. Then you find a compromise everyone can agree on and you move forward and build the thing. But it's not always that simple, because sometimes people are like I'd rather die on this hill than do any work. Okay. All right, we've been talking for about 35 minutes here. We've got about like 50 minutes left in the show, and if you're up for it, I would love to switch us over into paired programming view and let's actually bust out some SvelteKit and try this out. So, let me switch us over here to the paired programming view. And I'm going to just do a quick shout. We have Ashly with us today from White Coat Captioning. Thank you so much, Ashly, for doing the live captions. You can find that closed caption button down at the bottom of the player in Twitch right now. And that's made possible through the support of our sponsors. We've got Netlify, Nx, New Relic, and Pluralsight all kicking in to make the show more accessible, which I very much appreciate. Thank you very much to the sponsors. So, Rich, I don't know where the best place to start is, so I'm going to go to the Svelte homepage and ask you what should I do first if we want to try this out.
RICH: That is a good place to start. This website is actually going to get a complete overhaul in the fairly near future.
RICH: Yeah. So, the work is ongoing, and hopefully going to be fairly soon, going to get dark mode, among other things.
RICH: But if you scroll down a little bit to the code block on the right there, learn Svelte, there's code you can copy into your terminal, and that will show you the way. Alternatively, if you want to try Svelte and SvelteKit out without on your command line and setting up projects locally, then you can go to brand new interactive tutorial site learn.Svelte.dev, which is something that we properly launched about a month ago.
JASON: Let me drop this in the chat for everybody.
RICH: All right. This is going to set up a running SvelteKit app inside your browser, and you can go through the steps of this tutorial and learn about the different syntax in Svelte files, how Svelte components fit together, the features you can add to your Svelte components, and then it will take you through SvelteKit, how you structure an application with SvelteKit, learn about serverside rendering, rooting, all these other things. It does this in bite sized exercises that take everywhere 30 seconds to a couple of minutes to work through. None of it depends on the previous exercise, so you can come in, learn a concept, and step away. If someone wants to learn, this is ordinarily what I would recommend them to go. Go to learn.Svelte.dev and work your way through the tutorial.
JASON: Lot of positive comments in the chat, as well. People are yeah, just people saying it's best tutorial experience ever, says Yanneves. Yeah, tutorial just like knockout had, says parasocialFix? I don't remember.
RICH: Oh, good, Knockout, it's still live, I believe. See if I can find it here. Yeah, learn.knockoutJS.com. Knockout is... I don't know if it's the first interactive web based tutorial, but this was very influential for me when I was up and coming as a web dev. When I built my first, Reactive, it stole this format.
RICH: It's such a great way for people to learn stuff. Nobody really wants to break open the command line and start messing around. You want to try something immediately. Open a browser, tinker about, close the browser, everything is so easy. So, when we first built Svelte, we had a similar tutorial to this, which you can still see on Svelte.dev/tutorial. Now superseded by learn.Svelte.dev. Now we have this technology called web containers. If you're familiar with these, they are an interesting technology, basically lets you run Node inside your browser. Not emulated Node or anything. It's actually Node. So running inside your browser in a service worker. So, you can build applications that depend on Node tooling right there in your browser. And, so, this is enabled us to build a SvelteKit tutorial, in addition to a Svelte tutorial. So, you get a file system, you get server side rendering, you get all the stuff that would be so hard to build otherwise. It's literally running Vite inside your browser, which I nerd out about a lot. So, because of that, when you visit the page, takes four or five seconds to boot up, but after that, it's exactly the same experience that you'd have running SvelteKit locally.
JASON: That's just an incredible thing, thinking about how difficult it would have been to do something like this even a year ago, two years ago, right. It's really incredible, and I'm loving. This is a whole other area I didn't even think about when I was talking about big jumps forward. This idea of web containers. What's the other thing, fire cracker VMs. Just amazing stuff you can do that gets something up, it's just there, you don't have to install stuff, don't have to think about how you don't need to know how it works. You just get to start playing. I think that's powerful stuff.
RICH: Yeah. So, really excited about this site.
JASON: Do you want to work through the tutorial or something locally?
RICH: You know what, let's do something locally, because it would take too long to do a tutorial in its entirety. Maybe if you want to open a tutorial. NPM user, pMPM user? NPM create...
JASON: NPM create.
RICH: Svelte@latest. I do at latest. Okay, so, asking you where you want to create your project. Right now it will create in the current directly, which is probably not what you want, unless you created a directory specially.
JASON: I can't remember what we called the other one.
RICH: Few options there. We have a demo app, which has a few features we can look at without writing any code. We can do a skeleton project, which is a completely bare bones setup. Or the third option is a library project, which probably not going to look into today, but this is a way that you can build Svelte libraries using SvelteKit, which is different throughout the frameworks. We want you to use SvelteKit to develop things like UI libraries and other stuff.
RICH: Techniques you would use to build apps. So I recommend the app or the skeleton project.
JASON: Interesting, okay, okay.
JASON: At which point it... then everybody's got thinking to do on how we're going to approach this. If it's in the language, doing it the TypeScript way isn't quite correct. Is it TypeScript syntax making it in? Tell you what, we can Google that ourselves. Let's play with Svelte.
JASON: Got it, great. I'm going to follow the instructions, moving into the directory, I'm NPM installing, and then we will set up the init. Then I'm probably going to leave it there for now. So, make this bigger. And let's open this up. Why are you... All right. This is the wrong project. What am I doing? We want to be in this one. Here's our new project. Source code, route, we got an app, all right. Where should I start? Where's the first place to kind of look to familiarize myself with things?
RICH: So, the first thing I would do is fire up the dev server. So, I would bring up the integrated terminal, command J. Then npm run dev. All right. This is just going to launch Vite. 5173. This is your bare bones SvelteKit project. And that code that you're looking at, welcome to SvelteKit code, it's inside the source/routes/plus.Svelte file. You can find that by understanding the project structure and the routing structure are linked, but I'm going to show you a really cool shortcut that you can do for finding where elements are defined. Let me just double check how this works. So, if you go into your Svelte config.JS.
RICH: Okay. And then below where it says kit, add a new property called Vite plug in with a capital "P."
JASON: In kit or after kit?
RICH: After kit. Top level config property. Plugin. Then this is going to be an object with one property, inspector true. Okay, if this has worked correctly, now when you hover over the application, if you press command shift
JASON: Command shift.
RICH: Yeah. Then just hover over the elements.
JASON: Here? Oh... I thought it was going to be over here. All right.
RICH: Yeah. Then just click on an element. It will take you
JASON: Hold on. Let me close this so everybody can see what just happened, because that was incredible. I've seen people talking about this in a few frameworks, and I've never actually tried it myself, and that's incredible.
RICH: Yeah, this literally just came out of experimental status. So, this is like stable now. I'm actually wondering if we should have it default to true. The challenge, of course, can't find key bindings that are suitable for everyone. I cannot work without this. It makes my life so much easier. Pretty cool. This was built by Dominic on the core team, and it's fantastic.
JASON: Yeah, this is really, really good. Okay, all right. So, we're off to just a wonderful start here. So, we've got let's make some edits. We'll just say... reloading, all good.
RICH: There was a time when that would be like poof but now it's just like, well, using Vite, of course they got HMR. Just so nice that stuff like this is table stakes these days. I feel so bad for anyone whose framework does not work this way.
JASON: Yeah, it's really good. I got a question about Arc. This is because I'm in dev mode when you have a development URL, it shows you more controls. So, that's nothing special.
RICH: Oh, you're an Arc user, interesting.
JASON: I am. You know, I tried it, because it looked weird. And I can't give it up. Every time I go back to another browser, I don't know, I'm missing Arc features.
RICH: Man, I got to give it another whirl. I tried it for a bit. Just didn't stick.
JASON: You know what blew my mind on it, they implemented the tab interface for switching between your browsers. Just hit command tab sorry, control tab instead of command tab. Okay, I'm sold. Between that and the different spaces and stuff, I can't not have this browser anymore.
RICH: Yeah, that's pretty nice. All right, what shall we learn about first? Maybe let's you know what, I'm going to follow the structure of the tutorial, because that way I'm not going to miss anything obvious. So, the first thing that we'll do is create a new page. So, in your source routes directory. Create another directory. Then inside there we're going to have another plus page.Svelte file. And that's a special component essentially that says this is going to create a route of our application.
JASON: Okay. So, I can do something like about, and if I come out here, it just matches the route here.
JASON: Layout, if I can spell it right.
RICH: You'll see the page has gone blank. That's because our layout doesn't contain content for the page. So, first thing we're going to do is create a place for the page content to go. Do that with a slot element.
JASON: Like that. Okay.
RICH: So now it's just putting whatever your page is inside your main element. Above the main let's create a nav element.
JASON: Set like one of these. Then one of these. Then we'll... put in, let's see.
RICH: So happy you created an anchor, just HTML, just anchor tags.
JASON: Yes. That is definitely something that's made me very happy. I was trying to be clever and I deleted all my code. I had a render, but I don't know how to use it. There's our basic layout. We have a nav, we've got anchor components, and now we can move back and forth between links. Okay. Great.
JASON: As someone who has played that game before, I have definitely attempted to write my own like link preloading thing. And when I did some measurement on how much data was being sent that wasn't used, it was probably 75% of it. So, we ended up turning it off. So, I'm very grateful that, you know, the frameworks know enough about contents to be able to say this is important, this is not, load this, not this. That part has been hugely beneficial, I think, to the web ecosystem at large.
RICH: Yeah. And you can control it. You can vary the behavior for the entire app by having the attribute on the body, and you can vary it on a per link or per subtree basis, depending on what it is you're trying to do. Because in some cases it might not be appropriate to preload anything. Like if you're building like a stop tracking app or something, you want up to the second data, so only when you click you get that.
JASON: Got it.
RICH: All right. What is next? Maybe we should do some more interesting routing. We've got a route page and an about page, but very often the routes of your app are going to have parameters. So, for example, we might want to have a blog page, whether the post that you're looking at is a parameter of the route. And the way that we do that in SvelteKit is we create another directory. Blog slash, and inside that, something with square brackets in the name. Then inside that, we would have a plus page.Svelte component.
JASON: All right, there we go.
RICH: Put the content in there.
JASON: We can say like blog page. Anything that I hit here should work. So, blog/one. Then we'll do two.
JASON: If we want to show that it's working, how would one just put the slug in here?
RICH: So, we could put the slug directly in there. Or we could load some data. Let's do both, just so that we can see how this stuff fits together.
RICH: Inside here, create a script tag and add a Lang equals TS so we're able to write TypeScript inside here. And now I want to import the page store from dollar app stores.
JASON: Is that a named import?
RICH: It is, yeah.
JASON: Page oops. Page store like this?
RICH: Sorry, just page. It is a store, but it is just called page.
JASON: I got you, I got you. From app stores?
RICH: Yeah. All right, so, this is a Svelte store, which is kind of like a signal or observable or something like that. Basically an object that represents something that changes over time. And the way that we reference the contents of that store is by prefacing it with a dollar. You can replace that blog page with... if you just put some curly braces and inside that do dollar page.params.slug.
JASON: Now our page is coming in and whatever we hit is what shows up.
RICH: But that's not all that helpful. Obviously, you're going to need to load some data. Most likely, you're going to be loading data from the server, so that you can interact with the file system, interact with the database, something like that. SvelteKit does allow you to load data from external APIs instead, in which case you can have your data loading function happen on the server and in the browser, but for this we're going to have some data that only loads on the server. The way that we do that is by creating a separate module next to the page component called page.server.TS. Again with the plus. Yep. So, inside that module we want to create a load function. Do expert function load. Then we just want to return some data. We could return some hard coded data for now, like a title and a content.
JASON: All right.
RICH: Looks like you're returning an array there.
JASON: Do I not want to do that?
JASON: Okay, so, do an object. You said a title. We would say, you know, my cool blog. And then what was the other thing you said?
RICH: Some content. Whatever you want, really.
JASON: So, here's a good question. How does one approach content in Svelte? Is there do you do markdown, do you do are you expecting to import it from like a CMS that's going to give you back HTML? Are you getting content and having to mark that up yourself?
RICH: SvelteKit is completely agnostic about that. There's a lot of different ways to do this. And SvelteKit doesn't push you in one specific direction. This is the sort of thing that like you might build something on top of SvelteKit that enables you to do this in a really easy way. But, you know, I've seen people do it with markdown files, seen people do it with databases, with content management systems. There's really no right or wrong way to do it. You can have markdown as your pages. There's a project called MD specs, like MDX but for Svelte.
JASON: Right, right.
RICH: They are equally valid in our eyes.
RICH: Okay. I just want to highlight one thing on this module before we go over to the page. If you hover over that load function... oh, oh, you know what's happening? I don't think you have the Svelte extension installed maybe or maybe it's not up to date.
JASON: I bet I don't. Let me see. The official one here?
JASON: Is it up to date? Let me see, how do I check?
RICH: I don't know.
JASON: 107, I don't know how to tell if that's up to date or not. Tell you what, here's what I can do, I can quit VS Code and open again. And we'll see if that... now I get to play where the heck there it is. Okay, so, let me go here. And hovering. And we're just waiting for everything to fire up.
RICH: Interesting, okay. Something isn't quite working as it should. I'm not totally sure why. Let's move on and just try getting that data into the component instead. I think you are on the latest version, but might be some piece of setup that's not quite working. What I wanted to show you is
JASON: Here it is. I'm missing something. It says the Svelte for VS Code extension now contains a TypeScript plugin, would you like to enable it? Yes, I would like to enable it. Now maybe things are going to do what I want.
RICH: Okay, you see now you're getting in line documentation. That's because this is a framework with strong conventions, because you have this +page.server.TS file, we know what you should be able to export from that, and one of the things is a load function. And because of that, we can just type it for you. We don't expect you to import the types and type your return values, because we can just do that. It's the undifferentiated labor that you shouldn't have to spend time doing. And, so
JASON: This is exactly when you were talking about how the value of TypeScript is the IntelliSense and you don't want to deal with writing TypeScript, you just want to get the benefit of TypeScript. This is the world I want to live in, is the one where the framework is doing the vast majority of this, so that I get auto complete. If I get auto complete, that's really all I care about with TypeScript. And that's, like, no joke, that is why I adopted TypeScript, was that so things would auto complete for me.
RICH: Same, same. All right. So, back in our page. We've got to get the data from the server into the component. And the way that we do that in Svelte components is by doing export let, and then the name of the prop. And these page.Svelte components have one property, which is called data. So, hopefully, I'm crossing my fingers this will work. If you hover over data... it knows what it is.
RICH: Now inside your H1, you can replace that with data.title.
JASON: No dollar sign on that, right?
RICH: No dollar sign on that. It's just a regular prop. Below that, if you want to get the content, then you could do
JASON: Auto creating.
RICH: If you want to pass the HTML directly from the server, you can put after the opening curly brace, after HTML data.content.
JASON: After the open... do.
RICH: Curly@HTML, space, data.content. It will render that HTML.
JASON: Nice, okay.
RICH: Obviously, you want to make sure you're not doing that with untrusted data, because access. Yeah, there you go. All right. So... doesn't look like that's updating.
JASON: Stopped on the server when I restarted VS Code, so we're going to start that up again. There it is.
RICH: There it is.
JASON: Beauty. We don't even need this page anymore. I mean, that's simple. That's simple, that's very nice. And the conventions just kind of like knowing what stuff is, is also very nice.
RICH: Yeah. So, I'm trying to figure out what would make sense to cover in the remaining time. We could talk about more server side stuff, we could talk about how we do forms. We could talk about API routes. We could talk about middleware. We could talk about so many things.
JASON: Chat, if you've got ideas, please, please do hit us up. We've got a question about using form actions. Question about animation. Animation, I actually have a whole other episode that I did with Scott Tolinski on animation that I think is still accurate. Haven't been any changes in the APIs for animation?
RICH: No, no. Basically, Svelte itself is relatively unchanged in the last four years, it's actually one of the most stable frameworks out there. We are due for a couple of major releases this year, so may be some changes, additions to animations APIs towards the tail end of this year, but it's basically as it was when you talked to Scott.
JASON: Okay, three requests for forms, one for middleware. How does Astro and Svelte get along? Great. It's wonderful. Let's do some forms.
RICH: All right. Let's do some forms. Here's an idea. What if we create a form for making a new blog post.
JASON: Yes, absolutely.
RICH: Let's do that. All right. So, what's the best way to do this? Let's see. Create a new directory inside blog, call it new.
JASON: Okay, new.
RICH: Then another page.Svelte.
JASON: All right. Get over that for now. Put in create a new blog.
RICH: All right. We had a title and content before. Create a form, and inside that we'll have an input, name equals title, and a text area name equals content.
JASON: I made a mistake. I'm going to write accessible markup. Mistakes were made. Type, text. Get a name of title and then an idea title just to make that actually work. Then I'm going to copy/paste that whole shebang. Replace all of these with content. And that's going to be good enough. Then we'll give it a button, type submit, and save.
RICH: All right, if you were to enter some data in the form and hit submit, it would just stay where you are. It wouldn't actually change anything, although I think it would update the query parameters.
JASON: It should submit to the query parameters right now.
RICH: It should, yeah. By default, a form is really just a fancy link. Adds query parameters to whatever the defined action is. By default, the action is the current page, and it would just put the data in the form elements as query parameters when you submit. These are good for search functions. If you have a form that updates a search parameter, then it will reload the data, and it will put the new data into the page with your updated search results going to the server for that data if necessary. But then it will just update it in place. But that's not what we want in this case. In this case we want to actually mutate some data on the server, so for that we need to use method equals post.
JASON: What I like is that I knew that's where we were going, and I haven't written a form in SvelteKit. So, we're already leveraging knowledge I already have here instead of saying then you have to make this custom attribute that makes it into a post. No, do what you do in HTML.
RICH: That's very much the goal. At one point we considered adding like a form component to do this, but after a while we were like, why? No reason for that. That's daft. Just use HTML as far as you can. And you can get a long way. But now if you hit submit, then what's going to happen is you're going to get an error message. Because you can't post at this route. You have page.Svelte, and that's like a git route. If you do something not a git you'll get a 405 method not allowed. But that error message, no actions exist for this page, that's something we can fix. Inside your route directory, let's create another page.server.TS.
JASON: Inside new?
RICH: Yep. This time instead of exporting a load we're going to export const actions. And we're just going to have one action on this page. We're going to tall it default. Then inside there we're going to receive what's called a request event, which is an object with a bunch of different properties, one of which is request. So, if you type the curlies and then do request like that... exactly. And then inside here, this is where all our serverside logic is going to go. This is actually going to need to be an async function, because we need the data from the form and that involves doing an await.
JASON: Oh, I sure do... this is a function I assume.
RICH: Yeah. And, so, this is like all just web standards. This isn't SvelteKit stuff. This is all stuff that you can read about on NDN. Below that, const title equals data.get title. Content. For now, we can try just logging those out and making sure that everything's wired up correctly. We missed something here. We're going to need to add an import for the slug. Unless we want to
JASON: Oh, that's true. That's true. Let's do it. So, we're going to add one of these. Okay. And we could definitely derive this, but I think for the sake of ease and not watching me write a replacer function...
RICH: Yeah, slugification is all fun and games until someone starts throwing actions and characters at you and all that stuff.
JASON: Yes. I've written a couple, but mostly work, but I haven't actually tried them against an adversarial dataset.
JASON: Okay. So, we've got here we go. We've got a title slug and content, and we are logging that here. So, when I enter... when I fill this out, we should see it logged here, because it's on the server side, right. So, I'm going to do title, slug, content. And there we go.
RICH: All right. Data is on the server and it's reloading the page. But that's, obviously, not what we want. We want to save that data somewhere, we want to add it to our database, and then we want to redirect people to that new post. So, let's do that in a couple of stages. We could... I guess we could just store this stuff or do like a bootleg file system database.
JASON: I think we can just use memory for now. In a real solution, we would have a database we were working with, but for the purposes of demonstration here, we can just...
RICH: All right then. In that case, let's create an in memory database. We'll do that by creating a file called source lib server database.TS. And I'll explain each of those bits in part.
JASON: Is that right?
RICH: Yep. So, the lib part means that this is stuff that you can just access anywhere in your app by prefixing it with dollar lib. It has a built in alias that makes it easy to have code referenced from multiple parts of your app. The server part means that anything inside here can only be imported in modules that also run in the server. Anything in lib server or anything with a .server, .TS, .JS suffix can only be on the server. If on public facing code, your app will fail to compile. This is to make sure you're not accidentally leaking secret environment variables and things like that, that you're not accidentally including code in your bundle, just a safe guard that you can't break. So, inside here we can do, I don't know, const DB equals new map, or const blog equals new map, or whatever.
JASON: Yes, yes.
RICH: And then we could export a function called, I don't know, create that's going to take... yeah, our slug, our title.
JASON: Yeah, just like that. Then send in a title slug contents.
RICH: And then just add it to the DB.
JASON: And the key would be the slug. And then you want to send in our title slug.
RICH: Perfect. And then we could create another function, get, that gets a post from the slug.
JASON: Get slug. Return DB get slug.
JASON: Okay. Don't want to type them all. Any. That's not yelling anymore, so we've got the ability to I can import, and you said I import
RICH: You can. I think actually if you just started typing create, where that comment is, then it should auto import from lib.
JASON: Even better. Create, there it is.
RICH: Annoyingly, it has not respected the alias, but we can fix that.
JASON: Oh, it doesn't like my alias at all.
RICH: Database.JS not TS? Why is it doing that?
JASON: Great question.
RICH: TypeScript is funny sometimes. Looks like a squiggly there. Any ideas why?
JASON: It is saying it cannot find the module, so I think it's missing the alias entirely right now.
RICH: That's bizarre. This is supposed to be in source, right?
JASON: Yeah, yeah. I don't know why that is. Just a traditional live coding gremlins. Relative for now.
RICH: Let's see if it actually works, and if it doesn't, we can switch to relative.
JASON: Title, slug, content. We will say new blog.
RICH: Okay, so, hopefully that's now existing that's now in our in memory database. So, if you go to the blog slug page.server.TS there... then instead of returning that hard coded data, we can actually retrieve it from the database this time.
RICH: But we want to make sure that in the case where no data is returned, instead of just trying to render a nonexistent post, we actually take to a 404 page. So, maybe if we do const post equals get
JASON: How do I get that parameter out of the load function?
RICH: Good question. The load function receives a request event just like the action did. And one of the properties of that is params.
JASON: Okay, so, I can do...
RICH: Just params. The request is the standard request project, but the params is the you'll notice yep, it understands slug is the only parameter you can have here. So, if there is no post, then we want to throw an error. So, literally, type throw, lower case error, and then import that from SvelteKit. And 404 is the status.
JASON: Do I need to send a body, or can I just leave it as a 404?
RICH: It's fine. You can if you want to customize the message, but otherwise it will just throw a 404 error. After that just return the post.
JASON: So then what I should be able to do then is go to new post.
JASON: 404'd on us.
RICH: Didn't like that.
JASON: Let's see, is that what I called it? That's actually a great question. We're going to call this one test and say... put this into my clipboard. So then we should be able to go to test. And there it is. Okay, I screwed something up there, but that's fine. So, this is excellent. We've got the thing doing the thing.
RICH: We have, but we're not done yet, because right now we're posting that data and it's not taking us anywhere. It really should redirect. So, let's add a redirect, and then we'll just add the final touches to this one. Again, we're going to throw... this time throw a redirect. And it's going to be a 303 other. The location is going to be /blog/blog.
JASON: Now when we go to new, should be able to say anything, anything, and it does the thing.
RICH: It does, but we're still not there yet. In order to get to that page we have to do a full server reload, which it's fine, but it would be kind of nice if we could just update the content in place. And we can do that by just manipulating our form in a very small way. Back in the page component... if at the end of that form opening tag we add use colon enhance... then just import that in enhance helper. See it's added it. If you save, hopefully prettier is going to make it look less garbage.
JASON: I think I've screwed something up in my config here, which is not on Svelte. That is on me installing about 15 VS Code plugins per week for this show. So, my VS Code is garbage. This is not a reflection on the framework. Okay. So, we've enhanced. And now when I do this, we should see it should reload without doing a full refresh.
JASON: Yeah, I mean, we've made quite a bit of progress through something that, you know, I can see this taking an hour or more to just scaffold something like this, you know, if you've got to write all of this code yourself. Kind of gets back into that undifferentiated labor. We've all had to write form handling logic, and there's a bunch of stuff that I wouldn't want to do, like this redirect. I would just say, you know what, a full refresh is fine. We'll just reload the form and tell them that they can go find it in the blog list now.
RICH: Like you absolutely wouldn't be doing the speculative preloading and all of that other stuff.
JASON: No, of course not.
RICH: Life is too short.
JASON: Exactly. Life is too short to build this crap yourself. Go use a framework that does it for you. Okay, so, with that, we are at time. Rich, thank you so much for showing us even just a little bit. I feel like we could go for hours with all the features that just the chat was requesting. But, yeah, for folks who want to keep going, I'm going to push toward the tutorial. Where else should anyone go if they want to go further?
RICH: They should definitely come over to our Discord, Svelte.dev slash chat will get you over to the Svelte Discord. And our work is done in the open on GitHub. That's where we do all of the pull requests and we talk about new features. It's where people should certainly go if they encounter bugs or have feature requests. And they should follow Svelte Society on Twitter. Svelte Society is our sister organization, which does meetups, and conferences, and produces a lot of video content and other things. And it's a really great way to find out what's happening in the Svelte world.
JASON: All right. So, with that, we are going to call this one a success. Thank you one more time to Ashly from White Coat Captioning and to the sponsors, Netlify, Nx, New Relic, and Pluralsight for making the show more accessible. Make sure you check out the schedule, because we've got so much good stuff coming up. Make sure you hit that, hit that Discord link, hit the calendar, whatever it is that will make sure you don't miss any episodes. Rich, thank you so much. This was an absolute blast. Thank you all for hanging out today, and we'll see you next time.
Closed captioning and more are made possible by our sponsors: