Hacker News new | past | comments | ask | show | jobs | submit login
Solid – A declarative JavaScript library for building user interfaces (github.com/ryansolid)
373 points by revskill 9 months ago | hide | past | favorite | 171 comments

I recently rewrote a small toy project from Preact to Solid. It went from spinning my fans and consuming over 25% of my cpu to practically idling. Solid is legit. I could have optimized my Preact, but I didn’t have to think of it with Solid. Same is true of Svelte.

Edit: I see the author is here, and lots of typically negative comments are being thrown at him. Ignore them and keep up the good work! We need people like you to push performance forward.

This sounds like a really atypical project. Consuming 25% of your CPU is a lot! I hear people mention those kinds of numbers only for Slack, which does have a lot of functionality.

I'd just point out that for the average project, the main advantage is that with something like Solid or Svelte, it will load in less than a second, vs. a few seconds for React, especially for something simple like a blog where you don't want to think about perf or optimize much.

It is atypical, yeah. It's a speed-reading app, so it flashes a new word on the screen every nth of a minute, where n is how many words per minute you want to read.

Still, I'm tired of using a normal web application and feeling the UI lag when I type, etc. I suspect that if you start off with a project like Svelte or Solid, you'll have a longer runway on your app before you get to that level of suck.

Solid is another smart-compiler, virtual-dom-less frontend component building library.

If you're wondering how this is different from Svelte, the author has a Medium post on it[0].

[0]: https://medium.com/@ryansolid/javascript-ui-compilers-compar...

One thing the article doesn't really dive too far into is that Svelte is template driven, while Solid is more about React's jsx-drive-components. As I've used both style methods for years, I think I'm growing fond of Svelte's template approach as the best general purpose solution. This is because usually my pages are 70% static and can be expressed as simple nearly vanilla web-idiomatic html pages. Being able to keep all that static code as close to vanilla web really helps to reduce other overall complexity, with the added benefit of being able to copy html with css from anywhere into my project, and then add dynamic behavior without "rewriting" basic html into jsx (which can lead to subtle bugs).

We use JSX identical to a Template DSL more or less. We don't use JSX at all like React does. That's why Solid so performant. It does similar thing to Svelte. We don't compile it into HyperScript. You can copy and paste html with one exception (void elements JSX makes you close input tags etc). But otherwise I support all the standard stuff pre-adding the dynamic bits. Solid supports `class` and `for` and `style` strings etc..

> This is because usually my pages are 70% static and can be expressed as simple nearly vanilla web-idiomatic html pages.

React can easily be used to render just the parts of the page that need it, with all the surrounding html done the old fashioned way.

I've been playing around with your library for the last hour and so far it's excellent, pretty what I had hoped for after working with React for a while. The performance of individual renders is one area of improvement but I think the main contribution is the clarity the update model provides.

React works well until you try to avoid re-rendering and then it really falls appart. For example, updating a context re-renders the whole component chain from producer to consumer, and trying to block useless re-renders with shouldComponentUpdate easily leads to mistakes where children don't update when they should. Since React rendering use lazy evaluation of JSX expressions, tracking who exactly updates and when is much harder than what it might seem initially (akin to tracking mutations in a language with lazy evaluation). As this library actually tracks dependencies and only re-renders what you want, all of this bloat is avoided. One aspect that impresses me in particular is that JSX expressions actually return real DOM nodes, making it easy to keep references to them for imperative operations (not a big deal but so much nicer than React refs).

I'm wondering why you opted for the setState API rather than a nicer imperative API like Mobx. From what I can gather, state changes are tracked by diffing? Why not just return a proxy?

I do return a proxy. It's just readonly. I really like the unidirectional data flow and explicit read write segregation of react. This adds so much control without having to add Framework like control mechanisms. I know it isn't easy, but it something that makes the solution elegant in the end. I think that passing data should also mean the choice of passing the ability to update it. That is a problem I have with almost all reactive implementations in libraries today. I think React has that part just right.

> I think that passing data should mean passing the ability to update it.

I'm pressing this up triangle as hard as I can, but sadly it still lets me upvote this only once.

I'm not sure I understand your argument in favor of setState correctly. By splitting the state into two parts (a read-only view, and a setState function to update it), isn't the opposite being accomplished? It is now possible to pass the data without passing the ability to update it, or vice-versa. Which could very well be desirable but could be accomplished by other means (i.e. leaving to the parent the choice of passing a read-only or a mutable proxy). Settings aside the superficial issue of syntax, the main thing I dislike about the setState interface is for updating things like lists, where you need to perform a full copy just to insert one element. That being said I haven't yet looked into how exactly you handle lists.

I mean it's basically the same thing as you do with React. You create lens functions more or less to handle get/set over the state object. Solid's setState has a lot more capability than React's handling nested updates with an ImmutableJS or Immer inspired API. The clever part here is immutable libraries already have API patterns to describe mutation so I just apply them here. So instead of spreading everything and cloning you keep the mutation locality for performance but keep the control of immutability.

Also don't be worried about copying the array that much. I'm doing that in the JS Framework Benchmark and it's still about the fastest with 10k items. The real key is identifying where you don't need to update the list at all just the items in it. That being said you can do an update without copying the array like this:

setState('list', state.list.length, newItem);

Granularity of performance isn't a silver bullet. Being fine-grained doesn't necessarily make everything faster (especially creation). The power is that granularity is arbitrary so it can be maximized to the type of situation, completely independent of component structure.

That makes sense. It is mostly the O(n) rerendering which is expensive, not the array copy. With regards to superficial/syntactic issues now, I just don't see the advantage of:

`setState('list', state.list.length, newItem);`



Considering that the two operations can be otherwise equivalent when using proxies (from what I understand).

It comes down to control and immutability. I know not everyone agrees with this but I believe it's fundamental.

You can use the "Immer" syntax of setState if you want:

setState(s => { s.list.push(data); });

