Replies: 5 comments 7 replies
-
Incidentally, I think it really makes sense to include both builds on the server (in general). If you want to do SSR but also want server-side reactivity, e.g. to automatically push data to clients across web sockets, then you want the SSR rendering to not run effects for example, but you want the server-side functions to run effects. This is exactly what this proposal allows, with optional optimizations for cases where you need only one build. |
Beta Was this translation helpful? Give feedback.
-
Another case is that we don't want any other libs (f.e. any Solid components, custom elements, loaded into Electron and it thinking we're in Node so it doesn't work. I haven't tested this yet, but I'm fairly certain it won't work because the detection mechanism is in package.json exports currently, and that doesn't detect Electron.
I believe we should avoid auto guessing. It is bound to fail I think. Instead SSR should be explicit depending on tooling. First, we'd make solid-js package.json exports point to only the regular solid-js. Then this will never fail to give people the real solid-js API. Then, people configure SSR based on their tooling (and we document how, and/or provide starters and Solid Start). F.e. Webpack users can output multiple bundles. Webpack users would have:
Similarly with Vite and Solid Start setup. The default would be that, like any regular lib, if you simply import solid-js, you get solid-js, no surprises. SSR is a special and additional case. |
Beta Was this translation helpful? Give feedback.
-
Hmm, this is not guessing though, and might work, although it adds to the implementation of Solid, rather than build tool configs. So basically we import and use Solid APIs anywhere, except that specifically inside a SSR root it short circuits to the no-ops. 💭 I'm not sure which is better. Less implementation, specific build configs? Or the SSR root with more implementation inside main solid-js? An upside of the conditional checking in SSR roots may be we can eliminate the standalone SSR code, have it all in one place, and we do not need two separate builds.
I think the SSR root idea entirely prevents us from having to worry a out this bullet point, because we just have a single build, a single solid-js lib, and only the usage of the SSR causes the no-op context. Either way, with build configs per build tool, or with SSR root, we can just simplify package.json and make it minimal without it knowing anything about SSR. |
Beta Was this translation helpful? Give feedback.
-
Random side-note, but importing |
Beta Was this translation helpful? Give feedback.
-
@ryansolid @edemaine Here are the high level issues that I think we can solve all at once:
After these changes, Solid will be much more compatible with ESM tooling and environments, and when we import something any solid-js path we will always get what we expect, unless we explicitly opt into SSR via tooling config. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
When used outside the browser, Solid is currently "tuned" for SSR. If you want Solid reactivity in Node, for example, you need to declare a Node condition of
"browser"
, which is potentially inaccurate (maybe you want non-DOM reactivity but don't want other packages to think you're actually on a browser) and sometimes difficult (e.g. Meteor and old Electron don't support Node conditions). It's also a frustrating initial experience: a natural way to try playing with Solid reactivity is in Node, but new users are continually surprised that there's no reactivity despite callingcreateEffect
etc.Goals of this proposal:
Proposal:
main
build ofsolid-js
would include two builds — what's currently the browser build and what's currently the SSR server build — and a wrapper layer that decides which to call.createEffect
etc. (as provided by the wrapper layer) is to use the browser/reactive build. As a result, Solid is always reactive out of the box with no configuration/effort.renderTo___
SSR functions create roots with a specialssr
flag set totrue
.createEffect
etc. calls to the appropriate build according to this flag (depending on the current Owner). As a result, SSR works too — without reactivity and using the string-concatenation renderer — with no configuration/effort.createSignal
will need some tweaking for this to work, as signals don't have owners (and signals are often top-level, before you've "declared intent" by callingrenderTo___
). We'll need to always use the browser build forcreateSignal
. To remove reactivity in SSR mode, the signal setter function will need to detect whether we're in SSR mode and skip dependency tracking in that case; alternatively, perhaps it's enough to just not setListener
when in SSR mode, and the browser signal setter code can work as is.if (Owner?.ssr)
checks in the wrapper layer), you can specify Node conditions of say"ssr"
or"no-ssr"
. Each of these conditions forces the Node build to include only a single build with no wrapper, equivalent to the current behavior with no condition and with"browser"
condition set respectively. We can also define the"browser"
condition to imply"no-ssr"
.Based on Discord discussion with @fabiospampinato, who came up with the main idea here, but looking back I see @trusktr had pretty much the same idea in a Solid Everywhere discussion. I'm just writing this down carefully.
Beta Was this translation helpful? Give feedback.
All reactions