solidjs / solid

A declarative, efficient, and flexible JavaScript library for building user interfaces.
https://solidjs.com
MIT License
32.05k stars 914 forks source link

Have you ever considered porting solid to deno? #135

Closed matthewharwood closed 3 years ago

matthewharwood commented 4 years ago

It would be quite the lift but might get some really interesting traction with solid.

http://deno.land/

ryansolid commented 4 years ago

Yeah I honestly have no idea what this would take. Although given Solid is TypeScript and is designed to run in the browser primarily it would just be a matter of running the build tools. I imagine SSR would take some effort given Solid uses DOM apis. But maybe after I get a string renderer working looking into this could be worth it.

matthewharwood commented 4 years ago

https://gist.github.com/matthewharwood/e0bfba1f52fd9831a6c5a243212be5e2

here's a gist of it working with preact

ryansolid commented 4 years ago

Right so that is just a matter of setting up an import map similar to what you would do in the browser. I imagine JSX transpilation would be a bit harder. But the HyperScript and TaggedTemplate literals could work in exactly the same way as your Preact example. Minus the fact that they currently work with DOM APIs so I handle this in node by patching DOM environment with BasicHTML or JSDOM.

Is it common to execute deno with an import map like that? Are people making special builds or different repos for that? In any case I think the JSX transpilation and the need for DOM env on the server are both going to be the immediate challenges here.

matthewharwood commented 4 years ago

It works with jsx out to of the box today... and you can override the tsx config https://deno.land/std/manual.md#typescript-compiler-options

import { serve } from "https://deno.land/std@v0.39.0/http/server.ts"
import React from "https://dev.jspm.io/react"
import ReactDOMServer from "https://dev.jspm.io/react-dom/server"

const s = serve({ port: 8000 })

console.log("http://localhost:8000/")
for await (const req of s) {
  const body = ReactDOMServer.renderToString(
    <div>deno</div>
  )
  req.respond({ body })
}

About import maps ... I hve no idea... i just learned about them today and the reference is pretty small. Moreoever bundling in deno with import maps was released today lol (I had to bundle master up via rust lang run it all) https://deno.land/std/manual.md#import-maps

ryansolid commented 4 years ago

I need babel. TypeScript can't transform Solid's JSX effectively. They only know how to do React style VDOM JSX. I imagine stuff like that could just work, and truthfully it's at build time so while it would be cool for it to all be deno it doesn't need to be to use deno at runtime. At which point it's much simpler because it would already transformed. Throw in rollup and there is no need for import maps because it's already bundled.

So if the idea is to use deno as direct runtime without a compilation step it can work (hyperscript/tagged literals) but it would never be as good as precompilation.

I guess with precompilation that part simplifies unless your end-user code use node APIs. Solid is built for the browser so itself doesn't have any calls that would make it incompatible minus the DOM calls themselves. So I guess that's the only question. When I get string gen SSR though this should be smooth.

chasm commented 4 years ago

I would really like to see solid usable with deno. I haven't looked closely at this yet, but I believe you can use babel with deno using jspm.io.

https://stackoverflow.com/questions/62058070/how-to-use-babel-in-deno

sophiabrandt commented 4 years ago

There is an open issue on the Babel repo for adding Deno. As @chasm mentions, it seems that you can use babel/core via jspm: https://github.com/babel/babel/issues/11543#issuecomment-638807750

@SaekiRaku, just a note, I was able to use babel/core via jspm in deno, it works, but you don't have any typesafety.

import babelCore from "https://dev.jspm.io/@babel/core";
import babelSyntaxJsx from "https://dev.jspm.io/@babel/plugin-syntax-jsx";

const result = babelCore.transform(svgText, {
    plugins: [babelSyntaxJsx],
    configFile: false,
  })

I enjoy Solid and it would be great to be able to use it with Deno. :heart:

ryansolid commented 4 years ago

Well that's great. I guess the challenge is node/npm consists of a much wider ecosystem than just the node runtime. Like we use Rollup or Webpack to bundle code for the browser which uses node but never actually runs the generated code on the server. What is more interesting to me, since I compile for the server as well, is does the compiled output have to be different. It writes import statements and it feels like node import statements would differ?

I've done work so that import maps can work in the browser. But admittedly there is just so much I don't understand about Deno,

andykais commented 3 years ago

just to be clear, the babel snippet above is not actually running at compile time, it is transforming code at runtime. It would need an eval block to actually execute. I dont know how this actually fits into your use case, but I believe that you solidjs needs a compile time step in order to function properly

