RE: Pain and Tears in Svelte 3

Instead of the foreword



This post is a response to yesterday's article “Pain and Tears in Svelte 3” and appeared as a result of a very “plump” commentary on the original article, which I decided to design as a post. Below I will use the word author to refer to the author of the original article and allow myself to make some clarifications on all points. Go!







Who is Svelte?



When I saw the title of the original article, at first I was very happy. Right now, I think, I’ll read some deep and constructive criticism. And most importantly, interesting cases with pitfalls are not from "couch experts", but from the guys "who could." After reading, enthusiasm diminished, but thanks a lot vds64_max for the article.



Despite the fact that not everything worked out, I think I need more articles describing real problems and their solutions in Svelte. At least that he did not lag behind more eminent comrades, such as React or Vue. After all, in the end, readers may have the feeling that Svelte is too perfect, and this is certainly not the case.



Tutorial



I did not understand what the author had in mind in this part. Tutorial worked and works great. I suppose that the author only superficially got acquainted with him because of the deadlines of his project and could not understand the principle of work. There have already been cases when people did not immediately grasp the meaning of the step-by-step tutorial, when in order for the example to work, you need to do some action. Try it yourself!



UI Kit and Styles





Finding a UI Kit for Svelte was a separate pain for all of us. I wanted to exclaim: “At least Material, Bootstrap ... at least something ...”.


Firstly, far from all projects, in principle, UI whales are applicable. Secondly, not all UI kits for other frameworks work well.



The main problems begin when the project has a very confused and custom design, and whales usually still have limited means for customization. If we are talking about the admin panel, I agree that having a UI kit is useful, but not everyone writes the admin panel, and the profit from Svelte for backoffice will not be so noticeable.



The link can also be found with other UI whales for Svelte.



Due to the fact that Svelte works with the DOM “in a different way”, MaterialUI began to get out all sorts of nasty things related to how the UI components that are added via js to dom are displayed. For example, a simple spinner is displayed every other time:


I did not understand what the beginning of the sentence means and how exactly “in a different way” Svelte works with the DOM, but in general the whole thesis sounds, at least, not seriously. If you try to integrate a third-party lib that works with the DOM into any of the frameworks (React / Vue / Angular / Ember) that control the DOM, the exact same questions will pop up. Immediately there is a feeling that the author never did this.



Moreover, Svelte has a wonderful mechanism called actions , with which integration with any third-party DOM is reduced to writing a small function. It seems that the author has not read the dock until this moment. Well, it happens.



For example, an implementation of MDCSlider in 2 minutes: REPL





Tell me, please, where is it much easier?



Stylization



With styles everything is very clear, we stuff all the styles in like in Vue. You write the style and everything is fine, and then write a UI component (since you do not have UIKit) that should take props parameters, for example width and height, and logically do it like this:

...

And ... no, in the style you can’t insert variables.



As far as I know, in Vue the state cannot be used inside component styles either, and in React there is no work with styles out of the box at all.



Although, I can understand the desire to use dynamics in styles, but there are a number of reasons why this should not be done:





Alternative ways to use dynamic styles in Svelte:





And since Vue was mentioned, let's compare the use of dynamic inline styles:



<button v-on:click="fontSize++">Increase font size</button> <button v-on:click="fontSize--">Decrease font size</button> <p v-bind:style="{ fontSize: fontSize + 'px' }">Font size is: {{ fontSize }}</p>
      
      





 <button on:click={e => fontSize++}>Increase font size</button> <button on:click={e => fontSize--}>Decrease font size</button> <p style="font-size: {fontSize + 'px'}">Font size is: {fontSize}</p>
      
      





REPL



In general, I don’t see any special differences, but for some reason the author believes that everything in Vue is good in Vue, but not in Svelte. This is strange.



By the way, with the help of reactive declarations, it is quite convenient to collect all dynamic styles in one place:



 <div {style}>....</div> <script> let fontSize = 10; let color = 'red'; let width = 50; $: style = ` font-size: ${fontSize}px; color: ${color}; width: ${width}px; `; </script>
      
      





Usually this is enough for 99% of cases, and the rest is solved using themes and / or css custom properties .



