Lambda function in ClojureScript: How? Where?

Hi, I am once again asking for your support to get started with ClojureScript so that I can have something working end-to-end.

Currently, I was thinking of doing something simple, not much more complex than a “hello world.”

In fact, I would be happy with a hello world that I can deploy in a lambda function, either in AWS, Netlify, Firebase, or anything… preferably something with a free tier. If I can get a parameter in the URL and return “hello $parameter,” that’s already good. I just have no idea where to start from.

The second stage of the lambda function is a bit more complicated, just a bit. The plan is:

  1. get a URL as a parameter of the URL.
  2. get the contents of that URL.
  3. process them with readability.js (ClojureScript for .js compatibility — not Clojure)
  4. display (return) the readable result.

There are approximately endless tools to build the project: lein-figwheel, lein-buildcljs, shadow-cljs, lumo,… and, similarly, plenty of options to host a lambda function like this. The main problem is that compatibility seems incomplete, and by past experience, I guess most combinations lead to pain. So I decided to ask before running into a field of rakes.

I hope it is not much more complicated than it seems…

Nbb is also an option: AWS Lambda, now with first class parentheses
With just a few lines of code you can write your lambda.

If nbb isn’t what you’re looking for, I’d recommend shadow-cljs with either :target :esm or :target :node-script.

2 Likes

“Where?” should have been the first question. My mistake.

After some research, Vercel is my first candidate. I hope I will not run into too many rakes.

Next in the list are Netlify, Railway.app, and Fly.io. I think Vercel and Netlify are likely to be the easiest, allowing frontend and backend in ClojureScript. Railway and Fly.io seem to be more container oriented than lambda oriented, which seems an overkill for this.

If you see me running towards a field of rakes, this is a good moment to tell me to stop.

With respect to the “How?”

It seems all it takes for Vercel is .js files that export one default function each in the pages/api path, so I guess either Nbb or shadow-cljs may produce those .js files, pointing the source to a path like cljs having the functions in cljs/api, and mapping the output of shadow-cljs to pages so that pages/api is generated; hopefully without unnecessary code from the ClojureScript runtime. IIRC the closure compiler removed the code that was not used, but I do not know if it runs in this context.

I’d recommend nbb, like borkdude did, or shadow-cljs. To write “lambdas” I am using shadow-cljs to compile to a :node-library target (as opposed to the usual :broser target which I use to write my frontend. Then as to where (to deploy), I have been using Firebase for a while and I am liking it. (To be more specific, my “lambda” is deployed to Firebase Functions.)

I’d love to be able (ie have the time presently) to write up an article about how this can be put together—shadow-cljs to build; Firebase Functions to deploy; (I should mention Firebase Hosting for the frontend)—because I think it’s really slick.

The trouble with giving advice in this area is not knowing what exactly you are after.

Vercel is huge, it does so many things. Same with most other platforms. Your initial description sounds simple enough, yet I cannot find how you’d even do that on Vercel with any language.

If you can point to specific examples/docs this would be easier to answer. Like here is this repo that runs X on vercel. “How do I do the same in CLJS?” is a much easier question to answer.

I’m going to add the maybe unpopular opinion that you should never use nbb for any deployment. Seeing it recommended multiple times here makes we want to write a longer post and why it is bad for any deployment, as in not “scripting”.

I created an example repo for this. Doing about what you asked for, although it doesn’t take the URL from a parameter yet and instead has one hardcoded. I’ll leave you do figure out how to get it out of the event arg.

Feel free to ask questions, if anything is unclear.

If you mean that nbb isn’t as performant as compiled CLJS: yes, that is something to be aware about!

Also nbb (like babashka) can’t run all CLJ(S) libraries: that’s also something to keep in mind.

Yet there are use cases where nbb is convenient and yet sufficient: (almost) no build config, faster prototyping in production, being able to edit the source in the AWS console. This convenience sometimes makes up for performance and full CLJS compatibility. @ray-mcdermott has done several benchmarks to compare compiled CLJS to nbb for his lambdas and the overhead of nbb was ok enough, at least at the time when he wrote that blog post.

What is “scripting” anyway? A lambda is in many cases a just a small script, that happens to run on someone elses computer :slight_smile:

When it’s not ok anymore and your project outgrows the constraints of nbb, you can always migrate from nbb to shadow-cljs to get the better performance. The migration should be smooth and there should be no vendor/framework lock-in. It’s documented here.

I guess all roads lead to shadow-cljs anyway since nbb is also built with shadow-cljs :sunglasses:

Honestly, it’s astonishing how much of enterprise software exists outside of a hotloop.

1 Like

I am not going to be able to work on this for a while. I have an MWE with JavaScript, but I have written down the issues to check that when possible.

Thank you all again.

@thheller I will certainly be using that lambda-cljs repo in the future. Thanks a million.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.