Hacker News new | comments | show | ask | jobs | submit login
Deploying a ReasonML React app with Docker (hasura.io)
137 points by anirudhmurali 5 months ago | hide | past | web | favorite | 43 comments

With pure Reason (No JS bindings) it should be possible to skip Node / Bucklescript on the server and compile straight to binary.

This should be possible with something like bsb-native (https://github.com/bsansouci/bsb-native)

I haven't tried this because I don't have a pure Reason project

Anyone interested in this please look at:


A webserver in native OCaml that's going to beat Node.js (it seems popular cohttp server in OCaml was not cutting it).

I would be really interested about why this is getting downvoted? This seems like a related project, and I was happy to learn about it.

I'm back in the plus. Also cannot imagine someone down voting :-P

not a downvoter, but probably the “going to beat Node” part. an assertion which cannot be proved or refuted, and which is vague but provocative.

edit: actually I became a downvoter just now.

cohttp is not going to beat Node. Compiled code in a reasonably low level language should be able to beat (measures in all resources used, not just response times, but also mem/cpu consumption) an interpreted language for a simple task of responding to network requests. Well, that's at least what I believe, maybe I'm wrong.

this is also a vague but provocative claim. beat Node at what? what's the criteria for success? popularity? performance? security? I don't have a downvote for you, but answering a vague but provocative claim with another vague but provocative claim is not really that helpful in my opinion.

"my language can beat up your language" is like "my dad can beat up your dad."

ReasonML has two compilers -- a compiler that goes to JavaScript, and a compiler that goes to native code (the OCaml compiler, since Reason and OCaml share an AST/etc.) So if you want to use ReasonML with a web server, you have two options:

1) A native web server, or 2) NodeJS.

Because Reason can compile to JS, you can use with Node just like any other compiles-to-JS language. The claim here (which I have no opinion on either way) is that using a particular native OCaml web server with ReasonML is faster than compiling ReasonML to JS and using it with Node.

> that using a particular native OCaml web server with ReasonML is faster than compiling ReasonML to JS and using it with Node.

Faster considering the resources used (mem/cpu). Yups. Exactly that was my claim. Cohttp cannot beat Node, while a natively compiled OCaml server should be able to beat node.

I once read about a project that was basically Node.js as Reason module. They used the OCaml std lib and wrapped it with a a very Node.js like interface, so you could write native stuff with your Node.js skills.

I think you’re talking about this https://kennetpostigo.github.io/lwt-node/

Yes, exactly :)