But in some cases it is more expensive. Like a splice will per row will trigger the proxy to tell you they've all shifted a position. Where as just setting the array only hits the proxy once. Sure Solid batches the updates from the call but it's still unnecessary tracking. Solid lazily decides whether state should be made into a reactive atom based on whether it is referenced in a tracking scope.

The ability to update a value from the child, Swift UI does this... I really like that

state changes are not tracked by diffing, it is much more interesting. You can read about it here https://www.atfzl.com/understanding-solid-reactivity-basics

Thanks, that makes a lot of sense (basically Mobx but fine-grained). When I mentioned diffing, I meant for updating state objects like lists. Your `<For/>` element only updates if a new list is created, but only re-renders the changed elements. I assume this is accomplished by diffing the old and the new list?

Yes you are correct. Use diffing here actually very similar to VDOM libraries. It was more performant(and consistent) than just propagating the change purely through manipulation of a proxy. Especially if you consider things like batching.

Thanks. Batching was more efficient with diffing because you can avoid keeping track of which array indices changed within the same batch?

Yes and keeping the order of application. I actually played with this for a bit. Early Solid let you basically codify mutations you could send in as data. I thought it was interesting to do something like Redux where instead of producing the next state you produced the mutations that would be applied, and then applied them at a granular level instead of diffing. But when you add time into the picture you actually have keep track of more. I'm not saying it's impossible to tackle this just the people I know who have been working at this always hit limitations where they need to fall back to diffing anyway. I think it would take some doing to determine where the book keeping cost would be worth it. It is rarely as simple as more granular is better.

The negativity in this comments section is astounding.

Personally, I was originally introduced to it by someone in the Mithril.js gitter chat, and think it's a great project. I wish the Solid team the best and look forward to trying out Solid in my next toy project. The performance benchmarks and relatively clean API are truly impressive.

Thank you for your kind words. It can a difference to have the kind words of a few strangers. I'm used to these sort of responses now. And welcome it to a certain degree. Insightful comment can lead to interesting discussion. Ignorant ones gives me a platform to educate.

But it wasn't always like this. Leo Horie from Mithril was always supportive early days when it seemed I only was receiving this sort of "feedback" on reddit if any at all.

Disclaimer: I'm that Leo ^ :)

Unfortunately, JS fatigue is real and it can be challenging for someone who has their hands full with just relearning new React idioms to also evaluate the dozens of other libraries out there, so it's easy to miss a gold nugget.

For those who are not seeing the value proposition here, think Svelte, but where the "reactivity magic" is encapsulated via Components to still allow React-like "it's-just-JS" component code, while also getting rid of a lot of runtime overhead and the complexities associated with trying to optimize a virtual dom (as has been the recent direction for React).

One great benefit over Svelte with this approach is that you can use Typescript in templates (something that Svelte still is not able to do).

Solid's performance claims to fame are also legit (i.e. it doesn't sacrifice good devexp, good engineering, unlike many of the top performers in the stephen krause's benchmarks).

The only thing I wish was better is docs. It starts off "spilling its guts", so to speak, and while that is an ok way to explain why Solid is different than others and to garner interest from library authors, it's also not super beginner friendly. One cannot, for example, easily find docs for `<For>` even though it's analogous to core syntax if we were to compare to a programming language. Putting a follow-along tutorial upfront would go a long way.

Thank you as always. Early days spent so much time justifying things, everything became these expositions. Time to tighten up.

People loved React because of VirtualDOM.

Now JS libraries advertise themselves based having no VirtualDOM.

Can someone explain this to me?

People loved React because it solved a problem. They just happened to solve it using virtual DOM.

but theses next generation frameworks are showing that there's a better way to solve the same problem.

VirtualDOM allowed you to update the dom with better performance than before. Is there now a better technique? Why is it better than VirtualDOM?

This is a good talk on the matter from the creator of Svelte himself, if you're interested: https://www.youtube.com/watch?v=AdNJ3fydeao

Basically, it boils down to moving from tracking the DOM state in a VirtualDOM to tracking what DOM updates can happen at the compile stage and then just doing those exact updates to the DOM.

I haven't seen proof that the output of these libraries is restricted in any meaningful way. Is there a case where some small input n yields !n code? Is there even any proof that all states can actually be tracked? In the case of a vDom, your code size is fixed and execution has a provable upper-bound.

Even if that could be proven, code bloat is still a problem. With a vDom library, the render engine size is fixed. Moreover, those functions are guaranteed to run enough that they will be optimized by the JIT while changing render functions for every component could mean your renders are optimized for this view, but back in interpreter land when rendering the next view.


My annoyance with that talk is he never compared Svelte with multi-threaded React. It was the natural next thing to look at but it was like “okay my point stands let’s move on” haha.

