It has come to my attention this article is the first some people are hearing of SolidJS. If you want to learn more about Solid, this is NOT where to start. I suggest looking at the github or the links at the bottom of the article. This just details my personal journey and is highly biased.
The number of times I've asked myself that over the years is staggering. Even after hitting 2k stars on Github last week and reaching over 50k downloads on NPM I still question it. A lot of times when people approach this topic very early on in working on their library but I started Solid years ago before I thought anyone would be interested in using it. I only started promoting it because it had already achieved the goals I had set out for it. So today I want to finally lay to rest why I continue to do what I've been doing for better part of half a decade. Understand that this is a personal journey so it is one full of personal bias. So feel free to disagree with my assessments to your hearts content.
React
It often starts here. I love React. I didn't always though. I even detested it at times. In 2014, I didn't see the point. I was very happy with KnockoutJS. Early React rhetoric suggested things that I didn't believe but had no easy way to prove. Apparently the VDOM was significantly more performant than using the DOM. It didn't make sense. I watched over time KnockoutJS fade out of popularity. And was soon using React myself and it never quite sat right with me. I missed using function components and easy composition patterns based on primitives. I watched the first 2 years of React dev debate over the right store mechanism and I kept on thinking why is this even a thing? Change propagation and composition patterns are something I took for granted and now I had to use classes and figure out which flavor of Flux fit my mood.
So I started experimenting. And experimenting more. And it became clear to me especially after looking into MobX that it would be possible to make a renderer more performant than React based on all the patterns I longed for. If instead of parsing DOM nodes like Knockout, I could just read in a text file and parse the string to create my own HTML-like DSL. I played with this for about year and decided it wasn't bad. I still had this obstacle though that at this time all the performance benchmarks were based on re-rendering full pages from data snapshots. And while my experiment updated quickly these were a mess. I decided that Proxies were going to be key and changed my experiments to focus on that.
However, React was changing rapidly during this time. I don't know if it was a change of guard, but everything they were doing started to make sense. Batching updates, Function Components, HOCs for composition. Slowly by slowly React didn't seem so bad. IDE support and tooling made developing much nicer than my string templates. The only thing I missed was the code organization I had in my libraries. I really missed my data being declarative. By that I mean with Knockout I'd describe a thing and all its behavior in one code block and then I could encapsulate it. React HOCs weren't quite the same. The declarations and the behavior were still separate generally.
And then I stumbled across a library. Surplus it was called. It had managed to make the move to JSX and TypeScript yet still used fine-grained Reactivity. It was rough around the edges. It was easy to cross reactive scopes and props were a mixed bag of Signals and data you always needed to check what you were getting. But it had all the fundamentals. More so with the JSX it was able to just let the JS statements pass through. I had various JavaScript like DSLs in my String Templates, sort of invented my own language but I was hitting a place where I wanted to bring in JS parsers anyway. Artificially creating scopes for variables had sort of run its course and I had hit a performance wall. This library had none of it. It was arguably the most performant library out there.
So I decided that I'd just use this library and work with the creator instead of writing my own. But there was one major difference in our trajectories. I liked the state objects in React and I saw object proxies being the solution to doing diffing so that this approach could compete in any scenario that a VDOM could. However, Surplus' compiler optimizations wouldn't detect them so I had to artificially wrap reactive expressions in {( )}
to artificially fool it. Over time Adam, Surplus' creator, had less and less time to spend on the project and I decided to take my own shot. Building something similar on Babel, but proxy friendly, and I wanted to do something about those rough edges. I was hoping to still eventually merge with Surplus so I wrote in a way to support any Fine Grained library making versions for Knockout and MobX as well. And the result was just as amazing. Knockout was no means performant largely the same as it was when I started. But Knockout JSX was outperforming even Inferno in benchmarks.
Still it was a novel thing. Maybe I could get my company to use this to replace the large amount of legacy Knockout code we had. At this point it had been about 3 years since I started doing my experiments. I had no illusions. This was great but it felt foreign. React had gotten everyone to feel like they were using plain objects. And in some way I would always need to acknowledge the reactivity. It still had awkwardness. I couldn't land on how I wanted to box primitives. Should I use a getter/setter, or function form like Knockout, or explicit get/set like MobX? These were all ugly. No one wanted derivations, or computations. The pattern was amazing but realistically I felt no one would really get over their preconceptions here. That was until October 2018.
Dan Abramov introducing React Hooks made me do a double take. 2 things were immediately clear. Hooks were identical to Fine-Grained on the API surface and people were eating this up. This was the piece that made all their other recent work all gel and I gazed into the sun for the beauty that was there. But there was a problem. I used them a bit and realized almost immediately they felt like a leaky abstraction. I kept on wanting them to work like Fine-Grained reactivity, since it was much more intuitive. Hooks did all the right things, embraced all the right patterns but as long as React worked the way it did it would never be the best Hook library.
Vue
I never had much interest in Vue. Evan You is a different story. His understanding of tradeoffs and Framework... um, Metagaming for lack of a better word (sorry Magic the Gathering player here) is very respectable. However, Vue was always felt contrived for me. Like they tried so hard to make things easy they didn't care that they weren't elegant or simple. Still I knew they used a Reactive System so maybe there was some hope there. In fact for several years I had hope a library like this could evolve past the stigma's of the past around Reactivity. But I honestly had given up hope it was clear that Vue didn't want to rock the boat. But then I saw their reaction to React Hooks, deciding to expose their own reactive primitives and I got excited.
Until I saw how the community reaction to the Function API RFC. This firmly reminded me of why Vue was Vue. It did eventually land as the Composition API. However, in my (very subjective) opinion, it lacks the clear finesse of React or even Surplus. It was sort of like a modern Knockout which I think is exactly what what they are going for. Tooling and DX is improved, but the mental model hasn't moved forward as much. It has that easiness of use but I was concerned the approach was setting it up to repeat many of the patterns that caused reactive libraries to fall out of favour before.
I feel often, when first being introduced to this reactive approach focuses way too much on the getter/tracking part of the equation which is really the part you want reduce the mental bandwidth on, yet people tend to drop the ball on the mutation part. React had already impressed on me the value of uni-directional flow, immutable interfaces, and explicit updates. So unfortunately 1 step forward, 2 steps back. Vue has all the makings of the reactive titan we want, but they are only starting to embrace their true identity. Vue has great understanding of the whole ecosystem and where it sits relative to the complete landscape. But it clearly has different goals. I asked Evan why he still has a virtual dom at this point and he replied:
Because Vue allows you to write manual render functions and mix them with template based components. Giving up vdom is giving up an important capability for advanced use cases where logic expression is more important than a bit of perf
It is so much more than that! Why couldn't there just be a single template syntax? Which brings us to...
Svelte
Now I wasn't paying much attention to Svelte at all before Svelte 3. I wasn't really aware of it before 2017 so having already seen Surplus I just was thinking it was another library that had worse performance and syntax. But around Svelte 3's release I remember the first Rich Harris talk I saw and 5 mins in I was like "Wow this guy gets it and he knows exactly how to talk about it". Unfortunately I didn't feel the same way by the end. There were 4 main points being made that I felt were suspect, if not misleading. I had Deja Vu to when I first heard that rhetoric about React.
1. No Runtime
Wait what? No runtime. How does that work? Well, obviously JavaScript executes at runtime, so was he saying he doesn't reuse any code? Well as it turns out the message here has changed. I looked and sure enough there was a runtime. Of course there was. But I still felt it was deceiving more or less. Svelte has remedied this messaging since but it was the first thing that made we wary.
2. Virtual DOM is Pure Overhead
Everything on top of VanillaJS is pure overhead. I knew from my experience Reactive systems often bring an even heavier cost. If you think it's expensive creating a tree of JS Objects, how expensive do you think it is to do the same traversal and wire up a bunch of event listeners. This feels every bit as suspect as the old VDOM is faster than the DOM. There was a Q & A at the end of one of his talks where someone asks about Inferno, an incredibly performant VDOM library, and he sort of just side steps it. It's unfortunate.
3. Benchmarks
This one probably hits closer to home to me than for others, since I spend so much time here. But the benchmarks that Rich chose weren't even remotely good ones. They had obvious flaws that even the authors acknowledge and Svelte's implementation actually cheats what it was testing. He might as well just made a page with an h1
that said Svelte is the best for all the value those tests have.
4. JSX as a DSL
This one was the weirdest to me. JSX is a great DSL simply because it has a defined syntax that is somewhat standardized, is supported in tools like Babel, TypeScript, Code Highlighting, and Prettier. It basically does everything for you already and has patterns for extension all baked in. Now I understand why not everyone would use it, but the insistence that it wasn't an option for Svelte seemed odd. I realize now it was since there was a misunderstanding over what JSX is. Where I see it as a spec for syntax (https://facebook.github.io/jsx/), there are some who don't differentiate it from HyperScript runtime. In any case there seemed no interest to support these ideas.
Ultimately Svelte left me the most disillusioned with the status quo. Everything about it was coming from the right place, but it was getting sold like snake oil. My interactions with parts of the community indicated since people had bought it hook, line, and sinker. Very few were interested in furthering the platform in the places they just took for granted.
So I just did it
It was clear no one was interested in what I was working towards. React had all the strong principals, and vision but the implementation incompatibility would likely never be bridged. Vue is a large library that has to cater to people of all backgrounds. I'd gone through the process of understanding reactivity a few times now and it didn't feel like it was the right place to start again. Svelte had painted this picturesque world for us all to live in but made it difficult to talk about the hard topics.
So that's what I did. I took on the hard topics. If there was a place I thought reactivity would be weak, I embraced it and I worked on it until I was happy with the results. Ultimately it made me appreciate React more and more. But it also helped me carve a niche for what would become SolidJS. I still see that space today, so I'm glad that I did. If you are interested in a library that has the discipline of React, transparent implementation that doesn't cut corners for easiness, and all the performance to back it up maybe SolidJS is the library for you.
Want to learn more about Solid? Check out these links:
Introducing the SolidJS UI Library:
https://dev.to/ryansolid/introducing-the-solidjs-ui-library-4mck
Solid: The Best JavaScript UI Library you've Never Heard Of
https://levelup.gitconnected.com/solid-the-best-javascript-ui-library-youve-never-heard-of-297b22848ac1
Top comments (19)
Hi Ryan, huge respect for you and your work. While you make fair points about Svelte (and the other frameworks), I think that the performance and small bundle size are not its main selling points. They are a nice bonus and a way to insult React but as you say, there are frameworks that optimise better for that, Solid is probably the leading one.
The main thing with Svelte, imo, is how elegantly and straightforwardly it lets one express concepts that would be quite painful using other frameworks, like React. I guess it is thanks to the compiler (which turns the .svelte files into something that the browser can understand) and a very good API design.
I am thinking about built in but easily extensible transitions and animations, custom actions, reactivity that requires almost zero syntax, bindings to stuff that aren't normally bindable (like dimensions of stuff), stores and the way they can be combined with actions, the way it utilises custom events etc. It somehow feels very high level and very low level at the same time. Unlike React Hooks, it doesn't make it easy to shoot yourself in the foot with stale closures, infinite rendering loops, out of control effects and such.
Not saying it's perfect, it has bunch of weaknesses, most notably around what can be done with 'slots' and styles.
Svelte has done some really transformative things with its compiler. I was sort of hesitant even publishing this piece since I knew how subjective a lot of this stuff is. I think that experience you talk about is a big part of what attracts people to libraries. I know that I have gone from one end to the other in this regard and I still have admiration for different extremes. I actually joked a couple of weeks back that with the power of reactivity and compiler maybe I could emulate any libraries experience. I was imagining use Solid and JSX with a compiler preprocessor to basically mimic Svelte's API experience or React's. Svelte is just JavaScript executing DOM operations like everyone else.
I think some of the syntax Svelte uses is really powerful. And I've been considering how to use JSX namespaces to offer similar syntax for a different sort of directive extension. I think Svelte does a lot of things very well. My personal preference is to have more transparency on behavior and more extensible composition patterns which is why I stand by the importance of embracing the knowledge of reactivity, since even Svelte has to break that wall once it gets out of Components for things like stores. It's a philosophical thing that Svelte and Vue sort of have in common. They want to ease you in with familiar experience and grow you into more advanced things as holes in the abstraction appear. I don't have any particular issue with strength or weakness of features here, but more the philosophy.
React gets a lot of flack because it is basically always what you see is what you get. Here are the tools just do it. It doesn't attempt to tell you what to do or how to do it. Just these are the pieces you should need and they are always the same. Ultimately I learned to love React more because over time I just naturally got to the same conclusions despite years of fighting it. I'd rather have a few adaptible but powerful simple tools than progressive layers of experience. If you are going to get there anyway, why not start there with a tool that has set its focus in that zone. I agree the Hooks abstraction has issues, which was really the reason I pounced. But this explicit transparent approach gives more control and I appreciate that control. I noticed that for some reason no other reactive library had come to the same conclusions. And I think it came down to them seeing Reactivity as a user ease feature. I see it as the ultimate building block to construct optimal interactive interfaces. So right off the bat my goal was much more aligned with React's.
So maybe that is how I should sum up this whole article:
Solid is to React as
Svelte is to Vue
I was looking for some pros of SolidJS but didn't really get it here. you went thru other frameworks and listed things you didn't like, might want to conclude by making a comparison table showing things you do like.
That's fair. It's sort of unfortunate that the justification for existence comes from pointing at gaps. But I suppose it comes with the territory when I consider even publishing an article like this. I was sitting on this one for weeks and wasn't sure I was going to publish it until I found myself trying to defend why I didn't just give up before I started.
The amount of hostility towards the idea of Solid is unreal at times given the choice to not try to strike out new ground with the API. The library finds itself wedged between "Why even bother with this when we have React?" and "I am very suspect this is a real thing, as everyone knows you can't do this with JSX". It immediately invalidates the whole grounds of conversation. I can't quite pinpoint it. It's like the mere concept of what I've been doing here threatens something. It blurs some lines that should never be blurred. Maybe people just like being given the choice in a form that involves picking a side as it makes things easier to understand.
But I've written several articles explaining Solid's approach and benefits preceding this.
The quick "marketing" highlights can be found here:
dev.to/ryansolid/introducing-the-s...
The original more detailed Solid positives:
levelup.gitconnected.com/solid-the...
I have over 2 dozen articles linked on the github detailing everything from design decisions to performance profiling. It's a lot of content, and I realize I need to improve the presentation of that information. But hopefully the first 2 links are what you are looking for. This for me is the culmination of years of thinking and work, and in many ways I've barely scratched the surface.
Hey, and besides.... don't forget about the fun! Let's program anything we want, especially if its on our free time, even if the only reason is for fun, and we'll reap the benefits of learned knowledge from it. 😊
Hi Ryan, thanks for sharing this and your other articles on Solid.
Do you consider animation as an important part of Solid? Having been around to see the Web evolve/regress multiple times on the matter (Flash, GSAP, CSS, Canvas, SVG, WebGL), I feel that modern UI libraries diservice animation. Yet is seems essential to a complete story of Web UI/UX and a hard thing to add as an after though. In this sense, Svelte had some initiative that React lacked. What are your thoughts?
Not where it stands today. It is a very interesting topic but incredibly difficult to generalize. Svelte has admirably taken a really good stab at it and I'd say it is in a good place today although it took a few years of it being out there to get there. I'd love to understand a bit more about what Svelte is doing to see if we can do something similar.
Animation is on my list of topics but as one person I've had to lower the priority of working in that area, as by myself it would probably take years to get right and there are bigger gains I can do right now. I think its a topic that deserves more attention, but it is far from a solved issue. A lot of this stems from the underlying technology not being the easiest to interact with. And progress one UI library makes is generally not transferable. This is an argument for it living outside the UI library but I can't definitely comment on that conclusion without more investigation.
That being said, I said the same thing about SSR and a few months later guess what I'm working on? It is definitely on the list and given the power of compilation and that Svelte has shown what is possible, I wouldn't count Solid out here. Just feasibly the size of the project hasn't had the opportunity. The oldest open issue on the Solid Github is about this topic.
Thanks for taking the time to write a thoughtful answer!
I think in the end the counter-reaction won the day. The Vue team re-tooled their RFC to explain the concept & use cases better, to reassure the community that they wouldn't lose backwards compatibility, and to ensure that Vue wasn't turning into React. (The latter is probably what you object to, but I'm pretty happy about it!) The community has since come around very strongly in support of the new API.
You are right. Knowing how Vue works internally I never had any fear it was going to turn into React, but I know that wasn't obvious. I think they landed at a place that people like and they still accomplished their goals. I just was impatient and I kind of felt like they are going through the discovery process again. I had already started developing a path to push the boundaries and it just wasn't a feasible place for Vue. Evan's tradeoff talk (youtube.com/watch?v=ANtSWq-zI0s&vl=en) is such an effective way to understand Vue's thinking. The deliberate dance of how to cater a little bit to everyone. It's not an approach to pushing boundaries.
This is not a good way to promote your product. I had heard of SolidJS and thought I'd come and see what makes it stand out: apparently it's an unhealthy dose of negativity. I've been tinkering with Svelte and am really enjoying the experience; but I'm still open to alternatives. You've convinced me that SolidJS is not one I should spend my time on.
Taking that into account I've added a disclaimer. I wasn't really intending this article to get spread as far as it did without context. I never tagged it, I didn't make it a general post on Social media or on Hacker News. In the few locations that I have posted it, it has followed a place where Solid has already been introduced. I deeply regret this was your first introduction.
I agree. I actually wasn't trying to promote this like I usually promote my articles. People constantly suggest that I should have just worked with a different library instead of writing another one. Even after highlighting the benefits. Unfortunately people lack the the time to invest to really understand those things. I needed a place to point them. It's unfortunate this is the first one you saw and not the 2 dozen plus other articles I've written about Solid over the last 2 years. Sometimes unfortunately you have to point out what about other libraries visions does not fit with your goals to ultimately lay the question to rest. I hope this is the first and last article I ever write of this nature. Although I'm starting to regret even posting this because I feel like it cheapens what we've accomplished.
I have to say Svelte is sort of the poster child for this behavior. As I wrote, a good chunk of the material around the Svelte 3 release was purposefully misleading, tearing down at other libraries approaches. So going that way is kind of calling the kettle black. I'm not here to convince you of that though. Just to express how I reacted to what I was seeing. If you choose take a look around under that lens you might come to a similar conclusion. At which point maybe we can revisit this.
That being said I can also empathize with Rich Harris' position. It's hard to fight against a tide of "experts" and preset assumptions. Sometimes it does take tearing things down a little bit. Svelte has changed their tune a bit since that time. It was just this was where things were at, at the time. The amount of misinformation about React and the VDOM was and still is astounding. I just died a little bit inside when I felt reactivity was being marketed in the same unsubstantiated way.
Thanks for taking the time to reply. Don't get me wrong: it's perfectly legitimate to compare your library to others and point out where you do things better: that's pretty standard and what I was expecting from your article. But presenting a library author as a "snake oil" merchant and those who show enthusiasm for that library as fools for falling "hook, line and sinker" for his lies is pretty insulting and not particularly constructive.
If you're going to post claims like this you really need to back them up with some evidence beyond your subjective opinion. Case in point: from what I've seen the benchmarks you referenced in a previous article to demonstrate the speed of SolidJS show Svelte performing pretty well. From my perspective whether Rich Harris deliberately chose to present benchmarks that especially favoured Svelte is therefore a moot point: you expect some hyperbole during these presentations and you should of course question and verify the claims being made. I've yet to find anything that causes me serious concerns; and I'm finding Svelte a pleasure to work with on small personal projects. For me, whether it's a good choice for large professional projects is still an open question: e.g. it will need good Typescript support if it's going to be taken seriously at my office...
Anyway - best of luck with promoting SolidJS: ultimately healthy competition is a good thing; so we absolutely do need people pushing the envelope and showing how things can be done better.
Yeah Svelte has great performance. I think it is at a good place that people should seriously consider using it in larger projects. It's getting quite mature in its feature set and has been stable for some time.
This is why it rubbed me wrong. It definitely was subjective how I reacted. None of these things are serious enough to prevent one from using Svelte. It's an awesome library. I'm not saying it is snake oil, but that given the distance between what was being said and the facts, in my perspective it was being sold that way(especially the benchmarks, really atrocious, read this thread to get one example from Rethinking Reactivity: github.com/somebee/dom-reconciler-...). As a huge enthusiast of the approach Svelte has taken and performance that hit me harder than it should have. How does one defend the position when it is misleading. I felt like my work was going to get bucketed in with it and I could tell that it wasn't going to be the place for me. My first interaction wasn't great(github.com/sveltejs/svelte/issues/...) but I'm all for helping improve Svelte where I can(github.com/sveltejs/svelte/issues/...).
I think this is great. Always challenging the paradigms is how you move forward and force people to think differently. For better ( i think solid is better) or for worse, that's the lens you should look through whenever there are new additions to the javascript world.
@ryansolid given you liked Knockout, did you have a chance to look at Aurelia.io? If so, how would you compare it to SolidJS? Thanks!
I never really spent a lot of time with Aurelia. It reminded me of Ember or Angular at first glance given how extensive its approach is. And I did spend time with Ember the early years. Aurelia has always been very cognizant of performance. It was one of the first Non-VDOM libraries to adopt similar list reconcilling techniques. It was one of the first reactive library to show it could hold its own in the post-reactive VDOM era.
Although it is one of the larger libraries from a bundling perspective. Similarly heavy on memory usage. Coming from Knockout's minimalism more built-in features were never really much of a consideration. Mechnically it shares the granularity that Solid leverages, but similarities mostly end there. I've taken a very different/minimalist approach to components.
Mostly I think a focus difference. Aurelia seeks being an all inclusive framework. Solid has been as much of a research topic as anything. Basically an extension of a theory I had for optimal rendering and DX patterns. It's only in the past year or so that I've had the opportunity to start exploring the possibility of being a framework. Solid is much leaner and rougher around the edges. And I'm not done. To accomplish where this is going Solid is going to travel light atleast for the next while.
A great write-up, thanks for taking time to put it together.