> This should be possible with something like bsb-native (https://github.com/bsansouci/bsb-native)

Why not just use the real OCaml/Reason compiler ... ?

bsb-native is not a compiler. It uses ocamlopt for compiling. Bsb-native is a build tool, think of it like make

Reason is supported on every major version of the native OCaml compiler (currently versions 4.02.3 up to 4.06).

I know, hence my question! Why go through bs (which is locked to an old version of OCaml) to distribute executables, when you can use the normal compiler and enjoy the latest improvements?

I don’t mean to ignore your observation - it is valid. Bsb is a build system that works with a specific form of packages. What you suggest could work too. The only (small?) challenge is that people have bsb JS projects, and they aren’t configured for jbuilder/Dune etc. Because of JavaScript’s immense popularity, the largest number of people will start with whatever build tools integrate well with the JavaScript ecosystem and work from there. This plays out quite predictably. Just as an example, the most important thing to web developers is that each Reason input file becomes a commonJS (or es6) module. That allows integrating your Reason React app with existing web apps easily. So since people start with whatever tools integrate well with the JS ecosystem, they then reach for the easiest tool available to adopt native compilation.

I think that configuring jbuilder/etc. can be a point of friction for people coming from bucklescript, so bsb-native provides the same workflow for native compilation.

Thanks for the link, but why isn't it part of the article?

It is, but as in image form. I'll link this there.

One annoying thing you'll need to add before this is production-ready is configurable environment config, so that you can deploy the same container for your staging vs. production version of the app.

I use a `patch.sh` as the ENTRYPOINT, which says something like

  echo $API_URL >> /usr/local/nginx/html/config.js
  echo $OTHER_CONFIG > /usr/local/nginx/html/config.js
  exec nginx
Though there may be other ways to achieve this as well.

What can ReasonML do that TypeScript can't?

Full type inference, pattern matching with exhaustivity checker, modules, abstract types, ...

But to be honest, it's not very useful to do checklist-style comparisons — writing OCaml/Reason code is a completely different experience.

For me it results in less worry about how my code would sustain under refactorings — this is one of the reasons I feel more productive with it rather than with TypeScript or Flow or (of course!) plain JS. I can start writing code and don't worry about getting everything right upfront — refactorings are cheap.

I have replied to this question on SO [1], here is quote:

In a large application you will need a lot of features, which are provided by default in ReasonML: strict types, runtime validation if you encode/decode JSON, fast compilation time, immutable data.

In TypeScript you will have to add:

1. ImmutableJS + its typings.

2. Runtime validators like json-schema + its typings. Then you will have to write types in TypeScript, and also defined a schema in json-schemas. They can become out of sync very soon.

3. Some crazy hacks to tell the difference if variable is of specific type (like in official docs of TS: https://www.typescriptlang.org/docs/handbook/advanced-types...., Paragraph "User-Defined Type Guards"). This checks are done using side effects like a.swim !== undefined. In 6 months this 'if' statement will contain more and more checks.

4. You are lucky if a package you use has official and maintained type definitions. Or you will end up with custom typings.

5. If you develop hybrid app in JS + TS, then TS Compiler cannot create a bundled final d.ts file which you can import in other parts of your project. You will have to write separate d.ts files, which are bundled by tools like dts-bundle. If you have everything in TS, then this issue is not applicable.

6. Large apps take a lot of time to be compiled by TypeScript.

With ReasonML:

1. Immutable data is in the language.

2. Runtime validators are present (bs-json has them by default).

3. Pattern matching saves you from these crazy checks.

4. You are lucky if npm package you want to use has BuckleScript bindings.

5. N/A.

6. ReasonML compilation is very fast.

1: https://stackoverflow.com/questions/46147250/reasonml-vs-typ...

Hi, I work on Reason: To add to other comments: One thing that ReasonML can do that TypeScript cannot do, is take advantage of the world-class OCaml compiler to generate very fast native executables. If you learn Reason, then you are also a "native developer" in a sense.

In my opinion one of the most useful features is first-class support for algebraic data types. Using records and variants ('sum' and 'product' types) in Reason one can be much more expressive in terms of how program state and other constraints are defined.

One can get some of the same benefits of sum types in TypeScript using discriminated unions - but the syntax is cumbersome and requires boilerplate as compared to Reason.

Pattern matching with a sane syntax.


TypeScript has to handle every JavaScript quirk, it puts structure in place to help mitigate many issues.

ReasonML breaks from full compatibility, it can pick and choose JavaScript features to compromise between familiarity and functionality.

At the other extreme you have Elm, which has a similar background but won't compromise so can offer a clean break from JavaScript.

> ReasonML breaks from full compatibility

It promises zero compatibility code wise, but very easy interop (FFI) with JS land!

Prevent null bugs.

Typescript values can be null. A pure reason program will never have null bugs.


In case anyone didn't know, since Typescript 2 there is a compiler option to enable strict null checking.


Only since 2.7 (very recently) can you actually enforce initialization of class properties: https://www.typescriptlang.org/docs/handbook/release-notes/t...

I was just wondering about this today; thx for the link! Not sure how I missed it.

Unfortunately, libraries such as React have their own component lifecycle management, which doesn't play well with this (https://reactjs.org/blog/2015/12/18/react-components-element...).

This is also a bit of a pain point on Android with Java @NonNull annotations or when using Kotlin.

Yeah... It would honestly be cool to have a TypeScript native React(as crazy as that sounds). There are some really great projects out there killing it like Nest, MobX, TypeORM, etc.. The React typings have come a long way though.

I do quite a bit of TypeScript for the server though(less context switching and is mostly GoodEnough™) so still handy.

Angular plays very well with typescript, because the entire framework is written in it, more than that, Angular Team is working with TypeScript Team to help make TS better, and vice-versa.

Not true, TS has strict null checking

If you look at language itself many things. It's different paradigm.

Unrelated, but does anyone know what font/colorscheme are used in the screenshots? I find it very slick for code presentation.

Haha, it's here: https://carbon.now.sh/

since we use bs to compile, shouldn't we use a node image to compile and then copy them over to runtime image later?

True, optimising with a multi-stage build after `yarn build` should do it.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact