Video details

Rich Harris - Svelte Cubed


Platinum Sponsor: GraphCMS -
Gold Sponsors: LevelUp Tutorials - Cloudflare Pages - Svekyll - Netlify - Vercel - Magic - FaunaDB - WPEngine -
Music By: Fractal -
About the talk: The other side of SvelteKit


Hey Rich here. I want to talk to you today about an aspect of Sfelt kit that is kind of flown under the radar. So far, we haven't really talked about it a lot, and it's probably not what you think of when you think think about Spelt Kit, but it's a feature. I really like that. I think kind of sets it apart from its competitors, at least for now. I hope they steal it. So a quick recap. For those of you who aren't yet up to speed, Spelt is the component framework. Spelt Kit is the app framework that builds on top of Spelt and gives you routing, data Loading, server side rendering, static site generation, beautiful developer experience provided by VIT, and so on. Lots of you are already using Kit to build your apps, because there is apparently no amount of this is not yet one point messaging that will dissuade you lot, and that's fine. We're all adults, and your feedback has been hugely beneficial. So keep doing your thing. But here's the thing. It's not just an app framework. It's also a framework for building libraries. And in the next few minutes, I'm going to show you how that works and what it means. So imagine you're building a page of a spoke at App. Chances are you'll have some mix of code that's specific to that page, code that's been imported from a third party library, and code that sort of sits between those two. The sort of thing that you might shove in a generic. Utools. Js file or something like that. Every app I've worked on has some concept of an internal library. In Sveltkit, there is a place to put the stuff that belongs to that third category, the sourcelib folder. There's really a convention. More than anything, it's not a magic folder. This Spelt kit does provide you with an alias so that you can import files from here without doing the whole slashdowns. Really, the idea is that you don't have to waste brain cycles figuring out where to put common utilities and components. And if you move from one Spelt kit project to another, it'll follow roughly similar organizational principles. Now imagine you're building a library for salt could be a component library or a new action function or something like that. You're going to need to try out your library in a sandbox app while you're building it, and you're probably going to want to build a demo site or some interactive documentation. Historically, a typical workflow for this is that you start building the library over here and NPM link it into your sandbox app over here. Or maybe you're fancy and you have a mono repo or something like that, and then you'll do the same thing when it comes to building out demos and documentation. The problem is that NPM link is the leading cause of boldness among open source maintainers. There's just something about it that makes you want to tear your hair out, like having to relink linked packages every time you install a new dependency. There are solutions to the problems called by linking. Take a drink every time someone shouts PM PM, but it's never going to be the ideal workflow. And then you have to think about build steps. If your library uses TypeScript, or if you're one of the hold out still using SAS in your spell components, then you have to account for that, and it all adds friction. But wait, if every app needs an internal library in every library needs a demo app, then why do we have two separate workflows? Why don't we use a unified approach and let you build the two things in tandem, and then give you the choice between deploying your app and releasing your library? The punchline, of course, is that this is exactly what Spelt Kit does. It's not an app framework. It's a toolkit for building apps and libraries. Demo Time let's create a new component library called Spelt Math. I refuse to yield to the American Math. It's short for mathematics. It makes no sense that you would abbreviate it that way. We're using the bare bones Skeleton app with Patch bridge and prettier preconfigured. Our first component is going to be an add a component that takes two props A and B and adds them for you. We'll create an add function that takes a number B number because this is TypeScript and use it inside our markup back in our root route. Again, I refuse to you to route, even though root route is a lot easier to understand than root route. We can import the component from Lib added to the page, give us some props, and confirm that two plus two is indeed four. That's cool, but if this code was going to be visible anywhere, for example inside the demo, then it would be nice if we were importing from Spelt Maths instead of Lib. We need to jump through some Hoops to make that work, but it's pretty straightforward, so I'll do it here. First we update felt config. Js so that V knows about the ABS. We need to resolve an absolute path, so I'm importing the path module. Then we need to update our tsconfig JSON so that Vs code doesn't freak out about a missing dependency. We'll need to restart the Dev server in order for this to take effect. Now we can update that Lib to Spelt Maths. When we create a new multiply component, we can import it straight from Spelt Math multiply six by seven. Then the answer is 42. So we could now do NPM run build to create an optimized production version of our app. But we could also do NPM run package, which will create a distributable version of our library. Let's take a look at the contents of the newly created package directory. We have our two component files, except that they've been pre processed, which in this case means TypeScript has been converted to JavaScript. We also have these declaration files so that if someone else imports components from Speltmass, they'll get type checking and autocompletion inside package. Json is copied over the relevant parts of the root package. Json, and it's added the exports field so that library users can import from Speltmathadotsfelt and Speltmathmultiplier spelt. Maybe that's not what we want, though. Maybe it would make more sense to use named imports rather than deep imports. Let's go back to the library and create an index file that re exports our two components. Now we and anybody else can import them in a single declaration. If we want to disable the deep imports, we can update the package export section of our Salt config. As. And now when we do NPM run package, the exports map no longer lists the components. Of course, our Democrat might still need an internal library alongside the one destined for publication, and we want to exclude those files from the package. We can do that by updating the package file section of Asphalt and Freak. Js. So now we have both a production ready app and an NPM ready package, and we could easily add a script to build and release both simultaneously. I've grown to really love this workflow, and I think you will too. All right, all of that was really just an excuse to show off the library I've been building with Spell Kit. It's something I started working on over the summer at the New York Times for our Olympics coverage. News organizations aren't allowed to show footage from the Olympic Games because the broadcast rights are jealously guarded. So if you want to announce the results, you either have to describe them in text or you have to find a way to show them. And so my friends and I built an app using Salt kit. Of course, that would ingest results data from the Olympics API and convert it to Twitter videos, and embeddable widgets. We chose to use Three. Js because, for my money, it's the best 3D library out there. But when you're building something under extreme time pressure, it's really useful to have a declarative component based approach to keep a lid on the complexity and give us extra features like Hot module reloading. In other words, in the same way we use Felt to keep our Dom code manageable, we wanted something to keep our three code easy to work with. Today I'm open sourcing the result of that work. It's a component library called Spelt Cubed, and you can use it right now. There is a caveat. It is not feature complete. The documentation has gaps. Some things will definitely change, but I know you people well enough to know that that won't stop you. So let's look at a couple of examples. I'm hoping to add more to this page soon, but I'm only one person. If you know your way around Three. Js and have some fun ideas, then please help come and fill this page up. Does the obligatory hello world. We can edit values in the control panel, which is provided by another Spelt kit library called Spelt Knobby, so you can play with the material properties. If you're curious about what the source code for this page looks like, hit the link in the bottom right. Another example tricelaris Some of you might have read the Three Body Problem trilogy. I've only read the first two books, so no spoilers. And it begins with this classic physics problem about the unpredictable motion of three bodies relative to each other. I implemented it in JavaScript, and the behavior is indeed very chaotic. What I like about this example is that almost all the code is JavaScript. Three component stuff is very compact. On the documentation page, you'll find a short tutorial for building a 3D scene from scratch. Let's build it now. We'll begin by creating a new Salt Git project, Mpmit Salt at Next and setting it up in the normal way. I'm going to copy over the status quo from the tutorial. The first thing you'll notice if you've used three JS in the past is how little code there is. This is the equivalent boilerplate if you were to write the same thing without Spell cubed. So far, it's not that exciting. Let's make it look a little bit nicer by enabling antialiasing and giving the scene a background color. Now let's add some camera controls so that we can interact with the Cube. At the moment, the Cube has the default material called Mesh Normal material, which is very handy for debugging normals, which are vectors that tell WebGL which way our face is facing, but probably isn't what you want in your app. So we'll add a material of our own using the color of the spell logo. Now that we're using Mesh standard material, which is physically based, we need to add some lights so that we can see it. We'll add both an ambient light and a directional light coming from the left, hence the minus two along the X axis. Let's have some controls. We'll add variables the width, height and depth and apply them to the Cube mesh using the scale property. Now we can have some inputs and change the values. Right now, Saltcube is only telling three to reread the scene when something has changed the dimensions, the camera angle, or whatever. Some frameworks will automatically rerender 60 times a second regardless, but Saltcube has more respect for your user's batteries. That said, sometimes we do want to update things on request animation frame, and for that we have the on frame lifecycle hook. Looking good so far, but we can Polish it up a little bit further. We can make the Cube cast a shadow, then add a horizontal plane for it to cast a shadow onto. We'll use the primitive component to add this grid helper to the scene. We need to enable shadows both on the canvas and on the light source. I'm going to customize the shadow map slightly so that it looks less blurry. Lastly, I'm going to add a fog property to the canvas so that the plane fades out gracefully. And there it is. That's all I got for now. There's lots to do still docs to write features to ad and if declarative WebGL is the sort of thing that you get excited over, then come on over to GitHub and we'll build it together. Thank you.