Server side setup for ReScript client side?

What Server side setup (mostly storing things in a CRUD db) goes well with a ReScript client side?

If agonistic, will probably go with MySQL for DB.

Mainly looking for something where client <-> server communication can be auto serialized / deserialized / typed.

I donā€™t think thereā€™s any server-side technology that specifically targets talking to a ReScript client (I could be wrong). PocketBase is pretty simple and easy to set up, though (single binary, serving single SQLite DB file). And it serves a JSON API derived from your database schema in a predictable way, so would be easy to just write down the expected types and ā€˜magicā€™ convert them from parsed JSON. E.g. I just created a collection posts with two fields title and content, and the API response preview looks like:

{
  "page": 1,
  "perPage": 30,
  "totalPages": 1,
  "totalItems": 2,
  "items": [
    {
      "id": "RECORD_ID",
      "collectionId": "fzd019dixstilec",
      "collectionName": "posts",
      "created": "2022-01-01 01:00:00.123Z",
      "updated": "2022-01-01 23:59:59.456Z",
      "title": "test",
      "content": "test"
    },
    {
      "id": "RECORD_ID",
      "collectionId": "fzd019dixstilec",
      "collectionName": "posts",
      "created": "2022-01-01 01:00:00.123Z",
      "updated": "2022-01-01 23:59:59.456Z",
      "title": "test",
      "content": "test"
    }
  ]
}

As you can imagine, itā€™s easy to model the types in ReScript:

type page<'item> = {
  page: int,
  perPage: int,
  totalPages: int,
  totalItems: int,
  items: array<'item>,
}

external decodePage: Js.Json.t => page<_> = "%identity"

type post = {
  id: string,
  created: string,
  updated: string,
  title: string,
  content: string,
}

Now you can do something like:

// : unit => promise<page<_>> (inferred from usage)
let getPage = async () => {
  let resp = await Fetch.fetch("/api/collections/posts/records")
  let json = await Fetch.Response.json(resp)

  decodePage(json)
}

let getFirstPostTitle = async () => {
  let page = await getPage()
  page.items[0].title
}
1 Like

I canā€™t find the post in OCaml forums, so apologies if I am confusing you with someone else. I think, in a different post, you suggested Introduction

I was wondering if we can construct a ā€œpoor manā€'s version of that tech here as follows.

  1. have common.ml, which is readable by both OCaml & ReScript, and defines some data types

  2. ensure OCamlā€™s json of common.ml and ReScriptā€™s json of common.ml use the same encoding

  3. Now, we get typed OCaml http server <-> ReScript in browser typed communication for free: add your type to common.ml, and there it goes.

You can see an example similar to what youā€™re suggesting here on the Dream github page: dream/example/w-fullstack-rescript at master Ā· aantron/dream Ā· GitHub . Itā€™s dream, not eliom, but it could serve as an example for you to build on.