ryansolid commented 3 years ago

Yes. Doing it at runtime just adds unnecessary complexity. From that perspective ignoring the build tools it doesn't seem to far of a stretch to make an output that is Deno friendly. The only node native API solid uses on the server is readable stream. I've moved away from JSDOM and just use string concatting. A simple entry point like the examples in the solid-ssr package would probably do the trick assuming we had a module solution. That being said prebundling would probably remove most of the headache.

So let's say I used Rollup and Babel to make a server bundle what sort of obstacles would you see Deno having?

andykais commented 3 years ago

first, lets lay out what your plan is here. Are you suggesting end users write a server that is only compiled by deno?

andykais commented 3 years ago

If so, I think if you developed solid to be a deno friendly ssr module you could potentially get a working server, but its going to be a bit hacky. A solidjs ssr server ran with deno run cannot do compile time babel compilation. Therefore, you will either need users to run their project through babel (or babel + rollup) before calling deno run or your solidjs compiler will need to read in the jsx files as text files, transform them using your custom jsx transpiler, and then eval them. This is a possibility, but its definitely a little hacky. You could perhaps make this "as fast" as it is in nodejs by create an in memory cache of the outputs so that the server just passes in a filename and can immediately get back the compiled module.

This is assuming you want deno to be the single compilation step though

ryansolid commented 3 years ago

I mean that is sort of the problem I've been trying to figure. Someone asks "consider porting Solid to Deno" at a point Solid didn't even have SSR really. I don't even know what the expectation would be here. Do they want to build with Deno? Do they want it to run SSR in Deno? Are people interested in Deno interested in the fact having native typescript and bypassing the npm ecosystem stuff would be primarily runtime based at which point people might not be interested in compilation? That's an option too just not a great one.

andykais commented 3 years ago

Are people interested in Deno interested in the fact having native typescript and bypassing the npm ecosystem stuff would be primarily runtime based at which point people might not be interested in compilation

I think the first part of this is true. I think deno has a lot of interest because a lot of people find it more ergonomic than node, and because for most cases, users do not need to set up build systems. So, there has been a lot of interest in porting frameworks that have complex build systems (like react, solid, svelte, vue) into deno. The problem though, is that these frameworks do require build systems.

I hate advocating for waiting, but there is a ticket in deno for allowing external compilers https://github.com/denoland/deno/issues/1739. This is really the ideal case, where you can hook into deno's build system and it will handle caching and executing the compiled javascript for you. If this is also your ideal case (and for anyone reading this), I would recommend giving the issue a 👍 so the devs see the interest.

If you are interested in getting solid off the ground in deno now, you probably could, but youre going to have to maintain your own build system within solid, and handle whatever requirements your users have as well (do they want TS in their jsx files? Do they want babel macros? Do they want webpack module loaders?) I imagine it would look something like this:

const solidModules = solid.ssr({ index: 'index.jsx' }
console.log(solidModules.index(props)) // outputs an html string

[edit] I just saw your runtime options https://github.com/ryansolid/solid#no-compilation which is definitely something you can drop into deno for.

ryansolid commented 3 years ago

@andykais Thanks so much. That is the sort of perspective I was looking for. I agree for compilation we wait. My tact with Solid to date has been use what is already there because as an individual with a small set of contributors I'm not going to rebuild the world. The use of Babel and JSX are testaments to this approach where I was able to move much faster at the beginning than having to build my own template system.

I think if someone wants to go the no-compile route in the meantime I would definitely try my best to support them in that effort, but I will need them to take the first step and do some exploration to see what works and what doesn't. This issue seems prudent to wait to see where things land. As much as it would be nice to get ahead of it, I'm not going to be able to spearhead this.

andykais commented 3 years ago

Totally valid. You have built a wonderful library here that does things in an extremely efficient manner, but also has very little friction to adopt. I think familiarity is a fine pillar to stand solid on top of. Im sure this conversation will come up again when deno has a better answer on external compilation. Ill be interested to see how we can solve it here then :slightly_smiling_face:

shadowtime2000 commented 3 years ago

I think if you have support for SWC (ryansolid/dom-expressions#10) you could then run it through deno_swc and it should work.

ryansolid commented 3 years ago

@shadowtime2000 That sounds promising. On the list so if that gives a direction here I think that would be great. I was worried custom plugins would be a non-starter but that would be incredible.