Routing and Routers



In general, Svelte is a UI framework and it is agnostic to a router. Moreover, the external Svelte api makes it easy to integrate any independent router in just a couple of minutes and lines of code. For example, page.js :



 import page from 'page'; import App from './App.svelte'; const app = new App({ target: document.body }); page('/posts', ctx => { //     dynamic import & code-splitting app.$set({ ctx, page: import('./Posts.svelte') }); }); page('/', ctx => { app.$set({ ctx, page: import('./Home.svelte') }); }); page.start(); export default app;
      
      





 <nav> <a href="/">Home</a> <a href="/posts">Posts</a> </nav> <main> {#await page} <p>Loading...</p> {:then comp} <svelte:component this={comp.default || comp} {...ctx} /> {/await} </main> <script> export let page = null, ctx = null; </script>
      
      





Is it that hard? The author only encountered problems with a specific implementation, a specific router. Which, in addition, to put it mildly, is not the best of what is available for Svelte, since it copies the React Router with all its problems. You can find many other routers here .



Mistakes



Unlike React, which simply will not let you create a bundle and will scream strongly about an error, Svelte will perfectly collect everything with an error. At the same time, if you forgot something, install npm install or export, everything will be fine and just show a white screen (Incidentally, this was the case in the first versions of React).


React does not collect anything for you. Collector collects. In this case, I’m wang that the author worked with Rollup and most likely did it for the first time. It seems to me that it makes sense to either study the tool that you are going to use, or not to use it. I’ll add from myself that what the author writes about is not observed in Svelte. At least some problems arise no more often than in other frameworks. Most likely, for other frameworks, the author has already set everything up and worked, but here he was just too lazy to do it.



There is an assumption that the author also meant working with props, which in Svelte is carried out through exports from the component, but even here a warning will always be displayed if you try to throw props not defined by the component:





Svelte just needs naming convention



You will encounter this problem quite often - with the absence of a naming convention.


I really liked this phrase, because in essence it can be used for any project / library / programming language. The guile here is that in the same way you will come across this everywhere. For example, in the same React:



 class MyComponent extends React.Component { constructor(props) { super(props); this.dialog = null; this.loading = false; this.pins = []; this.stitch = null; } render() { return <dialog ref={el=> this.dialog = el} class="mdl-dialog» />; } }
      
      





In general, everything is the same and it will be necessary to somehow "understand" what is the refk on the element, and what is the object for working with the backend or the download flag. It would seem that if you have a team that did not meet yesterday, all these issues should be resolved long ago.



In general, of course, if your project and team do not have a naming convention, then Svelte will not help you. Some things that I use in my projects:



 <!--  ,      --> <Modal {open}> <!--      --> <!--  ,     ,      --> <form on:submit|preventDefault={save}> <!--  ,   --> <input bind:value={firstName} placeholder="First name"> <input bind:value={lastName} placeholder="Last name"> <input bind:value={birthDay} use:asDatepicker placeholder="Birthday"> <button bind:this={btnEl}>Save</button> </form> </Modal> <button on:click={e => open = true}>Open</button> <!--   --> <script> //     //  -  ,     import Modal from '~/components/Modal'; //     `as`,   `use:as<something>` import asDatepicker from '~/actions/datepicker'; //    -  observerable,    cycle/rx import user$ from '~/stores/user'; import { saveUser } from '/api'; //     let firstName = '', lastName = '', birthDay = ''; let open = false; let btnEl; //           let refs = {}; //       async function save() { const patch = { firstName, lastName, birthDay }; await saveUser(patch); $user$ = { ...$user$, ...patch }; } //          export { open, save }; </script> <!--   --> <style> /* ... */ </style>
      
      





In addition, usually my components have a “budget” of 200 lines of code along with the styles. If a little more - not scary. If it’s much larger, I create a folder for the component and start putting parts into separate files using svelte-preprocess , starting with the styles. In this case, the collector is configured so that imports do not change.



What has changed where and who did it?







As a result, you quickly write the components, but it is very difficult to understand what the junior wrote in this “Venegret” a few days later when he already forgot (sometimes even his name). Because of this, it will be impossible to understand what is inside without a clear organization of the code within the project or team.


A funny thesis, and most importantly, again applicable in general to any framework and project. Moreover, the syntax of hooks in modern React, so beloved by the creator of Vue that he even decided to urgently implement it in Vue 3, will have all the same collisions:



 import React, { useState, useCallback } from 'react'; function MyComponent() { const [ loading, setLoading ] = useState(false); const [ status, setStatus ] = useState(0); const [ pins, setPins ] = useState([]); const ReloadPins = useCallback(async () => { setLoading(true); setPins(await getAllPins()); setStatus(0); }); return (<div></div>); }
      
      





vs



 <div></div> <script> let loading = false; let status = 0; let pins = []; async function ReloadPins() { loading = true; pins = await getAllPins(); status = 0; } </script>
      
      





As you can see, everything is the same, only 2 times more scribbles.



Just kidding, of course, nothing is clear. Moreover, the state is not even clear, or is it just an auxiliary variable. In React, this is decided by state, which at least somehow brings clarity.


In fact, there is no point in “understanding” which component state variable is used in the template, and which is necessary only for the script to work. In Svelte, there is no such separation at all, variables usually live JS lives there - they exist in their own scopes, some have a whole component scope, others live within a single function or another block of code. Nothing new or unexpected. It is important to understand only one thing - the DOM is recalculated only when the associated part of the state changes.



For example, in the same React, if you do:



 this.setState({ foo: 1 })
      
      





and foo is NOT used in the template, the VDOM mechanism will not be able to understand this in any way and will produce rerender / reconcile. Did you know about that? Therefore, it is probably important in React to understand what is used in templates and what is not. At Svelte, we are free from such unrest.



As a result, here I can only echo to the author - if your project and team do not have a clear organization, you will have problems with any tool, on any project. Actually, an example of the author’s project is a direct proof of this.



Bind Stitch



Of course, this is due to the collector. The author should not be so frivolous about the new tool. By default, Svelte comes with Rollup, which out of the box supports much fewer features than Webpack, but it collects more optimized and more native bundles. Any additional functionality can be customized using plugins. If you don’t feel like taking a steam bath, then you can take the official template for Webpack , or any other from the community , since there are a lot of them.



Why do you need Svelte?



At this point, I will be more brief - for any new projects for which React or Vue is enough. It makes no sense to compare with Angular or Ember, because these are frameworks of a different scale.



Based on the latter, I don’t understand at all why Svelte maintainers are going to make TypeScript support? We love Svelte just for “shooting at the legs” and TypeScript in my opinion is like all-terrain tracks for the Svelte sports car. And you know, after working with Svelte, I realized how much JS has changed in recent years, and that it is no longer JS.



Svelte gives the opportunity to work in the same old and lamp JS, without PropTypes, Flow and TypeScript.


I can not disagree with this statement. In fact, TS is not really needed in Svelte. Although there is partial support for it with the help of preprocessors (without taypechek templates), but in general it is more of an appendage than without which you can not write good components.



Why NOT Use Svelte?



  1. If your project is already written on another framework and works reasonably well. No need to run and rewrite it.
  2. Even in point 1 there is a window of opportunity - you can rewrite some of the "heavy" components on Svelte. The project will become easier, and the components will work faster. You don’t have to rewrite everything.
  3. If you are writing an enterprise, Angular or Ember is probably the best choice. Svelte, just like React and Vue, is not always a good choice for this.
  4. If if you need first-class Typescript support.
  5. If you develop exclusively standard solutions and are used to assembling projects from off-the-shelf components.
  6. Still weaker tuning than more experienced comrades. If this is critical, then it's worth the wait, or join our community and develop tuning together.)))


***



In general, unfortunately, most of the conclusions from the original article are based on false assumptions and mislead readers. Given that I did not see the author in the Russian-speaking Svelte community in Telegram @sveltejs (1K + participants), I conclude that the author and his team did not put enough effort into mastering a new, unknown tool. I think if the guys just added to the chat room, most of the problems could have been avoided. At the moment, it seems the guys made rather hasty conclusions, however this is their personal matter.



All Articles