There's no such thing as 'multi-threaded React'. JavaScript runs in a single thread unless you use web workers, which React doesn't (this was a popular idea a few years ago, but people have since come to accept that it adds overhead and complexity out of all proportion to the problem it's designed solve).

You're probably thinking of Concurrent Mode, which the talk does indeed address. Concurrent Mode is, among other things, a clever way of solving one of the problems introduced by the virtual DOM paradigm: that you have to rerun a lot of user code on every state change that will often block the main thread if you don't break it up into chunks.

More on virtual DOM here: https://svelte.dev/blog/virtual-dom-is-pure-overhead

Well maybe we should compare apples to apples. With React you go down a rabbithole of workarounds around their initial concepts (like hooks) until you wonder why you chose it in the first place.

why do you consider Hooks a "workaround around [React's] initial concepts"?

I think Hooks are genius truthfully. But they are definitely shoehorning something into a place that didn't expect it. You are calling these render functions with the purpose of creating new transformations every cycle, and the injection mechanism has to include the initialization the first time. So you basically have these slotted things that allocate memory every time to just use what's cached most of the time.

Now don't get me wrong I've benchmarked Hooks like crazy and I don't think they are much consideration on performance at all. It's just the mental model of always update on the outside with bubbles of things that don't update creating these closures is a little unnatural. By comparison the mechanism they ape (fine grained reactivity) works exactly the opposite way. You just need to be aware the stuff outside doesn't update. Wrap what needs to be updated. Done. There are no out of date closures. No inconsistent mental model. It's as straightforward as registering event handlers.

Still I have to admit the solution is genius. They have managed to get 90% of the benefits with simply repositioning things. At one point this was one of my biggest arguments against React. People didn't appreciate it before hooks. But can you imagine knowing you could write applications this way years ago and trying to convince someone using React classes there was a better way? I just sort of gave up and did my own thing.

thanks for the explanation! though i have to say i only have a vague idea of "fine-grained reactivity", any pointers for reading about this or systems that work this way?

in particular, i don't quite get this bit:

> By comparison the mechanism they ape (fine grained reactivity) works exactly the opposite way. You just need to be aware the stuff outside doesn't update.

inside/outside of what?

PS. my yet undeveloped pet theory is that hooks are (somehow) something like half a monad/algebraic-effect-thingy... though they're probably too tied up with the render cycle to analyze them this way

I have the article for you: https://indepth.dev/finding-fine-grained-reactive-programmin... It's a bit dense at times but I try my best to cover the whole spectrum and how it relates to familiar libraries.

Burning cycles in another thread is just as wasteful, and problematic when you run on a battery, or when you run other stuff in the background.

Sort of. I don't think you can write off the virtual Dom. But this is basically my area of research. I'm saying that a specific approach to reactive programming is more performant. I have an article for that too: https://medium.com/better-programming/the-fastest-way-to-ren...

Thanks. The whirlwind of changing benefits of various frameworks can be rather confusing. I do wonder how much this matters for most apps and at what cost of complexity it brings. But advancements in the field is a obvious good thing.

From my perspective, the things are a bit like this:

1. Make all updates manually with jQuery. This is fast, but hard to keep track of.

2. React, create a virtual DOM, then compare the current DOM with the virtual one, and figure out what needs to change.

3. Solid, Svelte, don’t create a virtual DOM, but have the JS compile all the possible changes so you can make them directly in the DOM like with jQuery.

If you’re “compiling all possible changes” that’s a diff, right? If there’s no VD, what’s being diffed?

the question is not what, but when

Exactly. Think of is as the classic compiled vs. interpreted languages debated. One is clearly faster than the other but the slower one may have different advantages.

Ahead-of-time vs Just-in-time is a more accurate description.

In this case, there's no evidence that precompiling is faster in theory -- let alone in practice. In the JS framework benchmark suite, SolidJS and InfernoJS performance is almost identical (with SolidJS having a much larger margin for error in most tests).

This is the BEST possible case for precompiling too. In the real world, JITs take a long time to warm up (a couple hundred executions before all the optimizations kick in). With the vDom, you warm up ONE set of code that then runs forever. With the precompile, it has to warm up for EVERY new component and potentially slightly different codepaths within the same component.

The JS framework benchmark reuses the same components for everything which is a huge advantage to precompiled frameworks while not having much impact on vDom ones (as the actual components in both cases usually won't optimize very much due to being polymorphic).

> In this case, there's no evidence that precompiling is faster in theory -- let alone in practice.

It’s absolutely not because it requires far greater effort computationally. The benefit has nothing to do with performance but instead simplified state management.

I know people desire certain frameworks due to how they perform state management. I have never really understood that motivation myself though because managing state is incredibly simple. Here is a basic outline of how simple it is:

1) realize there are exactly two facets to every component: data, interface.

2) all components should be stored in common locations. A single object stores component data and a common DOM node for storing component interfaces.

3) pick a component facet to update, either data or interface, and never update the other. The other should be automatically updated by your application logic (reflection).

4) store your data on each change. That could be dumping it into local storage. In my current app I send the data to a local node instance to write into a file so that state can shared across browsers in real time.

5) be able to restore state. On a fresh page, or even page refresh, simply grab the stored data and rebuild the component interfaces from it.

My current application is a peer to peer Windows like GUI that works in the browser and exposes the file system (local device and remote devices) in Windows Explorer like interfaces. Managing state is the least challenging part of this. The slowest executing part are long polling operations against large file system trees (it’s about as slow in the native OS interface)

> In the JS framework benchmark suite, SolidJS and InfernoJS performance is almost identical (with SolidJS having a much larger margin for error in most tests).

I mean I agree with most of your post, but I'm not sure I would necessarily make that highlighted claim from the benchmark results. I mean the +- seems to be pretty run dependent for most libraries on there. And while I agree that the differences in performance is neglible, there is one. Solid is clearly faster in most tests even if by a small amount. Anyone interested you can look at: https://krausest.github.io/js-framework-benchmark/current.ht... And then isolate Solid and Inferno and then do a comparison against one library. It will color highlight the degree of certainty the difference is between the libraries in terms of significance of the results.

VirtualDOM allows you to roughly code your UI as a function of state. It's never been a magic bullet to better performance, except perhaps compared to Angular.js 1.x's "change detection" methods.

Perhaps faster than other framework implementations but there is no way it’s faster than the standard DOM methods.


VirtualDOM is more of an implementation detail IMO. What I love about React is for its declarative API and we can compose components easily.

I agree. I love that about React. I think all UI libraries could learn a ton from React.https://medium.com/@ryansolid/what-every-javascript-framewor...

But it isn't something that completely gets abstracted. There is a reason it has been so difficult to make a non-virtual Dom version of React. It isn't impossible, but has yet to fully flesh out despite attempts by a few projects including members of the React team.

So React needs VirtualDOM? Do people want React not to be dependent on VirtualDOM. Is there a reason/benefit?

You might get some answers here, from an SO comment written by virtual-dom’s author: https://stackoverflow.com/questions/21109361/why-is-reacts-c...

The link has been posted in another comment too, here are some chunks that may be relevant to you:

> A virtual DOM is nice because it lets us write our code as if we were re-rendering the entire scene. Behind the scenes we want to compute a patch operation that updates the DOM to look how we expect. So while the virtual DOM diff/patch algorithm is probably not the optimal solution, it gives us a very nice way to express our applications. We just declare exactly what we want and React/virtual-dom will work out how to make your scene look like this. We don't have to do manual DOM manipulation or get confused about previous DOM state. We don't have to re-render the entire scene either, which could be much less efficient than patching it.

