Profile avatar
ryansolid.bsky.social
got signals? @solidjs.com @sentry.io previously: @netlify.com @markojs.com
218 posts 6,517 followers 67 following
Regular Contributor
Active Commenter
comment in response to post
1. Technologies not used independently 2. Mutation has important implications on the tradeoffs
comment in response to post
While there is a clear connect where we render between UI and data, as data is shared it gets harder to unwind. It's kinda like the ContextAPI. People usually don't store Components in there. Anyway I'm getting beyond scope of the article. I mostly just wanted to say:
comment in response to post
The need to close the loop makes mutation -> query makes this more complicated. The co-location of UI with data actually can work against RSCs a bit, because to share isolated slots you are back to hoisting.
comment in response to post
Architecturally there are only 2 meaningful patterns here in regards to fetching> hoisting(everything but RSCs) and interlacing(RSCs). One can approximate GraphQL by co-locating query parts in component tree and importing them into the hoisted loader. Mutation widens the conversation.
comment in response to post
Yeah the small thing in server functions is they imply controlling both sides, so serialization format part of it. Have that GraphQL, RSC advantage of being able to define how you communicate. Most of my concern it positioned the pros/cons because these technologies aren't used independently.
comment in response to post
But that isn't why people have issue with them. Or even pushed back against Remix Loaders. It was because of data mutation and invalidation. Sometimes replacing the whole page isn't good enough. I know it worked for re-rendering components, but now there is a network in between.
comment in response to post
Bottom-line unavoidable waterfalls are unavoidable and should be moved to the server, like we've been doing since the dawn of the web. Co-location is an ergonomics question, do you stream data like in GraphQL/Server Functions or Components like in RSCs? RSCs offer nicer ergonomics for fetching.
comment in response to post
Why granular loaders? One of the huge weaknesses of Server Loaders and RSCs you can independently update parts of the page without grabbing everything, don't need server cache strategies for simple mutation. They work independently. It's great this post talks about fetching, but what about mutation?
comment in response to post
They can be router-aware. If you run them in the client loader you can run them independent of component trees and use server functions very much like granular server loaders. We've used this to do things like single flight mutations, ie return next page's data in single request.
comment in response to post
If I went in and made a PR I could update the code so all Solid projects connected context. I did this in SolidStart's Islands implementation I just hadn't in Astro. Our context is independent of the change mechanism. Signals are singleton so there aren't multiple versions on the page anyway.
comment in response to post
Yeah exactly. We have packages like that and people who work with individuals and teams to see that happen. But not quite the same as the educational video content that sparked my post.
comment in response to post
I was going to say basically the same thing. Similar in Solid. It would be a matter of going into the Astro-"your framework" wrapper attaching context to the slot nodes, and then on island instantiation find nearest ancestor with context and injecting it into the render/hydrate call.
comment in response to post
It's tricky when those day to day problems are with the tool they use. It puts us on the wrong vibe right off the start (like we are trying to tear it down). It's odd to teach people React to show them how we do it better. Developers familiar with React get it. But so many people who use it aren't.
comment in response to post
Yeah Solid had only one user back then so I get why it wasn't there at release. I just figured it might have gotten there at some point. Probably too big of a change.
comment in response to post
I mean I've been doing that for years. This one was sparked when I watched another intro video say Vue didn't have a VDOM and that Svelte compiled away the runtime. Both which aren't true.
comment in response to post
In any case I'm ok with how it stands because Composition API a modern Signals APIs, which uses getter/setters and proxies as needed. While Vue 2 Option API does not use a JS Proxy, it is inconsequential as it functions as one, and would use one if built today.
comment in response to post
Vapor works almost identical to Solid where it just takes the signals compiles the template into batch dom node clones and fine-grained effects to update only what has changed.
comment in response to post
I am wrong about Vue 2. it only had getter/setters which is shocking given Vue 3 didn't come out to 2020. I had been using proxies in Solid since around when Vue2 came out. I still consider the options API, proxied API but technically it was all nested getter/setters so calling it proxy isn't right.
comment in response to post
They are all forms of Signals.. (autotracking reactivity). Vue 3 took a primitive form so I called it out as such but proxy/getter/function call are all API choices but don't change identity. Like with Alien Signals they will still have proxies for deep tracking. Same way Solid has proxies.
comment in response to post
I think all the frameworks have a vision. Maybe it isn't communicated well enough but they all give me specific unique vibes. I think maybe there is a way I can create some content that qualifies that.
comment in response to post
Yeah that comes off as adversarial though. We did that a bit with performance early on. And I feel Qwik had no choice but to take that route. People resent you for it because they often don't have the choice in the tool they get to use. I think it is a necessary education but you have to be careful.
comment in response to post
It's a lot easier to sell on superficial things. Flashy demos or unique capabilities. But those capabilities rarely stay unique long. And a more popular solution's promise of getting there one day is often enough again because of a lack of understanding of what that entails.
comment in response to post
This is a lot more effort and leads to people taking more adversarial stances when everything is a head to head comparison. But in the absence of that you risk people not getting it. Those who know, know. A sort of damned if you do damned if you don't.
comment in response to post
It depends on the type of update the model that has captivated Tanstack of late is the one that I created while creating SolidStart. See thread: bsky.app/profile/ryan...
comment in response to post
You keep the client mentality without waterfalls. However, there is a tradeoff. You don't know which data is server only so you still need to serialize everything twice (in HTML/JSON on initial SSR) and you ship more JS code. RSCs haven't solved the first problem, so people are fine with the second.
comment in response to post
The benefit of this approach is you get the whole single request POST and send back the HTML feel on larger updates but it also scales down to single data points on the page without blowing up the whole thing. And the best part it is determined on a per action basis.
comment in response to post
However I solved this with SolidStart with "Single Flight Mutations". At the point of doing the mutation on the server you know what has changed and where you're going. Hoisted router fetching in combination of cache keys to can fetch the required data, and stream it back on the same request.
comment in response to post
The main place this falls apart is mutation, because you have maybe multiple touch points in the UI or maybe you navigate after mutation. Both lead to a situation where after the first "POST" you do another "GET". It's how like Tanstack Query works when you revalidate on Query.
comment in response to post
I think it is because most router based solutions hoist data fetching.. in so they fetch the JS and the data in parallel.. 2 separate requests but they aren't blocking each other at the front. So the difference between a single request that is streamed and parallel requests seems inconsequential.
comment in response to post
Interesting. I wasn't aware of a package for this.
comment in response to post
Compiled scope is a bit more of page from React runtime wise. If you tie things to a region (call it a component) you can make execution assumptions in terms of what runs together. But it is less portable and it requires more tooling. I do think it can make sense for Svelte here.
comment in response to post
Yeah this is the classic problem, compiled deps, compiled scope, or purely runtime. Solid has opted for the last which is why the split effects make sense. It isn't something you can fix with a compiler. Compiled deps we know is limiting from (Svelte 3/4).
comment in response to post
Yeah the await's aren't real, they get compiled away. My understanding is they've opted for a more bounds centric model. Instead of throwing they hold execution within certain bounds and use the compiler to basically tell the async primitive it needs to do that before it ever runs.
comment in response to post
Honestly, I have no idea how to fix this. TypeScript is a bit of a weakness for me and after trying multiple things that don't work, I'm pretty stuck. I've brought it up a few times around core team but no one really knows what this is supposed to look like. I think we are going to need help here.
comment in response to post
I think the composition argument is fair. The part that is less obvious is how easy it is to have multiple trees on the page that can entwine. What if you don't need to update the whole page on every mutation. Its a lot easier to picture that in a decoupled model.
comment in response to post
The solution in all cases involves building up a larger data set in a single request on the server. Which becomes more specialized to the UI. So you do make server components in sense. Maybe made of JSON. But now you have to update 2 locations on any code change. It's not unlike MVVM vs Components.
comment in response to post
I think the reason this argument never carries is because people have been solving this problem since the beginning. GraphQL is a solve, hoisting is a solve. The only thing people don't intentionally do is make 30 parallel requests. And a trivial example can always avoid it.
comment in response to post
I can't imagine the performance is great. How bad I don't know as of yet, but it is a way of solving the problem.
comment in response to post
The problem is we "create" the children before we are aware of their parents so how do you get rendered element instead of creating it when you need to do operations on it before returning from the create function? Without ever re-running that function? You could proxy it.
comment in response to post
The single tree are RSCs biggest strength. It's why one day you could solve double data/serialization, how we can know that certain data never needs to reach the client. But if leaned into in practice is a lot more like an MPA with route/state preservation in terms of rendering and mutation.