1. 35

  2. 27

    So AFAICT this is the tradeoff the author consciously rejects, and the one that Svelte consciously chooses:

    • Choose writing in a JS framework that is compiled ahead of time, over writing in a JS framework that is interpreted at runtime.

    The disadvantages of this tradeoff that weigh on the author’s mind:

    • If your language is compiled, debugging is harder because the compiled code that is run does not resemble the source code you have to fix.
      • They also make the point that it’s confusing that Svelte code is Javascript, but it needs to be compiled to run it, which may change its behaviour. (To me that’s not that different from frontend framework code that is valid JS/HTML, but needs the framework runtime to run it, which may change its behaviour.)
    • If in the future more front-end-systems compile to Javascript instead of writing in it, it becomes harder to glue them together.

    I think it’s interesting to look how Elm solved these, because like Svelte, it is compiled ahead of time to small and fast JavaScript that doesn’t resemble the source code.

    Elm’s solution to ‘you have to choose between debugging the runtime JS or the source code’ is to go all-in on making it easy to debug the source code. In Elm’s case, it is an ML-family language with a type system that guarantees zero runtime errors (but won’t save you from domain mistakes, obv.), and with compilation error messages that are so helpful that they have inspired many other languages.

    Svelte, presumably, wants to remain Javascript, so a lot of error prevention becomes harder. They mentioned they want to add Typescript support. Or they could add source maps that relate compiled JS to the original Svelte code? Also, debugging compiled projects is a very old craft, it only really gets onerous if the problem is low-level or compilation is slow. I also note that Svelte compilation has a ‘dev’ flag that produces named functions, and also extra code that performs runtime checks and provides debugging info.

    Elm’s solution to the interoperation problem: an Elm module can expose ports (blog post, docs that external JS can send messages into, or that JS can subscribe to. So the ports form an Elm module’s public API.

    That still leaves the interop problem of styling the created components. If it’s you writing the Svelte, you can let Svelte do the styling (if Svelte is the whole system), or specify the right class names on the created DOM (if you’re writing the Svelte component as a subsystem). But if you’re reusing sombody else’s Svelte component, I’m not sure how easy it is to pass in the class names you’d like the component to use. Perhaps ‘support for caller-specified class names’ is even an open problem / blind spot in frontend frameworks in general?

    1. 8

      Good summary.

      In one sense, all of the hard-fought web knowledge that people may subconsciously pride themselves on knowing now becomes a stumbling block. Technologies like Svelte treat the underlying web runtime as something to be papered over and ignored. Much like compiled C, being able to debug the generated code is a needed skill, but the 1-to-1 correspondence between source code and generated code is not a guarantee, and it can be disconcerting to let go of that.

      I’m all for it. We largely ignore x86/x64 by using higher level languages and our code is better for it, even if slightly inefficient.

      Web devs love to talk of developer experience and progress in tooling. Something something…Cambrian explosion? ;)

      1. 10

        I think the author’s problem isn’t so much with it being compiled, but the fact that the source code looks like JS, but your assumptions don’t hold because there’s a lot happening to that JS so the end result isn’t anything like what you typed.

        1. 4

          Yes, I agree. Elm is a language that has its own semantics which are adhered to by its compiler. But Svelte takes the semantics of an existing language (JS) and changes them.

          I have that concern about Svelte too, though it’s not strong enough to change the fact that I’m still a fan and excited to see how Svelte evolves.

          1. 3

            Reminds me very much of the Duck Test https://en.m.wikipedia.org/wiki/Duck_test. Svelte walks like JS and talks like JS but isn’t JS. This is typically seen as a positive for those who judge their tools, at least partly, based on familiarity.

            1. 1

              That makes the article make more sense. That would be difficult to reckon with.

          2. 6

            Or they could add source maps that relate compiled JS to the original Svelte code?

            Svelte creates JS and CSS source maps on compilation - https://svelte.dev/docs#svelte_compile

            There’s also the @debug helper for templates - https://svelte.dev/docs#debug

            In practice I’ve found debugging Svelte to be mostly trivial and sometimes difficult. Dev tools will help close the gap but they’re not mature.

            For styling, style encapsulation is what I’ve seen the devs recommend, but nothing stops you from passing classes as props to components that accept them. (I do that a lot because I like utility CSS libraries like Tailwind) The biggest open RFC right now is about passing CSS custom properties (CSS vars) to components. https://github.com/sveltejs/rfcs/pull/13

            1. 1

              I think the tradeoff here isn’t about source mapping and the sort, but instead that if you take it as given that you’re going to compile your language, then you might as well through more language safety features in (a la Elm).

              That might be true, but the other sacrifice is familiarity. Svelte can be learned by a frontend dev very quickly and without much “relearning” fear. Instead, you get the cognitive dissonance problem of it being almost what you expect but, then, not quite.

              1. 3

                if you take it as given that you’re going to compile your language, then you might as well through more language safety features in (a la Elm).

                There’s a big leap from Svelte to Elm beyond just compiling the language. Elm has tremendous benefits, definitely, but it gives up seamless interop with the DOM, mutable web APIs, JS libraries, and future web standards. Elm has JS interop but only asynchronously through its ports. Purity and soundness are great but at what cost? (that’s a rhetorical holy war question, not worth discussing here IMO!)

                I think TypeScript has been gaining so much adoption largely because it makes pragmatic compromises everywhere, not just because people are resistant to learning Elm/Reason/PureScript/Haskell/etc, and when support lands in Svelte I’ll be less shy about recommending it to people.

                1. 2

                  Yeah, I think for most people in most cases, familiarity and ease are the bigger win. I’m not arguing one should use Elm, just laying out that continuum.

                  1. 2

                    Thanks for emphasizing that point. I think I underestimate the impact of familiarity and ease for many people.

                  2. 1

                    By seamless interop do you mean synchronous? I started trying out Svelte yesterday and found the dom interop to not be seamless as I was confused by the difference between <input value={val} /> and <input on:value={val} />

                    I think from memory that’s how you get an interactive input.

                    1. 2

                      I meant seamless but that’s overstating it. (except for mutable web APIs and JS libraries - interop there is generally seamless because of how Svelte extends JS) Anything that isn’t plain HTML/CSS/JS is going to have seams. Svelte minimizes them to a degree that some other frameworks don’t, like React and especially Elm. Vue is on similar footing as Svelte.

                      The nice thing about Svelte’s seams is they often reduce the complexity and verbosity of interacting with the DOM. In your example, it sounds like you want:

                      <input bind:value={val} />

                      (or simply <input bind:value /> if that’s the name)

                      At the same times Svelte gives you the flexibility to optionally use a “controlled input” like React:

                      <input value={val} on:input={updateValue} />

                      The equivalent in plain HTML/JS is not as pleasant. Elm abstracts away the DOM element and events.

            2. 12

              I think the whole conversation around “runtime” or “no runtime” is largely a distraction. What matters more to me is: does it allow me to structure my application in a better way, that is more maintainable?

              In my experience Svelte provides a higher-level abstraction than React or other web development frameworks. It successfully abstracts away from exactly how it works, and provides a logical mental model for how to build web components. Being able to use it for server-side rendering, client-side rendering, or a combination of the two with client-side hydration with no code changes is a breath of fresh air.

              The concern about inspecting the runtime is mostly a matter of: how buggy and how leaky an abstractionn is it? The fact that we have to do such things regularly is an indictment of the brittleness of most JavaScript frameworks (admittedly the fault is mostly not theirs). It’s extremely rare to have to dig into runtimes for non-web languages (Java, Go, Rust, etc). In my experience Svelte has been unusually stable in this regard, too; I think I’ve had to dig into the runtime just once so far (in several months of daily work with it).

              1. 3

                How is it a distraction? Being able to debug live is a serious benefit.

                1. 1

                  I tried to elaborate in the comment, but you can absolutely debug live with Svelte. The reason I think it’s a distraction is because Svelte succeeds quite well in providing a non-leaky and reliable abstraction, which means I don’t have to dig into the “runtime” or generated code; the bugs are at a higher level. The same way you rarely need to step into standard library functions in Go, Rust, Java, or C++, because they mostly just work.

                  1. 1

                    The same way you rarely need to step into standard library functions in Go, Rust, Java, or C++

                    Hm… But don’t we often have to step into our own functions? Svelte seems pretty water-tight to me when it comes to the actual separation of concerns, but low-level bugs in code can still occur. In my view, either debugging or something equivalent is required for these scenarios.

              2. 6

                I haven’t really done enough with svelte to have a good overview of it, and this blog reads like the author is in the same boat. Those issues are not immediate blockers to me, but maybe they are for the author. I guess I don’t understand the point of this blog, it’s an opinion piece without much of any meat.

                1. 3

                  I started using React about a month ago, and was expecting to hate it. I have an instinctive distrust for frameworks, but I have also heard a lot of whining and moaning about how complicated it is. Much to my surprise, everything just… worked? The declarative, functional style translated pretty much directly into a DOM with few surprises. Handling mutable state with useState() declarations mostly just worked, and was a far cry simpler than $watcher in Angular. I had to read a few doc pages for things like contexts and routes, but everything went surprisingly smoothly.

                  At this point, React seems pretty great as far as I can tell. Am I just naive and the real pain is yet to come?

                  1. 4

                    I really like React as well and have been using it since 2013. It has essentially stayed the same since then, with the paradigm it championed influencing the UI libraries of big players like Apple and Google as well. It has a clear API surface, and does one thing very well. The biggest recent improvement was Hooks, and it changed the game for me and many other people too. The team is also continuing to come up with novel solutions to some pretty hard problems that have been historically unaddressed by JS libraries, such as Concurrent Mode. Not that everyone has these problems of course.

                    It is one of the most mentioned keywords in job postings, and it’s here to stay. Your investment in it will certainly not be wasted.

                    With that said, I’ll play the devil’s advocate and try to answer your question:

                    It is not a framework. When viewed from the eyes of a novice, or someone who bootstraps a lot of projects, or onboards a lot of new developers, the lack of conventions are quite tough. Every React codebase I’ve seen are wildly different, from state management to styling to code conventions to project structure to… you name it. In the end, for a frontend library to not even have a good solution for things like styling and routing is pretty out there.

                    This didn’t stop it from getting to where it is of course, and more complete things like Angular, Vue etc have been suffering from backwards-compatibility issues in this fast moving platform, language and ecosystem. I read a quote by Vue’s author in which he said that (paraphrased) he likes Svelte’s approach, he would’ve liked to adopt some of it if not for backwards compatibility. And just a few moments ago Vue was the new hotness.

                    When I bootstrap my own projects, I love it. I get to engineer my application just the way I want for the problem at hand. Usually choosing ReasonReact. But every time I join a new team using React, I have to learn everything from scratch, and a lot of your knowledge, war stories, preferences don’t transfer. Right now “we use React” tells me just as much as “we use Lodash” about a company’s engineering culture, programming paradigm etc.

                    It’s also very easy to get overwhelmed with the sheer amount of choices you have to make, usually in a group of people with different opinions and experience, from the start and at every step of scaling your app and your team.

                    1. 2

                      So what you’re saying is: Hell is other engineers. Guess I have our lead web guy to thank for how easy it was get to started with our React app.

                      1. 2

                        Just that when it gets bad it can get very bad, and there’s nothing in JS and its ecosystem that stop you from building projects that drown in tech debt, horrible performance, and completely go against React’s programming paradigm. You basically have to learn everything the hard way, or have awesome people in your team. For some the answer is more hand-holding and out-of-box featureful frameworks. For me it was using functional and immutable-by-default languages to use it at its best, and skip all the bad parts of JS.

                        1. 2

                          Just wanted to second @osener. I’ve been using React since 2015 across 3 companies and it felt quite different at each. Routing was different, state management was different, etc. Given all that, React is still my number 2 choice for web apps.

                  2. 1

                    I find these claims to be misleading & there are a couple of things that make the whole approach unappealing to me. Neither are absolutely disqualifying, but they make me hesitate to recommend Svelte to people starting new projects to learning [sic] front-end development.

                    I completely agree. I wouldn’t recommend Svelte as an introduction to front-end development either. I see it as an interesting alternative to React, Vue, et al but I would suggest a more mainstream language for someone learning front-end development. There are more learning resources, answered questions, and people who can help if you choose something more mainstream.

                    1. 1

                      Compilation is so popular in js world nowadays (even react does it with jsx) and macros are quite popular in some other languages (downsides of macros are well-known but every lisper praises them). So I doubt if such techniques are highly overused in Svelte.

                      BTW, this reminded me of sweet.js, very old macros implementation for javascript.

                      1. 1

                        Somehow the rant reminded me of Mint which compiles down to Javascript, embedding the Preact framework. It doesn’t pretend to be JS though which is nice. :)

                        1. 1

                          Svelte and Vue look cool, but I have no appetite for fancy JS frameworks anymore. React, and other libraries on different platforms using the same model of building UIs, stood the test of time for me. I’ve used React in production with apps written in Reason, Clojure, PureScript and TypeScript, and was always free to design and build my applications however I want.

                          I guess it’s the same tradeoffs that are in play when deciding for or against Rails. Made worse because of a fast moving platform, language and ecosystem though.

                          1. 2

                            I have no appetite for fancy JS frameworks anymore. React, and other libraries on different platforms using the same model of building UIs, stood the test of time for me.

                            The fact that React doesn’t count as a “fancy JS framework” to some people is kinda boggling to me.

                            1. 2

                              Well, React is 6 years old and working with the library is pretty “boring” compared to the major JS web frameworks that have come since.