> People loved React because of VirtualDOM.

I don't believe this is true.

VirtualDOM is a means to an end for React. People love that "end", but they do not love the means by which it is achieved.

Maybe one could argue that people love VirtualDOM because it allowed this "end" to be achieved, but I still think every React fan would much prefer it if was doable without VirtualDOM.

It is actually "doable" without vDOM but doing so would be much less scalable and require more care from the user of the library.

I think he may simply be referring to the fact that VirtualDOM/Shadow DOM was one or the “features” React was advertised with initially.

React is my UI framework of choice and I don't care one bit about the VirtualDOM or any of its internals for that matter.

I would bet a surprising portion of React's userbase wouldn't even know what the virtual DOM is.

These compilers work like a library with virtual DOM, but compile it away before deploying.

So, in theory, you get VDOM goodness, without the bloat.

Some people thought they must use VDOM to get things done efficiently, because "All those updates to the DOM will make the browser repaint and everything will be slows! Oh no! We must use VDOM!" This library apparently proves them all wrong, by using the normal DOM in a clever way.

Maybe I just need to spend more time studying the material, but I struggle to see how these precompiled frameworks can handle any arbitrary state change one might write into their JS rendering logic.

For example: suppose I want to take an arbitrary JSON structure, walk the entire JSON tree, and render it on the page as a tree of nested elements - i.e. a new subtree of divs for each array or object. None of that layout is known ahead of time, and it can take any shape - be any depth, breadth, etc. Intuitively it seems like very little can be known ahead of time for compilation purposes. Can Solid handle this case? Genuinely curious.

At that point you remove the benefit of the compiler but that is fine. You are essentially writing a builder script like VDOM HyperScript. But it isn't like there isn't a runtime portion, it just that it can be smaller due to treeshaking and that the change mechanism is generic (used for everything). I imagine this just falls into the classic Reactive vs VDOM scenario, where VDOM is more performant on creation and reactive is more performant on update. The compiler is just something a reactive library can use to its benefit given it does most of its work at creation.

So if this is your primary use case where there aren't really pre-existing templates, a fast VDOM is probably slightly better if you aren't doing much in the way of updating. But hard to say. There is a runtime HyperScript version of Solid that is still blazing fast, but it is probably slightly slower overall than Inferno since it can't leverage the pre-compilation of JSX or JIT compilation the Tagged Template Literals.

That makes sense. Thanks! I do still think this new wave is very exciting and I think it will dramatically improve a lot of cases where people have been (IMO) inappropriately using React thus far. Particularly when it comes to the mess that is hybrid server/client reactive rendering.

It's my understanding that regardless of the complexity of your custom JSON data at some point while parsing the tree you have a line that says "if obj is of this type, then render this component for this node", all Svelte/Solid etc need to know is that this is the line where a Component is being assigned to a variable that is going to be rendered in the template.

Or are you saying you want a layout rendered from JSON without first defining the possible components as Svelte/Solid/React components etc? As I think that defining components explicitly is a central part of all of the front-end frameworks, compiler or otherwise?

Consider the following pseudo-code:

    list2 = bubble_sort(list1)
Now suppose the user deletes one item in list1.

The question is now:

Will the update trigger a new bubble sort?

Will the update do something smarter, like just delete the DOM element?

There's usually no render function to call in these types of frameworks as far as I understand (my experience being a little Svelte).

I imagine in your scenario the psuedo code to achieve what you want would be written.

  list2 = bubble_sort(list1)
  removeItem = () => delete list2[random index]
  <for each list2 render div>
The compiler will see a change to the list2 variable anywhere that removeItem is called and annotate the code to make the appropriate changes to the dom in the function call and the bubble_sort line will never be re-run unless it was explicitly added to the removeItem function.

Correct. The idea is that the derived state only updates when the underlying state updates. And the mapping to the DOM is just derived from that derived state. So list updates.. triggers bubble sort, triggers DOM reconciliation. The difference with Svelte is it sees it and the compiler writes the reactive code in the background. In Solid you just write the reactive code yourself.. ie.. `setState` etc. But it more or less works similarly.

It's like Svelte without abstracting the update mechanism. Which makes it a little more to get into at first but very similar to a library like React. The difference from React is that Solid knows exactly what you are updating so it doesn't bother with the other stuff.

Note that the item is deleted from list1. The framework should (I suppose) track that list2 depends on list1 through bubble_sort(). Are the dependencies implicit? Or should they be declared explicitly?

Generally implicitly either through proxy or get method read. Solid provides an explicit API as well.

Well in React the rendering logic could still just be plain functions, though I guess technically those are considered "functional components".

Good thing this came about. I looked through various JS frameworks for web components a year or so back. I now can't remember did I find Solid had web component support then. I see it has this support now, with Solid Elements. I remember reading Solid articles at the time from Ryan's blog and being impressed. Now it's time to take another look.

Also, I see it's small in size and ES module friendly. Very nice.

Web Components were what originally led me to keeping the Component side light in Solid, which eventually influenced some of optimizations in that area. I hope you find things have progressed nicely in the last year.

Here is an introductory summary of SolidJS: https://dev.to/ryansolid/introducing-the-solidjs-ui-library-...

My 2c of insight: I found Svelte's docs & examples greatly sweetened the on-boarding.

While I presume writing specs is a boring collateral, a friendly / bitesized / WISYWYG documentation would make a world of difference for the enthusiastic but less-than-ninjas of us.

The smarter kids can catch up faster, and some might not bother, already do react/vue. I personally found with Svelte a way tamer learning curve.

I agree. I would love to do more. The truth is there is just so much to do. It's hard to find a balance between writing cleaner docs and say solving Async Hydration with Suspended Components. I had the luxury early on to prioritize the latter which is why Solid is so feature rich given how much of it needed to be researched and built from scratch. I always knew it would catch up with me. But that's a good problem to have.

