sveltejs / rfcs

RFCs for changes to Svelte

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

New template syntax

akaufmann opened this issue · comments

Since Svelte v3 is on its way and questions the status quo in the UI framework world again, I just wanted to come up with an idea how to make the template more compatible with JS. Maybe it was already in discussion for v2 or v3, so please forgive me if that was answered.

<script>
  // v3 syntax (maybe)
  export const numbers = [1,2,3];
  export let canEdit = false;

  const promise = () => getSuperhero(heroId) // returns a Promise

  const showDetails = (enemy) => {
    // ...
  };
</script>

<template>
  await (promise) {
    <p>Waiting...</p>
  } then (hero) {
    <!-- You must use strings, because Javascript can go anywhere -->
    <p>`Hello ${hero.name}`</p>
    <div>"Enemies:"</div>
    <ul>
      hero.enemies.map(enemy => <li on:click={() => showDetails(enemy) }>${enemy.name}</li>)
    </ul>
    if (canEdit) {
      <a href=`/superhero/edit/${hero.id}`>"Edit"</a>
    }
  } catch (e) { 
    <p>"Superheroes are in trouble"</p>
  }
</template>

Pro:

  • The biggest advantage I see is that you already know JS and you don't have to learn special framework syntax (maybe "await" 😉) for e.g. control flow (something you keep hearing from the React community).
  • Compared to JSX it looks way better (IMO)

Cons:

  • You have to learn the new syntax if you're used to the old one.
  • Work (if possible) that @Rich-Harris must do to make this possible.
  • Maybe not the syntax that everyone loves.

What do you think? Is this something that would be possible? What disadvantage/advantage do you see?

commented

I think Rich is more interested in pushing for a HTMLx community spec than completely changing the way Single File Components work in Svelte. This would push Svelte even further away from what other frameworks are doing with SFCs which is probably the opposite of what we really want.

It really just looks like JSX to me but in a <template> element rather than a render function. We lose a lot of the visual landmarking that makes SFCs so great to work with: elements, control flow and directives all simply smoosh into one here (personal opinion). I think this is probably less approachable to newcomers as well (HTMLx is HTML+, this is JS+ : that distinction is important, in my opinion).

I also think there are probably some technical issues here that would make static analysis more difficult. Executing arbitrary javascript wherever you want in the template element looks like it would make getting the required information more difficult. Templates are compiled, not run; we need to be able to extract the necessary information without running the code. Rich knows more about this than I do but, at a glance, it looks like it might pose some problems.

This would push Svelte even further away from what other frameworks are doing with SFCs which is probably the opposite of what we really want.

I don't understand what you mean. Most frameworks use a different way of writing templates. What is the difference between...

{#if foo}
  <p>Hello</p>
{/if}

... and...

if (foo) {
  <p>Hello</p>
}

...for you?

Did you look at Vue? They use the template tag but use different control flows as Svelte today. There is no similarity. So where are we supposed to go any further? Svelte is already different. But what we should ask is "can we do better than the others". Is it really bad to use control flows that we already know, that we use in our script tags and could also be used in the template compared to some custom ones that you have to learn? The template tag would also go hand in hand with the script and style tags.

I think this is probably less approachable to newcomers as well (HTMLx is HTML+, this is JS+ : that distinction is important, in my opinion).

I think the opposite is happening. Look at the big three (React, Vue, Angular), they all have their own way of writing templates and unfortunately HTMLx won't change that. Why they have not adopted Mustache already? Because they want to come up with their own that fits better. But what all frameworks have in common is to write JS and this could convince users of React but also newcomers that know JS.

I think it's a great idea to use a unified template (HTMLx ) but also HTML will change (maybe with control flow, event handling, ... (1)) over the years and the standard may look different compared to HTMLx. Then where is the place for HTMLx (is theoretically I know)?

HTMLx is HTML+, this is JS+ : that distinction is important, in my opinion

Why not HTML + JS = HTMLx?

We lose a lot of the visual landmarking

Have you ever worked with a big complex Vue or Angular template? Find something like this between hundreds of tags if the syntax highlighting doesn't fit...
<div class="...." v-if="foo">...</div>

JS with HTML tags are great landmarks compared to custom tag attributes and even a cleaner version of Svelte's current landmarks.

I also think there are probably some technical issues here that would make static analysis more difficult.

Yep, that could be challenging. But I think React will heading in that direction (if they can make it possible - why should they still using the { ... } for control flows).

(1) The Angular team chose their tag attributes (e.g. (click)=...) because they think it's closest to the future of HTML.

commented

Most frameworks use a different way of writing templates.

Yes, they do but none of them allow arbitrary javascript anywhere in the template it is finely controlled. This deviates from that, in fact that is it's defining feature.

Did you look at Vue? They use the template tag but use different control flows as Svelte today.

Yes, and I disagree with their design choice regarding control flow. I think using directives to augment elements and components as well as dealing with control flow is a mistake. Having separate control flow syntax is clearer. I did say that my comments regarding having distinct syntax for control flow was personal opinion.

But I think React will heading in that direction

And you should look into how they hope to achieve that. It is a complex process and will take a long time to come to fruition. Facebook have lots of resources and even they have said that prepack will be a multi-year project.

I don't think this discussion will lead anywhere.

Thanks for the suggestions @akaufmann! We did have a fairly wide-ranging discussion about template syntax ahead of v2 — sveltejs/svelte#1318.

In that thread we discussed a number of ideas, including have a leaner block declaration not completely unlike the await (promise) { suggestion. Ultimately we decided that it wasn't the right idea, and landed on the current HTMLx syntax, which was carefully and painstakingly developed.

The static analysis considerations make things like hero.enemies.map(...) a non-starter — the reason Svelte is able to beat most frameworks in benchmarks is that the compiler has a deep understanding of a component's structure, which becomes impossible when you allow constructs like that.

Given how substantial the changes already are going from v2 to v3, I don't think it's wise to introduce additional changes to the template syntax without good reason, so I'll close this issue.

Many thanks @Rich-Harris & @pngwn for clarifying the current situation. I developed the idea because the HTMLx control flow in combination with HTML tags feels a bit inappropriate and (of course) JS doesn't make it any better, but because they are standards and JS control flows comes very close to the HTMLx control flows.

A syntax that goes even further towards Svelte's ideas (using standards) and what I hadn't suggested because it is different to the current syntax, would be HTML custom tags. And with VS Code v1.30 support for HTML custom tags and better tooling for that (https://code.visualstudio.com/updates/v1_30#_html-custom-tags-attributes-support), this would take Svelte a step further in that direction.

<svelte:if cond="currentUser">
  <div>Hello {currentUser.name}</p>
</svelte:if>

<!-- or -->
<template if="currentUser">
  <div>Hello {currentUser.name}</p>
</template>

<!-- or -->
<if cond="currentUser">
  <div>Hello {currentUser.name}</p>
</if>

<!-- It doesn't have to be like this, but you're getting the idea :) -->

But no matter if something like this ever comes to Svelte, I would like to thank you @Rich-Harris for your great work on Svelte/Sapper. It's just fun to work with and with Svelte v3 it gets even better.

@akaufmann that feels a lot like directives in Marko: https://markojs.com/docs/syntax/#directives. While Marko did bring some interesting ideas to the table, I find Svelte's approach to be more concise and easier to reason about.

@maxmilton thank you for bringing Marko to my attention. We did a POC and it looks really promising, especially the performance of the SSR and the features available for it. We are looking forward to what Marko 5 has to offer compared to Svelte/Sapper.