Full stack languages
Introduction
Section titled “Introduction”For a long time JavaScript was the only choice for full-stack development. But recently there we see more and more alternatives.
Full-stack languages have one obvious advantage: you need to use only one language for development (aside from CSS, HTML, SQL etc.). But there is more - it also allows to use “transparent” RPC.
In “classical” approach one would need to define special layer for communication, something like:
- REST endpoints
- OpenApi specification
- Maybe some kind of transpiler which would translate from OpenApi to Typescript and runtime validators ↗
- client, for example TanStack Query ↗
But if you work with only one language you can avoid all of this. For example, React’s "use server" ↗:
async function requestUsername(formData) { "use server"; const username = formData.get("username");}
export default function App() { return ( <form action={requestUsername}> <input type="text" name="username" /> <button type="submit">Request</button> </form> );}Other examples: Qwik’s server$ ↗, Solid use server ↗.
And on top of it you can add TypeScript and have type checking across frontend and backend.
Downsides
Section titled “Downsides”- Frontend and backend are coupled. In case of SPA frontend can be out-of-sync with backend, so any change to backend may break frontend
- HTTP GET requests are often cacheable. Current implementations of
use serverdoesn’t seem to provide any similar mechanism - TanStack Query ↗ provides additional improvements, like retries, explicit loading/error states, refresh on windown re-focus, periodic refreshes, etc. It’s probably possible to implement, I haven’t seen anything yet
- REST and RPC both can have “waterfall” issue (GraphQL less so). But I guess this can be solved with
<Suspense>and some compilation tricks- related “TIME TRAVEL RPC” ↗
- security concerns: HMAC-SHA Signature, CORS, etc.
- potential serialization issues
Alternative
Section titled “Alternative”I think this approach is more superior than GraphQL or tRPC. Only one different approach may be comparable - offline first applications, when you work with local DB and it synchronizes with background transparently (ala OT or CRDT).
Actor model
Section titled “Actor model”This approach remids me actor model. In the sense that function call can travel across network (if actor is on a diffrent machine), without any need to declare transportation/serialization scheme.
Related:
- lunatic ↗
- lam ↗
- ractor ↗
- SIWA: Wasm Serverless Actors for the Edge-Cloud Continuum ↗
- Web Workers in Swift Wasm via DA ↗
- GoldFish: Serverless Actors with Short-Term Memory State for the Edge-Cloud Continuum ↗
Clojure
Section titled “Clojure”Gleam (BEAM, Erlang)
Section titled “Gleam (BEAM, Erlang)”- Wisp and Lustre ↗ (no transparent RPC)
- jaspr ↗ ?
- ?
Kotlin
Section titled “Kotlin”- ?
ReasonML / Rescript
Section titled “ReasonML / Rescript”- ?