reflex icon indicating copy to clipboard operation
reflex copied to clipboard

Support compiling Reflex app into an executable

Open cowboyd opened this issue 2 years ago • 5 comments

I would like to be able to distribute an entire web application as a compiled ahead-of-time executable that has all bundled dependencies, including the web app itself so that it can be used as a dependency free tool.

Once compiled, this single file should not need to download anything upon invocation. Specifically it should contain:

  • Deno.
  • reflex
  • react, react-dom, et al.
  • compiled app code

Things it should not need to do upon invocation:

  • d/l from esm.sh
  • d/l from deno.land
  • Ideally, it would not even need read/write access to the cache because the cache would have been pre-generated ahead of time.

Deno has support much of this with the deno compile command which downloads and compiles the tree of dependencies starting at its entry point, but where to put the web application and static assets is another matter. Upon cursory inspection, I found these libraries out there for bundling assets with an Deno executable.

  • https://github.com/mandarineorg/leaf
  • https://github.com/txthinking/denobundle

In both cases, it appears that the assets themselves are encoded as binary data within typescript files. Reflex would just need to support some sort of adapter to load its cache and other assets from some type of store.

cowboyd avatar Jun 09 '22 09:06 cowboyd

Other considerations such as performance not withstanding, of the two bundlers, denobundle seems the best choice since it does not take over the full responsibility of deno compile like leaf does. Instead, you just compile your entire directory into a single typescript file but it does not prescribe what you do with that file.

There may be other libraries as well.

cowboyd avatar Jun 09 '22 09:06 cowboyd

Deno emit was split off into a module https://github.com/denoland/deno_emit and that also includes the bundle functionality. I'm just linking it here to document it :)

Industrial avatar Jun 11 '22 21:06 Industrial

@Industrial Have you had a chance to think about being able to provide an abstraction around the cache so that it can be pre-build into a TS file?

cowboyd avatar Jun 14 '22 09:06 cowboyd

I'm now trying to work deno_emit into the equation so that each importMap.json entry will be just one file bundle and then those are cached.

Industrial avatar Jun 17 '22 09:06 Industrial

This is harder then it seemed before I started working on it. React is not made to be loaded twice. Even if you load the same version of react but one is bundled into let's say MaterialUI or another library then you will get a Hook Error.

Bundling works fine with other libraries because they don't contain the react "version checking" code.

Bundling everything into one file is pretty easy and I don't get the hook error on the SSR but it's the client side that is the problem. I can't bundle the client side into one file because that will not work with Streaming Server Side Rendering.

Industrial avatar Jun 19 '22 20:06 Industrial