jookyboi
5/10/2020 - 9:42 PM

Svelte has issues; let's talk

This is the second article of our series on Svelte. You can read about Svelte's performance advantages over React in our first post: Svelte is really fast

After working with Svelte, I've found a lot to be lacking. I want to make this clear: Svelte is fast, but my issues are related to its magic syntax and implementation details.


Svelte's docs... Meh.

React, and a lot of the tooling around it, has amazing documentation. It's clean, easy to read, and extremely easy to find what you're looking for. Their code examples are similar to those you'd use in your own code so there's less mental conversion necessary.

On the other hand, Svelte's docs seem to cover everything, but take a lot of searching to find what you need. They're ordered in a strange way like certain topics split into two sections at completely different areas of the table of contents. I often felt lost going through them when I was quickly trying to build a simple project.

Neither the API docs nor the examples have a search bar. That would be a fantastic addition, and something I've apparently taken for granted on reactjs.org.

Still, it didn't take more than a few hours to put it all together. A lot of that was mostly porting over React code. All in all, Svelte seems pretty simple to work with.

Magic syntax

I don't like magic in my code. Svelte does has code like this:

let count = 1

It takes that code and magically turns it into an observable.

It also uses JavaScript's label syntax, but what's clever isn't always understandable. It might just be how new I am to the syntax, but in my opinion there's a lot of magic around the $: syntax.

Let's not forget the magical word store which creates a subscription automatically based on the variable name.

From my experience with Svelte and other similar technologies, this kind of magic makes it so hard to know what's going on behind the scenes that you have to look at the transpiled output to figure out what's going on. This is especially apparent when debugging.

Transpilation woes

I had the same experience with CoffeeScript, Jade, Sass, and LESS. It's cool to work with higher-level languages that transpile into something that can be interpreted by your computer. But if you get into situations where you have to care about the transpiled output, then it's too complicated for widespread use.

Source maps fix a lot of the debugging issues from transpiling. These days, there are sites like svelte.dev and CodeSandbox that remove a lot of the friction when trying out a new library, and you don't have to install anything on your machine.

A transpile step means you can't write or paste that code in the console and test it out which means you'd need a code playground to figure out how it works. This is far less convenient, but it's not a complete deal-breaker. Make sure you're aware of these limitations before everyone on your team changes over to something new.

While I've had transpilation mishaps in the past, I didn't have issues with Babel or JSX. Almost all browsers today support newer ECMAScript standards so copy-pasting almost always works, and React has fantastic runtime error messages. On top of that, ESLint makes it easier to find syntax errors as you code.

Random Props

Even though many people are using TypeScript and Flow, the overwhelming majority use JavaScript (at the time of this writing). So then where's Svelte's hook into the PropTypes library? It doesn't exist. In fact, no semblance of a contract or interface exists.

Svelte has props all over the place. Sure, you can put them at the top like I did, but they're exports and not grouped in an object. This makes it kinda wonky when you're trying to add types when none exist.

While types aren't required, components need some sort of contract or interface for communication. With the ability to randomly export whatever wherever in the file, how are you supposed to know the component's API at a glance? As far as I understand it, you can't.

The only way around it is exporting a props object and wrapping it in a PropTypes check yourself. Sadly, this has to be manually performed in each and every Svelte component.

No TypeScript Support

While Svelte was written in TypeScript, it doesn't support creating applications in TypeScript. This isn't a problem for me as I still write in JavaScript, but since a significant portion of the industry has moved to TypeScript, this could be a nail in the coffin.

Since Svelte compiles away a lot of your code. This means it's parsing your JavaScript and doing something special. It doesn't parse your TypeScript, and if you write TypeScript and compile to JavaScript, that would be your workaround right? But you're not writing JavaScript either, you're writing Svelte files in a proprietary HTML format.

This is why official TypeScript support isn't so simple in Svelte.

Imperative is the norm

One of my biggest peeves with Svelte is its imperative approach. I've been doing functional programming for over 5 years and Svelte's examples opened up a time portal (hello 2014!).

It's not impossible to use functional programming with Svelte, but it's not the focus, and I couldn't find anything like it in the docs. If I first saw functional code in Svelte's simpler examples, it would've been an easier sell for me.

If I were to move to Svelte today, I'd be the outcast in a niche framework trying to jerry rig in function programming concepts. Good luck getting hired when you're the one guy doing it differently when the market's so small.

Because of the imperative approach, I'm afraid a lot of Svelte apps will remind me of the AngularJS, Knockout, and Backbone controllers of yore. Then again, it's not like you can't write terrible React components either.

As a caveat, I recently confirmed with Rich Harris, the creator of Svelte, that RxJS observables (any observable) is natively supported in Svelte and may provide a superior syntax to React hooks. While this is awesome, it doesn't change the fact that I'd be in an even smaller niche using RxJS with Svelte.

Svelte files are a proprietary HTML format

From my first impression, Svelte's proprietary HTMLx syntax is immediately off-putting.

Like most frameworks, HTML parsing is proprietary. To loop, handle if-else conditions, and render async code, Svelte has to have some way of coding these into static HTML.

Here's an example of a simple loop using the proprietary #each:

<ul>
  {#each items as item}
    <li>{item}</li>
  {/each}
</ul>

Unlike JSX, which allows you to write regular JavaScript in mustache tags to make your JSX Turing-complete, Svelte has its own way; something you have to learn from scratch that's not the same as other libraries.

While HTMLx does support putting regular JavaScript in mustache tags, you can only return strings. You cannot return an array of components like you can with JSX. To me, this is limiting, but potentially not as bad as I first thought.

HTMLx is supposed to make views easier to write, but I've had issues in the past with proprietary HTML syntaxes because they don't convert easily when you switch frameworks in 2--5 years time. Not only that, they're usually really difficult to debug because they're hacking around HTML.

The Svelte Data Store

Svelte has a number of options available for handling application state right in the framework.

While there's no action dispatch model, you can create a store and call functions on it similar to Unstated. With this, you can create little segments of state that you can share around your components.

This method is referred to as a custom store:
https://svelte.dev/tutorial/custom-stores

If you want something similar to Redux middleware, you can use derived. This function allows a part of state to be derived from another value in state. Think ko.computed from Knockout or merge in RxJS or useEffect in React.

An example of derived is getting the current time and a deriving the elapsed time from a start value:
https://svelte.dev/tutorial/derived-stores

Where is Redux?

A lot of people still use and like Redux. If you were switching from React over to Svelte, it'd be nice if your business logic could come along for free. Sadly, because Svelte uses the observable model (which is actually pretty cool), it doesn't have a 1-to-1 props conversion to allow using Redux.

Conclusion

Svelte really does seem like it's in the early stages. It's hard to find questions on StackOverflow or any articles on advanced usage. This makes it really hard to get into.

On the other hand, the creator and community around Svelte are really impressive. This is a full-on React competitor from all-in-one DOM libraries to native mobile apps; Svelte has it all.

If you wanna get into Svelte, it's pretty hot stuff right now. Let's see if that lasts. I'm very interested to see where it goes even though I have major issues with its current state.