Hacker News new | ask | show | jobs
by xrd 1073 days ago
The really exciting thing about svelte is getting rid of the virtual Dom. Having everything just be explicit JavaScript code that modifies the Dom manually makes for really readable code. If you have not tried it, got to the svelte tutorial and look at the output code. It's awesome.
4 comments

I don’t follow… in what sense is this JavaScript?

    <button on:click={incrementCount}>
Specifically, what is on:click? It doesn’t look like JavaScript, and it doesn’t look like the DOM. It looks like a new language which is specific to Svelte.

Or what about this… is this JavaScript?

    $: doubled = count * 2;
Or…

    {#if user.loggedIn}
      <button on:click={toggle}> Log out </button>
    {/if}
Or…

    <button on:click|once={handleClick}> Click me </button>
I am willing to believe that all of that is ergonomic in some way, but it doesn’t appear to me at first blush as very JavaScript-y, or explicit. I see a lot of black box stuff controlled by a declarative API.
> I don’t follow… in what sense is this JavaScript? > <button on:click={incrementCount}>

it's not. it's html. incrementCount is a pointer to a javascript function.

> Or what about this… is this JavaScript? > $: doubled = count * 2;

Yes. $: is a javascript label. We use it to indicate that a function should be reactive - if the count variable changes, the right hand will be rerun and double updated.

> <button on:click|once={handleClick}> Click me </button>

html again. the |once is a modifier to click which detaches the handler after a single use. It's a directive in the html markup (still valid html) which the compiler picks up and converts into node.removeEventHandler.

While this is all technically true, I don't think it's all that helpful a thought process to have when approaching Svelte. Yes, Svelte files are syntactically valid HTML, Javascript, etc, but they have very different semantics.

Take the ability to reference functions in HTML - this is simply not possible in normal HTML, where inline event handlers instead are passed Javascript expressions to evaluate. It's definitely a useful feature, but it's very clearly outside of the normal realm of HTML.

This goes further with Javascript: here the semantics differ considerably, with labels in normal Javascript doing nothing except when dealing with loops, and labels in Svelte are a form of reactivity. You've also got things like dollar signs interacting with stores, and other semantic differences.

As Rich Harris says, Svelte is a language.

<div onclick="handleClick">Click me</div>

100% valid HTML and within "the normal realm of HTML". The event is passed as a parameter to the function. Has been available since the introduction of JavaScript. Predates addEventListener(…) and its ilk by a few years.

Yes, "$:" as a labeled break exists outside JavaScript proper. That said, given the rare cases where anyone uses a labeled break and how unlikely that labeled break would be named "$", it seems a pretty safe extension to the language to allow such powerful behavior.

Both "$:" and "$store" are not magical; they are quite deterministic and serve to substantially reduce the total amount of boilerplate. Seems a fair tradeoff, but you are correct, it's a superset of the JavaScript language.

Now let's discuss the "naturalness" of useState, useMemo, and their ilk. I'll take Svelte's minimal "magic" over the verbose, repetitive, and error-prone library API logic, thank you very much.

> 100% valid HTML and within "the normal realm of HTML". The event is passed as a parameter to the function. Has been available since the introduction of JavaScript. Predates addEventListener(…) and its ilk by a few years.

Like I said, it's valid HTML, but it doesn't do what you're describing (and you can try it out fairly easily in your browser). The "onclick" handler executes the code string that it's given, working essentially the same way as `eval` or the `new Function("...")` syntax. It does not take a function pointer.

So in this case, the only thing it executes is a variable pointing to a function, which doesn't do anything because the function isn't being executed. You would need to add the function brackets to get any sort of effect.

This is the crux of the issue: Svelte is an additional language that happens to use the same syntax as HTML and JS, just with different (in some cases very different) meanings. You are not just writing "explicit Javascript code", you're writing Svelte code (which in most cases is probably very easy to pick up if you know Javascript, but it's still a different language).