Clear Docs is important because they say we spend 1x developing a product and 10x marketing it. In the developer experience world, docs are marketing.

Also, polished product and polished code deserve a polished set of docs. Just sayin'!


Ahahaha I know it sounds like that. But I realize what a massive task that would be. Am I volunteering? No. I appreciate your invite.. I'll email you if I change my mind.

I think a cool thing would be if the docs site was made in it. Self documenting.

This (and similar libraries) is the way forward.

I joined the Svelte camp a while ago so I'm unlikely to try Solid anytime soon, but had I started with it I wouldn't complain, because the value proposition is the same: an abstraction which is runtime-inexpensive both in terms of CPU usage and bundle size.

I think, the "3rd Age of JS" [1] of frontend libraries are running directly in the browser without a build step. Like in the beginning. ES modules in the browser paves the way.

Svelte and Solid are actually the pinnacle of the "2nd age of JS".

[1] https://www.swyx.io/writing/js-third-age/

I read that article a few weeks back. It's interesting. I see the desire to lessen on tooling but it is going to be hard to match what these libraries are doing purely runtime. I know people want to get there again. But I think we are more likely to see lighter dev methods and then when it comes to actual production the real advantages of compilation and bundling.

It's an interesting thesis but feels a little cult-ish in mindset. The Neo-isomorphism prediction seems most interesting in terms of the benefits. Because honestly - I think we are MORE likely to see a shift towards containerization of services/apps rather than a module orientation.

There is already a project named Solid led by Tim Berners-Lee: https://solid.mit.edu

Note that that website is no longer the project home - it has spun off from MIT: https://solidproject.org/

(Disclosure: I work at Inrupt, the company started by Tim Berners-Lee to support the project's adoption.)

SOLID was a set of principles for OO design introduced in 2000: https://en.wikipedia.org/wiki/SOLID

In 1983, a database was named SolidDB: https://en.wikipedia.org/wiki/SolidDB

etc. etc.

That is an interesting project. And looks like they beat me to Solid name by a few years. I usually refer to my project as SolidJS. But thanks for bringing this to my attention.

This SolidJS project already has more legs/traction than that's ever going to have.

This is interesting (I’m doing something similar in a specific domain) but there is a bunch of issues: very scarce documentation, funded by Quatari money, and more importantly built on bloated, low adoption set of Semantic Web specs. Heck, the tutorial even acknowledges[1] "If all the above looks terribly complicated: that’s because it is."

[1] https://solidproject.org/for-developers/apps/first-app/4-dat...

Agree with the point about SemWeb. AFAIK, RDF/OWL/SPARQL is kindof a long-term pet project of TBL's, and now with SOLID IMHO he's kindof reusing parts of it as a 2nd chance to finally become mainstream (with weaving and creatively interpreting specs as is typical of SemWeb). What SOLID wants to achieve, though (a federated, less centralized web) is too important an initiative to let it become a case of puzzling out an utopian stack based on tech that has failed mainstream adoption, so unfortunately can't be taken seriously, and seems more like a project for fundraising TBL's pet project. Saying this as someone who has just recently worked with SPARQL and graph DBs in bioinformatics which is one of the domains where it actually has gained traction.

I personally have only had substantial experience with react (and its hooks), but the replacements for hooks in this library look very exciting to me, though I'm not sure I fully understand them on a first reading. One thing that react hooks require is the placing of hooks at the top level of a function, which precludes dynamically creating hooks in a loop, or lists of effects. While usually there is a way to achieve whatever you're trying to achieve anyway, it's still a bit of a restraint on what you can write with React. I haven't tried Solid yet, but if its hooks are nestable and composable as the Reactivity page says, then this could enable some patterns that were previously impossible with react hooks.

as an ex frontend developer. this looks like a great library. i'm sure people won't understand, why this exists i.e JS fatigue. reason, being the current libraries don't solve all problems. till you've libraries that have good cpu performance, no build steps, great syntax. people will keep spinning out JS libraries. anyways great big-up to the author.

I am digging this. The main issue I personally have with svelte is that it goes into a completely different API design than React.

The closeness with the React design makes it better than svelte imo.

Thanks. I get criticism like "Why even make this? just use React." But it's so different. Yet I didn't want to throw everything away. People forget React came up when there were tons of libraries with similar reactive approaches and won our hearts and minds. It does a lot of things purposefully and it does those things well. We need to learn from the past it we are doomed to repeat it.

Can you use react components with it? All the libraries of beautiful components are the main reason why I use react. Like I know you can but with cross component comms and stuff.

Does the state thing have the same gotchas as react hooks? Not a big fan of how that's impl'd in react.

No Hook Rules. Hooks are an amazing feat by the React team as they basically come so close to emulating the behavior here with running through top-down VDOM reconciliation. But they can't be nested etc.. This reactive approach is similar to MobX or Vue Composition API and doesn't have those constraints.

That being said for the same reason. No React Compat. The library doesn't work even remotely similar. People have used them together, but this is no straight swap in.

Might be a good feature. One idea might be a standard way of wrapping a react component so that it uses an embedded iframe / postmessage to post messages back and forth with solid. Tho personally I would like to see this approach to managing state win: https://github.com/colshacol/storage-changed

Solid doesn't re-render Components over and over.. so integrating React is as simple as wrapping a `createEffect` calling `React.render` on a ref. The other way around is a bit harder, but been at this for a while here is a codesandbox with a HOC for that: https://codesandbox.io/s/solid-react-hoc-8m2yd

If anything there is just so much to document.

Any comment on that storage-changed lib? I think that's a massively underrated abstraction for high level state / comms. I want it to be more popular. :)

It's interesting to wrap the persistence in there as well and it's lightweight so that's a plus. But someone also could use say Redux(or Storeon) and achieve a similar thing. The challenge of interopt is more with conflicting update/render cycle and props (especially children). For global storage any event emitter will do. Although one so browser native definitely has it's perks.

Is there dedicated DevTools support for Solid like there is for React, Vue, Svelte, and co.? If not, is there a convenient way to inspect state, props, and the component hierarchy?

I actually think this is extremely important. One downside of these compilation-driven frameworks is that they would, I assume, make it much more difficult to track with exactly how your code manifests at runtime, and would therefore make it harder to debug. Even setting that aside, I'm a strong believer that "frameworks" (contrasted with "libraries") have a responsibility to bring their own tooling, because existing tooling is less likely to be useful against the new concepts they introduce.

It's easier to just open up and debug than say VDOM views since you can see your dynamic expression (what's not updating) and just drop a breakpoint. The template structure flattens so you don't have this issue of nested children and what you are debugging is the actual DOM nodes. It feels more like debugging jQuery. But it is no replacement for good dev tools.

