Zach Olivare - 2022 Jul 29
The highs, the lows, the lessons learned
I recently published the first version of Formsvelte, a complete form solution for Svelte; with an API inspired by Formik.
Formsvelte is the first library that I've created for the ever-growing Svelte ecosystem, so I thought I would share some of my takeaways from that experience.
Usually when you first sit down to write a new library, your first hour or two goes into configuring Rollup or some other bundler in a way that suits your needs. I started doing that, only to find out that SvelteKit has built in support for packaging a library! 🎉
I wanted my library to have named exports so that users could import all my components from a single path:
A couple different resources that I found online mention "re-exporting" your components, but it was unclear if I needed an index.ts
file or an index.svelte
file. I wasn't sure how it would work with an index.svelte
file and renaming the default during export didn't work either:
I eventually found that the solution is to first default import your components, and then export them; you can't do both in one step.
I wanted to create a store within the context of a wrapper component and then pass that store down to child components via a slot prop. My thinking was that this could be like Svelte's version of React's render props:
It turns out though that that's not possible. There is this bug on the topic (that was closed in favor of other bugs that seem slightly different to me, but I'm sure the maintainers know what they're doing), and you also get this linting error when you try to do so:
I'm hoping (as the linting error foreshadows) that this does change in a future version of Svelte. But in the mean time, I still haven't figured out how to get around this. It looks like it might be possible to implement Svelte render props as a clunkier version of what I was trying to do with slot props, so that will be the next road I explore.
In my experience with building reusable components in JavaScript frameworks, I've found that one of the most important attributes is to make them easy to style. The primary mechanism for doing so is typically passing around CSS classes. There are two attributes of Svelte that make this difficult.
Svelte has chosen to follow HTML in using class=""
to declare CSS classes, rather than following the React path and using className=""
. This is problematic in a JS framework of course because class
is a reserved keyword in the language. In terms of Svelte, that means to allow passing a class to a component, it requires two statements instead of the usual one:
You can't pass class names declared in a Svelte component to a child component without making it global. This seems silly to me. With CSS modules it is perfectly fine to declare a class name in a particular module, import it into a component, and then pass that imported class down to any arbitrary child component. With Svelte's locally scoped class names, the same is not true.
If you haven't tried it yet, take some time and thoughtfully go through the Codecademy style tutorial that the Svelte team has clearly put a bunch of time into creating. It's a really delightful experience and gets you up and running quickly with all the "quirks and features" of the framework.