Compare and contrast with, say, Typescript, which is syntactically different from Javascript, but semantically identical - just remove the types, and you have normal Javascript. (In fairness, with old decorators and enums, this isn't quite true, but it holds in general.)

To be clear, I don't think that's saying that one thing is better than the other, or that Svelte is bad because it's a new language or something. I think reactive primitives in Javascript are important, and adding them directly into the syntax of the language is a really clever way of solving a lot of problems in this space. I'm not sure if it's the solution I like the best (I've really enjoyed working with SolidJS signals recently, which provide some of the same ideas with a more typically Javascript-like API), but it's good to see experimentation here.

> which the compiler picks up

I think this is the crux of the gp's question. The browser doesn't support explicit behaviours for "on:click" or "|once" (the "$" label is a cool trick I'd forgive the gp for not recognising as native JS) - it may be "valid" HTML but it's not "just HTML" (nor just JS), it's a DSL.

It does support onclick though. This isn't a far off derivation. Also "|once" is a whole lot cleaner and more terse than the "once" variant of addEventListener, to be sure.

Anyone who already knows HTML and native event handling could pick this up in less than 5 minutes. Good enough.

Author means explicit after compiling.
Reminds me of Angular
Angular template syntax is correct HTML syntax. It's nothing like the examples abovd.
https://angular.io/guide/binding-overview

Haven't looked at angular since 2015 to be honest, but it still seems like they do weird html stuff to me, such as:

<ul> <li *ngFor="let customer of customers">{{customer.name}}</li> </ul> or <label>Type something: <input #customerInput>{{customerInput.value}} </label>

Angular will soon be migrating to the Svelte style of conditional flow control. https://github.com/angular/angular/discussions/50719
I agree with you, it looks weird, but my point was that it's correct HTML syntax, even though you cannot expect it to work if you open an Angular template in a browser, but an HTML parser can tell you it's syntactically correct.
> HTML parser can tell you it's syntactically correct

Which is completely useless because your website doesn't work anyway

This is true of Svelte's syntax as well, is it not?
Oh, that makes sense, I get you now.
You're telling me on:click={toggle} is nothing like (click)="toggle()"?
it's not. `toggle` is a pointer to a function name and "toggle()" appears to be an expression which is parsed and then executed (scary).

you can on on:click={() => toggle()} in svelte which is more similar, but it isn't parsed and executed, it is a pointer to an anonymous function which is directly executed.

on:click={toggle()} in svelte would run the function immediately (probably not what you want) and return the result as the handler for the on:click

so quite different, really.

Not a pointer to a function. In JS, functions are first class objects. You might as well say toggle() is an invocation of a pointer to a function.

<div onclick="toggle"> has existed since the dawn of JavaScript in Netscape Navigator 2.0 Beta Gold. Your complaint about the syntax is in fact baked into the foundations of the web.

One is syntactically correct HTML, and the other is not. That's was the only point of my comment
I haven't used Svelte beyond a couple toy tutorials, but, for me, the infrastructure adapters [1] are the most exciting thing. I love the idea of being able to build using Svelte and auto-magically deploy to something like Cloudflare Pages without completely giving up the potential to deploy somewhere else.

1. https://kit.svelte.dev/docs/adapters

I've got mixed feelings about this and I'm sure I'm in the minority. Those adapters are usually supported by the commercial company that wants you to use them. But, for example, the static or node adapters often don't work great with the important parts of svelte kit like SSR, and feel like second class citizens.

I love svelte but I'm having a hard time getting the same development ergonomics out of svelte kit. It's probably just me.

adapter-static is meant for generating fully static sites. It's fundamentally not aiming to and cannot support SSR in that context. However, SSR is fully supported in adapter-node, which is well maintained.
Infrastructure adapters are becoming table stakes for frontend frameworks.
Which other frameworks have them out of interest? Sounds like a great feature. AFAIK Next doesn’t and it’ll be interesting to see if it gets them given it’s from Vercel. When I tried Remix you had to choose your deployment when initialising a project and it didn’t look trivial to change it, but that was a while ago.
Solid & Astro.
First we were excited for the virtual DOM which is good for batching updates, flexibility, efficiency, etc. But now the cool thing is to get rid of it?
Never been excited in the least by it. Being too clever imho. Problem is: I don’t often get to dictate what we use so there I am, caught in the web.
not everybody was excited about the virtual dom. people who looked closely at it weren't particularly excited.
Browsers are not the same as they were ten years ago.
> Having everything just be explicit JavaScript code

This is funny because it's exactly the reason I prefer react

Agreed, I want markup in my logic — not logic in my markup
CSS and HTML in JS was always a bad idea. HTML can live on its own. JS is a dependent technology, on the same level as CSS. The HTML was always the foundational technology.

Centering JS has always been like putting the cart before the horse.

This seems intuitively right but doesn't really result in good outcomes in practice (I'm curious if you have any concrete reasons to justify saying it "was always a bad idea").

