Hacker News new | ask | show | jobs
by codelikeawolf 1025 days ago
I've been using Svelte exclusively for my projects (and at my day job) for the last 3 years. I've converted several large projects over from React to Svelte. I also do some part time work as contractor on a very large React app. I can provide you with some downsides for Svelte:

1. The developer experience with Svelte just isn't that great. Unfortunately, the Svelte team has (understandably) optimized for VS Code. I've been a WebStorm user for about 8 years and have no plans of switching over to VS Code. They just introduced Svelte LSP integration in WebStorm, but it's buggy. For the longest time you didn't get autocomplete on props with the Svelte plugin. With the Svelte LSP, you do, but I'm getting a bunch of errors from the LSP saying "x is not a module". This may be a configuration issue (I'm using pnpm workspaces and TS path aliasing). But I don't really want to go down that rabbit hole, so I just turn the LSP stuff off. It has gotten better, but it comes nowhere near the DX you get with React.

2. You technically can spread props down the component tree using $$props and $$restProps, but the documentation recommends you don't because there's a performance hit. So for stuff like "aria-" attributes, you either need to define them explicitly as props (e.g. "export let ariaLabel"), which is sort of gross, or you bite the bullet and use $$props or $$restProps.

3. Unless I'm doing something totally wrong here, using CSS nesting doesn't work the way I expect it to for scoped styles. I get that they are scoped, which is good. But if I have a button element with a child Icon component, and I want to change some CSS property in the Icon component's inner svg element using CSS nesting, it won't work:

  <script>
    // Icon has an inner svg element:
    import Icon from "./Icon.svelte";
  </script>
  
  <style>
    button {
      & svg {
        width: 1rem;
        height: 1rem;
      }
    }  
  </style>
  
  <button><Icon name="close" /></button>
The Icon's svg won't pick up that 1rem x 1rem sizing. I guess this makes sense because that is essentially just button > svg, which also doesn't work. But I end up having to fall back to CSS modules (or Emotion, which I stopped using because it needs a runtime).

4. I feel like the whole "$" reactivity gets overused, which leads to confusing and, in some cases, difficult to debug code. Maybe this is the ol' React dev in me (one way data flow), but 9 times out of 10, instead of binding a value to an input component, and listening for changes in a "$" block, I'm going to use the "on:input" or "on:change" event listener to capture that and just reassign the value variable.

  <script>
    let value = "";
    
    // Instead of this:
    $: {
      // Do something with value.
    }

    // I do this:
    function handleValueChange(event) {
      value = event.currentTarget.value;
      // Do something with value.
    }
  </script>
  
  <input id="use-binding" bind:value />
  
  <input id="use-event" {value} on:change={handleValueChange} />
5. This isn't a Svelte-specific issue, but I'm not crazy about single file components. I really like how components === functions in React, so you can put multiple components in the same file. In lieu of a function that returns a bunch of JSX based on some args, you can switch that over to a component with props. I think that's a really clean design that encourages good separation of concerns. In Svelte, you either end up with a bunch of extra files that need to use context + store or prop passing for state, or a giant component file.

6. Unless there have been major improvements in the testing space that I haven't taken advantage of recently, you can pretty much throw any hopes of reliable test coverage out of the window. At some point I just stopped testing my Svelte components and moved as much logic as I could outside of of the component so I could write unit/integration tests against that to get reliable branch coverage. This sort of ties into point #1, but I feel pretty strongly about having a comprehensive test suite to avoid regressions (enough to make this it's own bullet point). I don't put a lot of emphasis on the coverage percentage because that way lies madness, but it is nice to see at a glance if I'm missing a test case for a branch in the coverage report.

There's probably a few more minor gripes that I can't think of right now, but those are the heavy hitters. That all being said, two of the biggest advantages Svelte offers over React:

1. No virtual DOM. This allows you to do things like change the style of something based solely on an HTML attribute using CSS, no state variable needed. Also mentioned in the original post: you can use plain ol' JS libraries and everything just works. This is a big deal for stuff like D3, because you don't need to add any wrappers. I've had problems with React + D3 in the past, and it drove me bananas.

2. Much fewer footguns. I know this is a controversial take, but I don't like React Hooks. They're a pretty big footgun. They often require you to break up a component needlessly so you adhere to the "Rules of Hooks". Stale closures are a thing. I never had a problem with class components. I never understood the confusion around "this", which was a common defense for using hooks whenever the topic of the weirdness of hooks came up. If writing class components was still acceptable, I would be more amenable to using React in my projects. But whenever anyone I work with at the contractor gig encounters a class component, they immediately want to refactor it to a functional component with hooks. It's never even up for debate, class components bad, functional components good. Svelte doesn't have anything analogous to a hook, which makes me happy.