isServer returns false on the server with Deno
Describe the bug
I've been using SolidJS together with Deno successfully, I just use hyper DOM expressions instead of JSX and I think I even prefer it like this.
However, I was trying out the new ssr capabilities and noticed that the isServer function returns false even when I run it on Deno.
Your Example Website or App
https://deno.land/
Steps to Reproduce the Bug or Issue
Run the following script like this deno run bug.js:
// bug.js
import h from 'https://cdn.esm.sh/v84/[email protected]/es2022/h.js'
import {renderToString,isServer} from 'https://cdn.esm.sh/v84/[email protected]/es2022/web.js'
console.log(isServer)
console.log(renderToString(()=>h('h1', 'Hello')))
Expected behavior
Output true
Screenshots or Videos
No response
Platform
deno 1.24.3 (release, aarch64-apple-darwin) v8 10.4.132.20 typescript 4.7.4 solid-js 1.5.4
Additional context
I've tried fixing this myself but did not see a clear path forward but I might know why we get this behaviour.
When the js module is created by http://esm.sh it does so by using the code in solid-js/web/src and not solid-js/web/server.
Yeah can we leverage conditional exports in deno? By default only make ssr build with node export. But this came up recently with workers too. I could add all these, but almost wish to just make a server export and have it settable for all of these. I imagine with Deno this might be more challenging if we can't set these conditions. Import Maps is potentially another option.
Deno has conditional exports in when running with --compat, and you can have a "deno" condition, but I don't see how that will help in this case.
I've tried another quick workaround with something like this:
import client from 'https://cdn.esm.sh/v84/[email protected]/es2022/web.js'
import server from 'https://unpkg.com/[email protected]/src/server.js'
const IS_BROWSER = typeof document !== 'undefined';
export function renderToString(e) {
if (IS_BROWSER) {
return client.renderToServer(e)
} else {
return server.renderToServer(e);
}
}
The problem with this is that it is also difficult to make a esm for dom-expressions beacuse of 'rxcore".
Yeah and we have different runtimes and compilation. Ideally we'd want to write the code from a single import regardless of the platform. Export conditions make this really easy as the code in the browser and server can be different and we basically rely on this behavior to import the right version. Making a deno export condition could assure the right version gets included.
Why are you messing with dom-expressions directly? Solid basically builds that into the library. Are you trying to build a version of HyperScript that works with SSR? Because currently, only JSX supports SSR, mostly that the output is not only different for the server but different for the client as well to allow for hydration.
I wanted todo something similar to deno's fresh which uses preact. I was under the assumption that SSR worked something like JSX -> hyper dom script -> html. But I guess CSR and SSR are just too different especially with the hydration step. Like if I understand it better it should not just be IS_BROWSER but also checks for is_hydrated and needs_hydration and stuff like that. Depending on where you are in the renderer.
Deno does support the conditional exports if you make your project a hybrid between node and deno. If tested this and it sort of works but I thats not the deno DX I was hoping for. At any rate I do think there needs to be a way for deno to know when what part of the renderer is running where, otherwise you still have the problem that deno import just one behaviour when using conditional import.
Yeah generally we don't do JSX -> HyperScript. This way we can optimize the compiler for the platform, and we use export conditions to optimize the runtime for the platform. This happens all without flags or additional aliasing etc. We can configure a plugin for most bundlers and it just works.
I'm unclear how Deno would either mind you. But build step + export conditions make this trivial with existing tool chains. Not to mention our JSX transform not only offers better DX, performance, and size. I hope there is a way in the future to be able to fully leverage what we are doing here. I mean in general we aren't alone when you consider custom bundling and build required for all the cutting-edge frameworks especially those focused on hydration.
Fresh sort of got in a loop hole because their setup happened to be supported by Deno's tooling choice, but long term this is a very stifling position to take and will get in the way of innovation if they don't expand what they can do.
But to be productive ultimately what I'd like to see is:
- Ability to run code through different custom compilation server/client
- Ability to ship different code to server and client from the same import statement
- Ability custom bundle the client code to ensure minimal JavaScript (ie treeshake at a sub module level).
I think if we get these Deno will be a great platform for most frameworks.
1.5.6 now has deno condition which is really all we can do right now.