Iā€™m sorry, I think I am missing something very obvious. How is it ensuring that for all structs / enums defined in the common/* directory, the json representations line up ?

Ahh, yeah I just realized I kind of ignored your point 2 in your second post, sorry about that :sweat_smile: I was focused on the points 1 and 3ā€¦ common.ml defining datatypes and the ocaml on the server, rescript in the browser, which is all that example shows.

For json I would probably use atdgen, mainly because I use it in ocaml (and it apparently works also with rescript), and so I already know how it works. Pretty sure there is a bs-atdgen somewhere for use from rescript.

Just wondering, if youā€™re already going to pick rescript rather than jsoo, why not use rescript on the server with node? (purely out of curiosity)

Thank you for sharing this library. It looks great. Iā€™m looking at Welcome to ATDā€™s documentation! ā€” atd documentation . Is there a tutorial for writing a generator for a new language? (I need it to also hit Rust).

Multicore, libraries (OWL, MySQL, Postgres), generally not a fan of node.

No problemā€¦yeah atdgen has worked nicely for me in the past. Not sure about rust support, or how to go about getting it to support other languagesā€¦but I would love to see it added, ha.

Makes sense. At the risk of going off topic, let me ask one more questionā€¦since you like the ocaml ecosystem, rather than node, why not use jsoo rather than rescript, and stick with ocaml? (I saw your jsoo-react question in the other forum, so Iā€™m wondering if youā€™re using rescript for its nice react support, or for another reason?)

Edit: just curious about your thought process on choosing between them. But that may be going too far off the original topic.

1 Like

Mainly looking for something where client <-> server communication can be auto serialized / deserialized / typed.

If youā€™re just looking for the communication part, I built a RPC library which handles the communication and all the serialization / deserialization stuff (in a very simple way. Probably it doesnā€™t work for complex data types).
It is written in and for rescript (the client and server), but maybe a good inspiration?

If youā€™re interested, have a look at https://github.com/dkirchhof/rescript-rpc

Thatā€™s a great question. I would not say I am committed to either .What I do believe though is that I should figure out what ā€œoptimal flowā€ feels like in both before deciding which to go with (rather than make the decision while only having novice level in both). I.e. steelman, figure out what expertise feels like in both, then decide what to go with.

1 Like

Makes senseā€¦I would be interested to hear what you end up going with.

I suspect you are more knowledgable than me in both ReScript and Jsoo. I am curious to hear which you use more and why ? I.e. their tradeoffs.

Day to day, I use OCaml, and right now, its ecosystem covers my needs. Though, I have made a few small javascript targeting projects using rescript, because similar to you, I wanted to get a feel of how it was working with js ecosystem with rescript (itā€™s good, as Iā€™m sure others here would agree ha). In fact, I have a legacy JS app that needs a lot of love, and am planning on doing further work there in Rescript, as the interop is quite smooth. Going forward, I have more JS work planned, and then itā€™s a bit harder to choose. I already am comforatble with ā€œThe OCaml Way :camel:ā€ , but Rescript just makes it so straightforward to work with JS stuff.

Generally, the advice I have heard is if you need or are already using JS ecosystem, then use Rescript. If you need or are already using OCaml ecosystem, then use js_of_ocaml. And Iā€™ve found that to be good adviceā€¦eg jsoo magically turns my ocaml code (and otherā€™s code too) into something workable for the browser, so, big time saver, especially if JS isnā€™t your main focus.

tl;dr ā€“ rescript and jsoo are both awesome, but really have separate goals/targets imoā€¦if thereā€™s a killer library you canā€™t live without on either side, pick that side. If targeting JS and being a bit more frictionless in that environment is critical, probably pick rescript. (But ffi in jsoo is defined well, so you can of course do that do. Eg, brr makes ffi from jsoo pretty nice, but it does feel a lot different.)

Edit: btw, you will find many more opinions (some very strong indeed) on this topic in posts throughout the years, either here or in the ocaml discussā€¦I imagine youā€™ve seen many of them, but I would just say while reading them to keep in mind that though rescript and jsoo have sort of different goals, they are both nice technologies to work with.

1 Like

One thing Iā€™m really appreciative is how logical/pure-merit both the ReScript & Jsoo communities are. Typically, in a dogmatic community, if one asks:

ā€œHow do I do XYZ?ā€

there are often responses of:

ā€œWhy would you want to do XYZ? XYZ is unidiomatic, etc ā€¦ā€

where here, in both communities, it is extremely level headed, and it seems like both sides are very good at steel man -ing the arguments of the other side.

1 Like

Yeah thatā€™s a good point. I think you (and me and everyone using either of them) can thank the community leaders for setting a good tone.

This might be a bit premature, I think at this point, after spending a few weeks studying both, Iā€™m leaning heavily in favor of jsoo. The reasoning goes something like this:

Pro ReScript:

  • rescript-lang.org is some of the best documentation Iā€™ve ready
  • blazingly fast compiler
  • integrates nicely with react / jsx
  • readable output

Pro Jsoo:

  • I actually prefer *.ml syntax to rescript syntax. In particular, Iā€™m a big fan of higher order functions, (limited) point free programming, and currying.
  • Jsoo-react syntax isnā€™t all that bad. After running into a few brickwalls, itā€™s pretty intuitive now.
  • OCaml libraries are insane .[@@deriving sexp] for example, is really useful; even if this is supported by Rescript, Iā€™m sure Iā€™ll run into this issue in the future
  • Regardless of client side; Iā€™m going with OCaml, not node, on server side. Iā€™m not smart enough to constantly swap syntax when switching Server-OCaml / Client-ReScript. The mental switch is frustrating.
  • Free obfuscation. Imagine I write something in jsoo + run a minifier. An adversary comes along, runs a de-minifier, and gets ā€¦ continuation-passing-style OCaml byte code. LOL.

The way you describe your situation and preferences, you are definitely right to go with OCaml, because it will match your coding style way better than ReScript. Just be aware that JSOO bundling may be quite excessive, depending on what you are building. I would definitely not use JSOO to build a website, unless I am compiling a language compiler to a standalone JS bundle (like we do for the ReScript playground).

Now thinking about it, I guess the best way to build web applications in OCaml is to join Ahrefs, because they commit a lot of resources to make it work for bigger organizations and applications ā€¦ and using a fork of ReScript to make things work on both ends :smile:

Regarding pros and cons, I think one important aspect that a lot of engineers tend to forget for their excitement of a technology is that you need to eventually scale up business and hire / onboard more ppl in your product development process.

ReScript is already more challenging to hire for than e.g. TS, but I think we did an okay job to onboard JS / TS devs to the platform without the need of extensively re-teach how to develop for the web. At least this is how I feel about it after the past few years; new folks are coming into our community and get to play with the language in their existing stack rather quickly.

Always keep in mind that companies are in the need of juniors that get productive rather quickly and the pool for hiring new devs is quite limited (esp. if they hire locally), so we tried to build a language ecosystem that allows devs with basic web development experience to get something done in a reasonable amount of time without a lot of handholding.

Sorry for the tangent, but I think we donā€™t talk enough about hiring capacities when discussing trade-offs.

11 Likes

My JSOO bundles, after esbuild minify, are in the 1-2MB range. I realize how horrendous this is (back in the day, 1.44 MB 3.5-in Floppy Disks were precious), but I think it is negligible on both desktops & modern phones. I have not measured this, but I think React + CSS + other node packages are often verbose enough that JSOO vs ReScript end up being a rounding error.

Re Hiring: Iā€™m not qualified to comment on that.