I guess what I meant is that VDOM views (at least pure-functional ones like React) can have a much clearer separation between the view logic and the state logic. I don't have to understand how the VDOM works because it's never entwined with my code that might have a bug in it: I'm just creating a data structure and handing it off. If there's a bug, it's in the creation of that data structure, which is 100% my own code. That hard barrier exists even at runtime. Solid seems like it deeply entwines the two in a way that's very clever and has performance advantages, but would also, I expect, come with a cost.

Yes it's all the same thing. Your data is reactive and an be modularized. The renderer is reactive with the DOM basically being a side effect. There basically is no renderer just a reactive system with different types of data. It means there is an incredible amount of flexibility and raw performance.

The tradeoff is rendering isn't particularly special. So the systems consciousness of specific render specific concepts requires additional consideration. There is no "onMount". There are reactive lifecycles but they aren't particularly tied to DOM updates.

There is an open issue for this. It's an area that needs work since I can't just repurpose existing tools like VDOM libraries do. The challenge that comes with pioneering an approach.

This seems like a silly issue. At one time there was no DevTool support for any of those other tools you mentioned.

This is not a silly issue.

Lack of devtools is expected for a new framework, however, it is worth asking for, especially if you are considering it for production

I'm skeptical about the way state can change from under you within the same execution of the rendering function. This type of mutability will prevent all the help that typescript normally gives for complex components.

Also if anyone has used it, do you have to use this pattern if you have derived state?

      displayName: `${state.user.firstName} ${state.user.lastName}`
If you simply do `const displayName = ...` in the component, will the component update properly?

Feel free to shoot any issues or discussions on our gitter or reddit. You are correct because it doesn't work like that. It works more like MobX. There is no render function that runs repeatedly. Instead everything is split apart granularity and only those pieces update.

If you want to have derived state. Simply wrap it in a function or use it in a JSX binding.


const displayName = () => `${state.user.firstName} ${state.user.lastName}`

return <span>{displayName()}</span>;


return <span>{`${state.user.firstName} ${state.user.lastName}`}</span>;


// this expensive to calculate:

const displayName = createMemo(() => `${state.user.firstName} ${state.user.lastName}`)

return <span>{displayName()}</span>;

Really cool, I should have a serious look at this non-virtual dom thing. All the examples make it look like this project is dependable. Sorry for the plug but I somehow explored similar path when creating the Blop language, maybe the author might be curious: https://github.com/batiste/blop-language Maybe I should get rid of the virtual DOM lib. I use?

It's not unexpected at all. I've had several template library writers reach out to me about the potential here. And there is some. The challenge is figuring out how to hide the reactivity in a way that your end users would be happy with but still benefit. I think it is an interesting challenge.

I'm glad to see continued experimentation in this space. I'd hate to think that React is the best we can come up with.

HTML - A declarative markup language for building user interfaces.

CSS - A declarative, domain-specific language for styling user interfaces.

Neither allow you to build interactive user interfaces besides what is provided by the browser.

I understand the sentiment about reinventing the wheel, but this is more like inventing tyres I suppose (fortunately they are made of rubber, so I can stretch the analogy pretty far, haha). The wheel is there, but there is something to improve to cover more use cases.

<a href="path/to/resource">click</a>

That link tag above, is not only the poster boy of interactivity, it the the foundation of the web.

> Neither allow you to build interactive user interfaces besides what is provided by the browser.

Neither does JS, or any framework built on top of it. All types of interactivity in a browser are provided by for by the browser.

Solid - A declarative JS library for building highly-interactive, logic-driven user interfaces.


Short answer: worse.

Long answer: It is worse, and it all boils down to two phrases which I classify as "marketing speak". Marketing speaks aim is to impress and influence you, "technical speaks" aim is to inform and educate you. When shopping for a library or framework for your next feature or project, it helps to distinguish between the two. Usually any time you see a buzzword, you've stumbled upon some marketing speak. The buzz-wordy term "declarative" has been popularized by React, so I just thought I'd apply it to HTML and hopefully encourage someone to skill up on the web fundamentals (HTML, JS and CSS) before tackling JS frameworks to avoid disasters like this https://stackoverflow.com/questions/42464888/how-do-i-change....

> highly-interactive

What does this mean? Are you talking about video games? Because that is what comes to mind when I see the term "highly interactive".

> logic-driven

Aren't all programming languages logic driven? Or are there some feelings-driven apps?

Probably. I lifted it from React when I opened sourced the project because I liked how generic it was.

JS devs like to reinvent the wheel.

For the life of me, I can't understand why there is so much emphasis on the virtual-dom and dirty checking.

DOM manipulation is expensive, so a check is made to see if it really needs to be done.

If you're guaranteed to need an update, then this check is pointless. But this depends on what you're doing. Its really not something that's tied to the technical identity of any library. React, vue, etc, could probably also skip this step if they wanted.

Also, this will almost never be the bottle neck. It's really low down on a long list of other things that will have a bigger impact. Web dev is in a really bad state - you're supposed to have something like 1.5k nodes according to lighthouse because of all junk that browsers have to do now. That's a puny number of checks for the cpu to do.

The problem is more in the huge number of renders react does if you don’t do everything perfectly. In a large application it gets steadily slower.

IME the Virtual DOM approach is not bad per se -- I appreciate that I can just instruct the library what final state I want and it figures out the details. It's just that for various reasons the algorithms used for "should we update this DOM node" don't scale well.

