back

by tobr·8y ago·view on hn ↗
Maybe it's just the documentation that is lacking, but when I've played with Svelte, the API and template syntax feels like a hodgepodge of special cases.

For example, what exactly does a tag starting with colon mean? Is it just arbitrary syntax for things that don't fit in? What does a colon in an attribute mean? (i.e., why on:click rather than onclick or onClick or even something simpler like :onClick?) Why is there both {{#if condition}}<p>Content</p>{{/if}} and {{{condition && '<p>Content</p>'}}}? I feel like all these different concepts break the "it's just HTML" promise, when it seems like it could be simplified a lot.

Yes, JSX has similar gotchas, but at least it has references and specifications.

And what's up with the crazy semantics of computed properties?

Sorry if this sounds negative, but these have been genuine problems for me in getting a hang of Svelte.

3 comments
Colons indicate that something is a directive rather than an attribute — so `on:click` is the `on` directive with the `click` event, and `bind:thing` is the `bind` directive with the `thing` data property. The one place we violate that slightly is with `:foo`, which is shorthand for `foo={{foo}}` (since people dislike the ceremony of passing props down between components, and this makes it easier).

{{#if condition}}...{{/if}} tells Svelte something about the structure of your app. {{{condition && '<p>Content</p>'}}} doesn't, and you can't add interactivity to the <p> if it's just a string. Moreover, if `condition` is `undefined`, then that's the string that will get rendered to the DOM. Generally, {{{triples}}} should be used for blobs of HTML you get from data sources, such as a blog post.

If you can overcome your distaste for the computed property dependency injection, you'll hopefully find it's an extremely easy and compact syntax for declaring arbitrarily complex graphs of properties. The advantage of doing it this way is that Svelte can generate, at compile time, very efficient code for updating computed properties without any wasteful runtime dependency tracking. I realise it's slightly controversial (because it's a Svelte idiom, rather than something in JS itself), but for those who have embraced them, computed properties are one of the best features of Svelte!

The problem with Svelte's computed properties is that it's not just an idiom, but a completely new language that happens to look like JS. It does things JS can't, and breaks very basic things like functional composition.

Why not simply use the "correct" ES6 syntax to do the same thing? It's almost identical:

  computed: {
    hours: ({time}) => time.getHours(),
    minutes: ({time}) => time.getMinutes(),
    seconds: ({time}) => time.getSeconds()
  }
This way, the compiler could simply optimise idiomatic cases where it's easy to see which data is depended on, without breaking the language.
Interesting idea! I've raised an issue, thanks — https://github.com/sveltejs/svelte/issues/1069
At first, this looked like a bad idea but now can see the value but also see the ugly and less-friendly to newcomers angle.

Trouble is, coming from a Vue background (where computed props do not have to rely on a state item), the pre-requisite in Svelte to do so seemed at first a major PITA (then I saw the light/benefits and was actually easily able to re-work the Vue versions to Svelte).

Unless this is the only place Svelte goes slightly 'off-piste' in terms of JS then personally I'd leave as is, otherwise make the change

That syntax looks arbitrary and frankly, hell to mantain. The cost:benefit ratio of learning all these idioms ("idioms", a huge red flag) doesn't seem efficient at all. I apologize for being blunt, yet I still recognize your work as great for pushing boundaries in web development.

What made you turn away from javascript and into templates?

Simply put, you can do more with templates. It's the Principle of Least Power at work — the same way you can do more with a blob of JSON than a blob of JavaScript, templates allow you to do things that are basically impossible with JSX, such as compiling to a string concat function for server-side rendering that is much, much faster. Ask the teams behind Glimmer, Marko, and other tools, and they'll tell you the exact same thing.

We've basically covered all those idioms in a few paragraphs. There's very little extra stuff to learn. Now if I may be blunt in return, I was converting the React RealWorld implementation to Svelte for the purposes of this post, and there were moments that I spat out my coffee at how absurd some of it was — twice as much code, with some truly bizarre (but idiomatic-to-React) constructs. It's all a matter of perspective and familiarity!

Hi Rich, I notice you mention Marko. That was my first thought when checking out Svelte today - Marko uses somewhat similar approach, and thus brings somewhat similar benefits. But Marko has couple of other advantages - beautiful "concise" syntax option, and easy debugging at dev time as the Lasso bundler turns JS modules into equivalent files in the browser, complete with same line numbering. (It only works with CommonJS modules, but that's what I prefer to use anyway as it allows unit testing in Node without transpilation.) What advantages would you say Svelte has that would make me consider using it over Marko? Thanks.
I'd say it's a matter of personal preference as much as anything else. (Personally I'm not a fan of the compact syntax — I prefer just using HTML and CSS, but it's subjective.)

Performance-wise, you'll get great results with either framework. You mention debugging — Svelte creates useful sourcemaps, and the generated code is very readable anyway. Svelte has a few features you might find interesting (AFAIK Marko doesn't offer these, though I'm not intimately familiar with it):

* it can compile directly to custom elements * your styles are scoped to the component * declarative transitions * built-in global store (think Redux, but zero boilerplate) * useful element bindings (for e.g. customisable media players https://svelte.technology/repl?example=binding-media-element...) * computed properties. these are a lifesaver when you're doing a lot of complex reactive stuff

and so on. Also, I don't think Marko has an equivalent of Sapper.

Finally, while Marko is slimmer than the likes or React or Vue, there's still a runtime library you need to include on your pages. A typical Sapper page is about the same size as Marko by itself, before you've added any app code.

Thanks, sounds worth a closer look.
Just like anything, there's a small learning curve on syntax. Once you can get past your grievances (is HTML any less weird?), Svelte is extremely fast to build with.
I'd love an attributes syntax akin to riot.js, less noise and blends into html nicely.