1. 6

Dear Crustaceans, what would be your favourite setup if you wanted to build a server-side rendered web app and run it as a native (or just single) binary?

Is there something that offers Clojure-like native experience or I should just give up and use Go?

Thanks!

  1.  

  2. 5

    If you want native compilation and Lisp, most of the mature Common Lisps would work. You could also use Chicken Scheme or Gambit. It depends on which of the other two big Lisps you like. Is there a reason GraalVM to produce a single binary of your Clojure app won’t work for you?

    There are other crazy things, too, if you don’t mind not Lisping. SWI-Prolog has a web server. The Seaside web framework in Smalltalk is pretty delightful. Haskell’s web backend story is pretty strong, too.

    1. 4

      Janet is an interpreted language that looks a lot like Clojure, but its semantics are more similar to JavaScript. It can produce native executables that statically link the Janet runtime and interpreter, although the Janet code you write is only compiled to bytecode. But the single executable means that it’s very easy to deploy, and the runtime is tiny. There is a friendly HTTP framework that powers, e.g., https://janetdocs.com/.

      How’s SCI’s runtime overhead? I have no idea if it’s up to the task of running an HTTP server, since I’ve mostly heard of it through Babashka. But it would probably work, right?

      There are also people writing ClojureScript, compiling it to JS, and running the result via Node. Which is not at all “native,” but fits the bill for a lower memory-overhead way to run Clojure code.

      Common Lisp is the “obvious” answer for native binaries, but it’s not very Clojure-like at all. Chicken Scheme also compiles to native code. So can Racket, apparently? But if this is only for fun, you can probably get away with one of those interpreters.

      1. 3

        There has been a ton of Common Lisp web tooling for ages, ranging from just web servers to full frameworks. Maybe this book would help? (I like it.) https://leanpub.com/lispweb

        1. 3

          SBCL (or Common Lisp in general) is pretty boring and supports single binary deploys.

          For example: https://stackoverflow.com/questions/14171849/compiling-common-lisp-to-an-executable.

          1. 3

            A while ago I did a proof of concept using Common Lisp (specifically SBCL) for just this. It also ran nicely in AWS Fargate connected to an AWS RDS database.

            1. 2

              What does “native” mean in this context, and why is it relevant? Do you just want “clojure-like without the JVM” or is there something else you are looking for? (Do you care whether the lisp is literally AOT-compiled to machine code?)

              Fennel can compile to standalone binaries of around a minimum of 200-300kb, but it’s not “native” in that most of those few hundred kilobytes are taken up by the Lua VM (or add another few hundred kb for a major speed boost by using LuaJIT instead). But it is a single-file self-contained executable which can be statically-linked if you want. Pulling in C libraries for sockets is a bit more work but not too much hassle.

              1. 3

                OK, you got me. Maybe it’s less about “native” and more about “minimal memory requirements”. Like: cramming 10 small web apps on a small 1GB VPS, instead of just ~2 with Clojure (I know I could go Tomcat route instead of a separate Jetty per app).

                1. 3

                  Well, Fennel is more commonly used for programs that don’t run on servers, but this could be a good fit if you’re not going to be bothered by the smaller library availability of the Lua ecosystem. Most Fennel web programming is done inside OpenResty but if you really have your heart set on doing it from a standalone binary that should be doable too. Ten small applications in 1GB should be no sweat either way.

                  Drop by #fennel on Libera or #fennel:matrix.org if you have questions and want to explore further.

              2. 1

                Go, Rust, … or you could try and see what happens when using a Graal Native binary. I’m curious.