Of course, if everything was done perfectly I'd imagine an 80486 CPU should be able to render most of today's websites in 0.5 secs but... it's not done perfectly. :)

I like Svelte quite a lot, and I like the idea of the OP's library as well but I wouldn't count React dead just yet. It has a really good idea and the general ergonomics are there. But we shouldn't deny that it still has a room for improvement.

Yeah JSX has its clear advantages. But I wanted to offer runtime only solutions as well. Tagged Template Literals is still the best runtime only solution for Solid, but I've got HyperScript too. Just remember it's reactive so wrap expressions in functions. JSX compilation sort of hides this detail from you.

Can this be used with things like mobx/mobx-state-tree? Absolutely having a blast with MST.

Also, does lack of vdom mean a project like react-native could never really come from this?

It can be used with MST with a bit of interopt. As for native it's possible but would require different compiler output. I saw an approach with another library mind you that emulated DOM API over Native script and used the same compiled output for both. Probably not the best way but interesting.

> Whenever any dependency changes the State value will update immediately. Each setState statement will notify subscribers synchronously with all changes applied.

If two things change that both trigger a third thing to change, how does this efficiently prevent the third thing from updating twice needlessly? I'm imagining this becoming an exponential problem in real apps, where hundreds of components are re-updated needlessly at every UI interaction.

The reactive graph is a push/pull system as it updates similar to MobX. This is a great article on the subject: https://hackernoon.com/becoming-fully-reactive-an-in-depth-e...

Is it possible to use Solid with just plain JavaScript/TypeScript (like using createElement with React)?

I generally find those far more readable than JSX (and is one of the reasons I think SwiftUI and Flutter code looks nicer than React).

You can use HyperScript(createElement) version. You just forgo the advantages of compilation - better dx(less need for explicit wrapping), better performance(optimized code path), and smaller bundle size (more directed code).

Solid's JSX does not compile to HyperScript like React. HyperScript is a different slightly de-optimized experience.

It sounds to me that you are looking for Webscript: https://mudgen.github.io/webscript/docs/

Webscript does work with SolidJS nicely.

Probably should have specified, but a big ting I'm looking for is sull TypeScript support in this regard.

Webscript looks really cool, but it doesn't look very TypeScript-friendly.

One minor thing I might consider is more examples with animation in UI --- it's a place where most apps want to go but have trouble doing elegantly/performantly.

I agree completely. I left an early github issue open with some examples. It just isn't my forte. I've worked with frontend guys who were mostly CSS ninja's and we never relied on framework mechanisms beyond applying some classes etc. I just lack the base knowledge to know what the expectation is here. I know Svelte has a very impressive system. I could look at doing something similar with Solid just not sure where to start.

It's a dumb example, animated lists transition are kind of a good go to... https://svelte.dev/tutorial/animate as is https://dev.to/buhrmi/svelte-component-transitions-5ie

Yeah I guess I mean more I don't understand what it takes mechanically to support those types of transitions. It makes sense to me but I also feel like there would be a lot of details in a generalizable solution. Super interesting though.

I think that's exactly right. it ends up being a LOT of super specific, fragile code --- so kind of interersting thought to see if you can make them elegant/easy/emergent in the library/framework itself.

This looks very interesting!

With new projects and languages and frameworks a good angle to evaluate is, "what's the debug story like?"

Yep. I agree in practice Solid has some work to do here. The basics are think are reasonable in that we are dealing with your expressions in the template and real DOM nodes. So just drop a breakpoint in that sucker. Sort of return to how simple that was in jQuery/Backbone days.

It never is that simple mind you. I have an open issue around Dev Tools etc... We need to do better given the expectations of modern JS libraries.

Essentially react without virtual dom?

Syntaxually and philosophically. Implemention-wise it's more like MobX or Vue style reactivity without a Virtual DOM. It takes compiled reactivity past the localized component model of Svelte to new(ish.. the library has been around for a few years) heights in flexible templating with JSX and unparalleled performance.

The update cycle is the exact opposite to React Hooks. With React your Component needlessly re-renders over and over and your Hook dependencies explicitly whitelist change. With Solid your Comoponent is a basic function that executes once closing over state with it's Hooks, which are the only thing that run over and over as needed when state changes.

"Using JSDOM or similar we can run Solid on the server"

Doesn't sound very promising tbh.

I've been working in this area. Solid now has string rendering on the server without DOM emulation. I'm just one person so I went with what was cheapest first.

Nice, thanks for the quick reply!

Warning performance there isn't stellar there yet but it is my current active area of research.

How hard would it be to get this working with React Native backend?

@ryansolid What minimum browser versions does the library support

As is probably evergreen browsers to use all features. I use proxies which are notoriously hard to polyfill. It is possible to avoid them but I was not taking IE in mind after that. So while possible to support older browsers with Babel unclear what all the polyfills that would be necessary.

Solid looks like Surplus.js mix react.js

Yep more or less. I was working with Adam, Surplus' author, for a bit before he didn't have time to work on the project further. I've take a different tact now with the reactive system and improved the rendering technique a bit. But he definitely deserves the credit for pioneering the JSX approach 4 years ago now. My initial JSX work was generalizing it for other reactive libraries and then it just grew to this.

I see Solid uses proxy to 'get' and 'notice update' the state. This seems providing a better DX than s-js. However, Solid require developer to explicitly use 'react style/hook' to update the state.

Why not also use proxy to 'set' and 'notice update' on the state?

I'm big on read/write segregation and explicit mutation. With simple signals you have this naturally. Once you move to a nested tree you can lose this. Keeping this control allows us to adopt immutability patterns and enforce unidirectional flow. To me this is the most sane way to deal complex reactivity.

I agree, then the way to read and update state with dependency tracing in solid seems meeting the sweet spot of the s-js and elm/react style.


Fair enough. Keep in mind I've been working on this for close to 5 years. Basically around the time I realized KnockoutJS was going to die out and React was for good reason going to win. Here is an article about why this library exists: https://dev.to/ryansolid/why-solidjs-do-we-need-another-js-u...