In practice what I've found is that HTML is fine/optimal for event-driven interactions layered onto entirely static content, but for inherently interactive UIs, what ends up happening is you get one of two systems:

1. If you start from a HTML-forward standpoint, you can go a certain distance separating your concerns entirely, but at scale the drawback is maintaining disparate references, negatively impacting code colocality: having to edit a reference in three separate files in a repo is incredibly bad for DX and readability. To overcome this, a common approach is to make the JS side generic by embedding DSL with dynamic functionality into your HTML: the worst of both worlds, creating both a Frankenstein HTML+weird-extras language and still needing to bundle JS with it.

2. If you're starting a greenfield project with the early intent of having a fully interactive UI, instead of growing into it, you can avoid the above mess and architect your project from the offset with good code colocality by embedding templates for highly dynamic/transient UI components into the imperative part of your application logic (i.e. the JS).

Svelte is neither a Frankenstein nor incredibly bad. In implementation, the compiler is JavaScript and there is JS bundled in the output. However, the developer experience is comparatively indistinguishable from plain old HTML, CSS, and JS in a substantially similar form to a static HTML page to the point where vanilla JS libraries can bind to HTML elements without modification. This is in fact how I develop for Svelte: I start with a static page, put in some elements and CSS to look like my design target, drop them into Svelte largely unmodified, and add if/each/await control flow.

I have yet to find a greenfield React project with more than a few developers over a few years that didn't turn into a big ball of mud that only the original developers could understand (at best). State management alone on React is an utter, total, and indisputable shitshow. Codebases with a mixture of classes and functional Hooks are far from ideal for developer experience.

Svelte code by comparison is a breath of fresh air both to develop as well as maintain. Whether Svelte wins or something inspired by Svelte does not matter as much to me as something that takes away the inverted JSX model, the virtual DOM, and allows the use of vanilla libraries without React wrappers interfacing with other React wrappers.

> Svelte is neither a Frankenstein nor incredibly bad.

"bad" is subjective I guess but "Frankenstein" can equally be applied to ".svelte" & ".jsx" - both are non-standard amalgamations of imperatives with markup. In my mind the qualitative differences here end up being in parser support (jsx as a js language extension, svelte as... I'm not sure... not quite a HTML extension but closer to it I guess) and output consistency: this is either dynamic output by the node server in Svelte's case, or perhaps a multifile static bundle with Sapper/SvelteKit; that bundle taking various forms depending on your bundler chunking plugin configs, etc. JSX in contrast is a line-by-line one-to-one simply defined translating to basic native JS render calls: it's eminently auditable and will work with an infinity of preexisting testing/parsing tools that support basic JS.

> I have yet to find a greenfield React project with more than a few developers over a few years that didn't turn into a big ball of mud that only the original developers could understand (at best).

I've seen this with Svelte and React in relatively similar measure (I've seen hundreds of large React projects, some elegantly structured but most a mess. I've seen <20 large Svelte projects, all much much younger, all but 1 a complete mess). All in all this is a problem with the development/developer landscape and not either individual project dependency. Contributor scale is a hard problem.

very interesting, i wonder what's your opinion on tools like htmx which work on the exact opposite basis
this!