This article is well written. Great job!


For sure. Which is why in the early years I just did my thing. Win the benchmark battles and move on with my life. But then this whole React Hooks thing came about. And Vue Composition API. Even Svelte 3, and I was like.. there is a better way. I tried to convince those libraries of this but hit walls. So I just kept writing articles and demonstrating it. And here we are today. Some else posted it on here and for the first time I believe it is on the front page of Hacker News. Years later.

Don't let him get you down, mate. These types of people who like tearing other projects down for the sake of it litter the internet.

If you're having fun, keep going. That's all that matters.

> If you're having fun, keep going. That's all that matters.

How is it different than what I said?

Surely you’d agree that “keep going” is rather different from “just don’t do it”?

You missed a comment in between though.

You could think of a library like this as an argument in a conversation about frontend. One that is demonstrated and backed by an actual implementation. As such, I'd say it is valuable regardless of npm download counts.

I'm sure he could also have spent that time at $company, helping to plumb gossip and cat memes a bit more efficiently. I'm sure that would have been more lucrative as well.

Dude, just let him have his fun and stop with the needless negativity. You don't know what the future holds and being rude for the sake of being rude, says quite a bit about you as a person.

I don't think I was being rude in any way. I agree that it is fun. But then its a slim chance that its going to be widely adopted. how come bringing that up is rude?

Don't worry I didn't find the initial comment rude. I get what you are saying and I respect not everyone has time to read a 9 min article. Just know that I'm very aware of it and reflect on it in that article and a lot of writing on Solid.

> If your library/framework/etc's goal is to make life slightly better, just don't do it.

> is fun and beneficial for the individual. YOu just have higher chances of staring a unicorn co, than creating a js library that is widely adopted.

OK, but this thing scored like 600 extra stars in 1 day. And already has over 2K stars. I get you're discounting that. But people like it and are using it. Some dude worked years on it. And you try to trivialize all of that positivity by saying well it's just fun for an individual, as if it's nothing more than fun, as if all the other people who like it don't matter. Which is a lie. He's made something that's more than just him. Something people like. And you're giving the advice, "Oh, all that you did, just don't." as if you're so much smarter than this guy who has created this amazing thing. And, yeah, I get you're dismissing that because it's not "as big as" whatever.

Sure, you're right from your perspective. But how useful is your perspective? And...holding that perspective, how can you really appreciate this work?

You dream of building something better than what is. In some area. Eng dreams. We can all relate.

In the framework space, does any tool really have all the answers? No. Improvements can be made. So make them. Totally good thing to do.

Seems you think you don't have a useful comment to offer, so you just land mean criticism. You know it's mean. That's your point. You feel low, then on HN and see this library written by this dude, get angry and unleash on here. Sure, you feel better for a time, but you hurt other people.

Yeah, I get that putting yourself above this work, and this guy, and dismissing and trivializing the guy and the work, makes you feel better, by comparison. But that's just about what you need to believe, in the moment, to feel good, as a result of whatever situation you're in. It's not about this guy, and it's not about the reality for people using it.

I don't know Ryan, but I've faced this sort of comments from the internet before. It hurts. It gets in the way. It makes you, the commenter, come across as...some sort of inhuman troll. Which of course, you're not!

I'm not trying to change your mind. I get the pain you're feeling to want to say stuff like that. Just trying to point out that what you're doing is bad. For you, and others. Yeah, I guess that's your point, but people can choose different things.

The way I see it, apart from being bad for trying to hurt others, being cruel like this is a huge disservice to you. That's my appeal to you.

I'm trying to read beyond the meanness in your comments to see your actual thoughts on this. And I think they're valid. Actually I want to know about your criticism of the eng landscape and what you think. But when you land this cruel hit, but leave off explaining how you actually think, you let everyone down. Including yourself. Because you do have something interesting to say. what you offer is not just meanness. I genuinely believe that. Don't care if you don't.

What you did this time, is not great. Plus it's bad karma for you. Hopefully next time you only comment on someone's work if you make kind comments and share your true perspective. That would be valuable! Hope you have a good one :)

Please never listen to toxic negative comments like this that try to convince people that they shouldn't be experimenting and creating new things.

I mean, Preact exists and is somewhat widely adopted, and it's literally just React but with a smaller bundle size.

All these transient JS libraries all for what? Making state updates... easier? It's already easy with what's available from the standards.

Explain the big picture abstraction differences between this and React in two sentences? I don't care about compiler vs interpreter implementation details.

With React your Component re-renders over and over and your Hook dependencies explicitly whitelist change. With Solid your Component is a basic function that executes once closing over state getters with its Hooks, which are the only thing that run over and over as needed when state changes.

Very cool work! And great performance. Funny - during quarantine I've been playing with the OPPOSITE. A no build, runtime only reactive JS engine...

Would love to compare notes - you can check out (very much WIP progress) at https://github.com/sreekotay/reefer

It's been only a few weeks of fun... but REALLY interesting problem space. I use a DOM memo-ish approach to help with performance...

Awesome I think so too. I love exploring this space in general. It's really interesting to see how you can model problems this way. Reactivity isn't a solution to a single problem but a way of modelling any problem

Solid actually can work runtime only too but I do put most of my effort on the compiler since I can use it to overcome most of the classic shortcomings of the reactive approach performance wise (and DX wise) with a bit of consideration.

At this stage, web components is no more than a glorified template string + a way to fill it, it seems?

Now only name it template separate it out into its own file, and build an "engine" around it. Then we are almost back, where we came from with backend rendering, which we should be doing anyway.

I've yet to see the JS framework that takes usability seriously and outputs a noscript block (during development) for me to copy paste and get the functionality for anyone disabling JS.

As it stands many web devs only see the JS enabled side of things and then are too lazy to, or not capable of implementing the noscript part. Or they are not even aware of the white page one gets for their oh so cool React apps, once JS is deactivated. It is very unprofessional amd exclusive, I must say.

Applications are open for YC Summer 2021

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact