
BuckleScript: write JavaScript faster, safer and smaller - _qc3o
https://bloomberg.github.io/bucklescript/
======
virtualwhys
From Why BuckleScript[1]

 _Large JS output even for a simple program_

"In BuckleScript, a Hello world program generates 20 bytes JS code instead of
50K bytes. This is due to the fact that ... all BuckleScript’s runtime is
written in OCaml itself so that these runtime libraries are only needed when
user actually call it."

What happens when you go beyond Hello World though? Surely there's some
overhead vs. plain JS. For example, Hello World in Scala.js is tiny, but once
you touch, say, the Scala collections library, then file size increases
significantly. In the end, once you go beyond trivial applications, there's a
150KB baseline tax to pay for using the full power of Scala in the browser.

If BuckleScript provides an OCaml-like language with file sizes comparable to
plain JS that is both compelling and impressive.

[1]
[http://bloomberg.github.io/bucklescript/Manual.html#_problem...](http://bloomberg.github.io/bucklescript/Manual.html#_problems_of_javascript_how_bucklescript_solves_it)

~~~
hongbo_zhang
Unlike scalajs, bucklescript maps one OCaml module to one Js module, it is
like coffecscript/typescript compilation model, there is no tax on the code
size. You can write very clean code, here is an example of avl tree in ocaml
compiled into JS([http://bloomberg.github.io/bucklescript/js-
demo/#Balanced_tr...](http://bloomberg.github.io/bucklescript/js-
demo/#Balanced_tree))

~~~
sjrd
I like that BuckleScript has chosen the module-by-module design, if only to
explore more design space than what was previously done in Scala.js and
ClojureScript.

I do not think this is what makes the 150 KB tax of Scala.js, though. The dead
code elimination of Scala.js is really good, plus we combine it with Closure
as well. But it faces a very difficult challenge: the entanglement of the
Scala standard library. The collection library was designed when the JVM was
the only target, and decoupling within the collections library was definitely
not in the requirement set. This is why, once you touch the Scala collections
library in Scala.js, you receive 150 KB worth of (non-gzipped) code. There is
currently a large-scale effort to redesign the collections library for Scala
2.13 [1], with, among others, a desire to reduce inter-dependencies (while
keeping most of user-level compatibility). This should hopefully significantly
improve the situation of Scala.js regarding code size for smallish
applications, as you will only pay for the collections you actually use; not
the entire set of collections once you require one of them.

[1] [https://github.com/scala/collection-
strawman](https://github.com/scala/collection-strawman)

~~~
paulddraper
.NET was (past tense) also a target of Scala. Also didn't work out.

Java is the greatest and worst part of Scala.

Without Java, the language would be far, far less popular than Haskell. With
Java, it has a lot of forced compatibilities, e.g. null.

~~~
sjrd
> Also didn't work out.

Are you implying that Scala.js didn't work out? That would be denying the huge
success it has within the Scala community. It is notably supported by most
major Scala libraries. To back this by data, it appears 5th in a ranking of
Maven artifacts based on the number of artifacts depending on it [1]. Above it
are Scala itself, Specs2, Akka and scoverage.

Scala/.NET didn't work out because we never managed to reconcile the type
system of Scala with that of the CLR. For JavaScript, we _did_ manage that,
and pretty easily: it's much easier to erase all types than converting from an
advanced type system to another advanced type system.

[1] [https://scaladex.scala-
lang.org/search?q=&page=1&sort=depend...](https://scaladex.scala-
lang.org/search?q=&page=1&sort=dependentCount)

~~~
paulddraper
> Are you implying that Scala.js didn't work out?

Er, definitely not. Bad mis-statement on my part. Should have said "also had
challenges." And you're correct about type erasure.

Scala/Scala.js/SBT are my tools of choice for web apps.

I gave a talk "Scale your code with Scala.js" at Fluent last year
[https://conferences.oreilly.com/fluent/fl-
ca-2016/public/sch...](https://conferences.oreilly.com/fluent/fl-
ca-2016/public/schedule/detail/46780)

~~~
sjrd
Cool!

I had completely misunderstood your earlier comment ;)

------
yawaramin
I wrote up a non-technical post about my experience with BuckleScript
[http://yawar.blogspot.ca/2017/01/bucklescript-significant-
ne...](http://yawar.blogspot.ca/2017/01/bucklescript-significant-new-ocaml-
to.html)

------
bootload
_" BuckleScript is one of the very few compilers which compiles an existing
typed language to readable JavaScript."_

Elm (type inference) is sort of. While there is a lot of OS type projects
used, having bloomberg use it is a plus. Interesting that FB have build system
^Reason^ (build system) doing something similar (OCaml backend->JS) ~
[http://facebook.github.io/reason/](http://facebook.github.io/reason/)

~~~
yawaramin
Reason is an alternative, JavaScript-like, syntax for the OCaml language. Same
language, different syntax! It's crazy cool. BuckleScript is an OCaml -> ES5
compiler, so it actually compiles Reason to ES5 just fine.

Bloomberg and Facebook are two big users of BuckleScript. FB have a couple of
folks writing significant stuff in Reason, compiling with BuckleScript, and
deploying to user-facing web properties.

~~~
k__
What is the difference between reason and bucklescript?

~~~
phpnode
Reason is a language, bucklescript is an alternative backend for ocaml which
generates JavaScript. You write reason, you don't write bucklescript

~~~
k__
okay, then what's the difference between ocaml and reason? :)

~~~
phpnode
Reason is a js like syntax for ocaml, semantically they're identical. Similar
to coffeescript and JavaScript, except ocaml has really good support for this
kind of stuff

~~~
nerdponx
So what you're saying is I could write a JavaScript-esque program and compile
it to OCaml using Reason, and then compile it to true JavaScript using
Bucklescript?

~~~
phpnode
Yes exactly, although you can avoid the middle step and go straight from
reason to js because of the way bucklescript plugs into the ocaml compiler

~~~
e12e
Why would one prefer reason to ocaml? (Honest question)

~~~
phpnode
It is much more like JavaScript than ocaml and so you get a familiar language
but one which benefits from all the cool things that ocaml can do.

~~~
k__
Another n00b question: What are "all the cool things that ocaml can do"?

I only saw rather simple typing examples, which didn't seem much different
from what TypeScript can do.

On the other hand I read often that ocaml doesn't have runtime errors, which I
certainly get with TypeScript.

~~~
yawaramin
This is a good overview I think, although it doesn't get into specifics:
[https://realworldocaml.org/v1/en/html/prologue.html#why-
ocam...](https://realworldocaml.org/v1/en/html/prologue.html#why-ocaml)

Of course the rest of the book is a great read too if you're so inclined.

------
djsumdog
This looks pretty interesting. It makes me want to learn OCaml. :-P

I've been using Coffeescript in projects for about two years. I know people
have raised issues with it vs ES6, but I still really like Coffeescript. I
feels more natural with my Scala/Ruby background and it outputs into
Javascript in ways that (mostly) make sense and are predictable.

~~~
aikah
> This looks pretty interesting. It makes me want to learn OCaml. :-P

You can learn F# with dotnet core, which has a better ecosystem for web
development. OCaml is quite poor in that domain.

~~~
KurtMueller
Are you speaking from experience? If so, do you have any or know of any
resources I could look at? Also, what type of backend are you using with F#
and dotnet core?

~~~
ZenoArrow
If you want the BuckleScript equivalent for F#, that would be Fable.

[https://github.com/fable-
compiler/Fable/blob/master/README.m...](https://github.com/fable-
compiler/Fable/blob/master/README.md)

There's a newer branch called Fable Arch which I believe is focused on
promoting the Elm Architecture for structuring web apps:

[https://github.com/fable-compiler/fable-arch](https://github.com/fable-
compiler/fable-arch)

FunScript is another alternative:

[http://funscript.info/](http://funscript.info/)

~~~
elbear
Elm Architecture for F# is Elmish: [https://github.com/fable-compiler/fable-
elmish](https://github.com/fable-compiler/fable-elmish)

------
willtim
I found a page explaining the differences between bucklescript and js_of_ocaml
:
[https://github.com/bloomberg/bucklescript/wiki/Differences-f...](https://github.com/bloomberg/bucklescript/wiki/Differences-
from-js_of_ocaml)

------
jxm262
Built in npm support is huge for me. I use Scalajs full time and one of my
biggest issues is having to use SBT and webjars. I also end up using some
mashup of npm modules as well later on in the build which complicates it even
more. Plus the speed of the compiler becomes a massive issue, especially
during unit tests.

By turning it into a more readable Js, I wonder if the debugger would play
more nicely too. I've noticed in Scalajs the debugger randomly misses
breakpoints or moves to the wrong line sometimes. Anyway not a rant on
Scalajs, I do like it but there's definitely some bottlenecks for me.

~~~
sjrd
npm support is now available through [https://scalacenter.github.io/scalajs-
bundler/](https://scalacenter.github.io/scalajs-bundler/)

I agree with your analysis on breakpoints and step-by-step in Scala.js.
Usually it's a good idea to disable the Scala.js optimizer if you're doing
that, using:

    
    
        scalaJSOptimizerOptions ~= { _.withDisableOptimizer(true) }
    

But it's still not 100% perfect. I am toying with the idea that we should have
a mode of the optimizer that tries to optimize for debuggability with step-by-
step and breakpoints. This would try to arrange the generated source in closer
relation with the source code (like, 1 line = 1 line). All of this is trying
to work around limitations of source maps, and also of browsers' support for
source maps. It would be so much easier if source maps were a little bit more
powerful in what they can express (e.g., indicating what a "step" should be in
the code).

~~~
jxm262
This bundler looks awesome sjrd, will give it a try soon. My other option I
was going to suggest to other is to take a look at the sbt-web project. But
keeping things compatible and seamless with npm I think is important since
it's ubiquitous with front end devs

------
david-given
This looks really interesting. Does this implement the entire OCaml language?
I found a section of the docs marked 'semantic differences', but it seems...
suspiciously small...

This would allow me to write GWT-style client/server apps where both ends are
written in the same language with a set of common library code compiled for
both, right? What's the library support like? Don't suppose there's any ELM-
style DOM diffing support, is there?

~~~
hongbo_zhang
Yes, we implement the whole language, except a very few places that is hard to
due to the limitation of JS runtime.

Exactly, client side/ server side in a single language. People are working on
porting the Elm architecture to BuckleScript, they will be coming soon

------
grandalf
I think BuckleScript is going to blow up one of these days and become hugely
popular.

~~~
fspeech
I am waiting for the next Windows release that would allow one to use the bash
subsystem from native programs so I can use Reason/BuckleScript with Vscode.
OCaml/Windows integration isn't the greatest.

~~~
yawaramin
BuckleScript itself works fine on Windows. Installs in an npm project with
`npm install bs-platform` and good to go from there. Try it out.

~~~
fspeech
I can run BuckleScript under Windows/Bash. However as I understand it one
needs things like merlin working to get a decent IDE experience.

~~~
bobbbi
There's an OCaml VSCode extension powered by merlin.

[https://marketplace.visualstudio.com/items?itemName=hackwaly...](https://marketplace.visualstudio.com/items?itemName=hackwaly.ocaml)

------
progx
Learn a language to program another language. Find the issue. (I did not say
that BuckleScript is bad, i have only a problem with all kind of these tools)

~~~
yakshaving_jgt
How is there an issue at all? Most languages people use compile down to
something else. You don't need to know assembly to write Ruby.

~~~
innocentoldguy
I cannot speak for the parent, but the difference for me is this: Matz wrote
Ruby, for instance, because he felt that Perl lacked some
features/capabilities that he wanted. This is good, and from this perspective,
I have no complaints. Now, if Matz wrote Ruby to compile down to Perl, then it
becomes an issue. At that point, Ruby wouldn't really be a new language, but
just a Bandaid to hide the weaknesses and blemishes of Perl, for instance.
Fundamentally, I would still be writing Perl, and that, for me, is where it
becomes an issue, because I really haven't solved anything. I've just
disguised it.

My opinion on the matter is that Javascript sucks. We all know it sucks too,
which is why things like Elm, CoffeeScript, ClojureScript, TypeScript,
BuckleScript, Scala.js, etc. exist. We want to fix Javascript because we
understand that it sucks; therefore, we tend to embrace these various attempts
to make it less stupid. The solution to the problem, in my mind, isn't yet
another Javascript transpiler though, but rather native support for superior
languages.

I'd like to see an API built into browsers to make them language agnostic. I
think that would go a long way towards making web programming less lame. It
may also give us a chance to clean up the DOM.

~~~
eru
Our bearded forefathers wrote C because assembly had some issues. They still
compile to assembly.

Haskell compiled to C for the longest time (and quite a few other compilers
use that trick). That didn't make Haskell a bandaid around C, did it?

------
hazza1
BuckleScript looks great but I've never found any project using it - maybe
Reason will be the tooling to make it mainstream?

~~~
bobbbi
Projects in Bucklescript do exist, here's one that shows how easy it is to
integrate with JS -
[https://github.com/paulhoughton/montecarlo/](https://github.com/paulhoughton/montecarlo/)

Or lots of examples here - [https://github.com/OvermindDL1/bucklescript-
testing](https://github.com/OvermindDL1/bucklescript-testing)

------
coot_
[http://www.purescript.org](http://www.purescript.org) \- PureScript a small
Haskell like programming language compiled to JavaScript (and C++)

------
buzzybee
Ooh, I wonder this could lead to the Haxe compiler running in JS.

------
vorotato
For those who need babel source maps there's Fable, it uses F# and Babel to
generate javascript, OCaml and F# are remarkably similar.

------
dochtman
Well, Rust can compile to asm.js or wasm, too.

Might still be rough around the edges, but it will improve soon enough.

~~~
chrismorgan
Rust compilation is slow, and the compilation target opaque.

BuckleScript is fast, and compiles to readable JavaScript.

Please don’t just go spouting that Rust is the answer to everything; it’s not.
It’s also not always relevant in a discussion.

(I say this as someone who is lauding Rust at every turn and who has been
using it seriously for years and who is looking forward to a solid wasm target
and ecosystem.)

~~~
dochtman
Sorry, my post maybe came off as more negative than I intended, but the
downvotes seem a bit harsh.

To me, in the WebASM world, transpiling to JavaScript is starting to seem a
little old-fashioned. Readable JavaScript is not as important as long as we
have source maps, which WebASM was designed to take into account. Presumably
Rust (or Ocaml) compiled to WebASM will also have substantially improved
performance compared to transpiled JavaScript, which IMO is worth the longer
compile cycles.

I think Rust is relevant because Ocaml and Rust share a lot of heritage
(indeed, I think Ocaml was one of the most influential languages in the Rust
design), so I think that makes it relevant in this discussion.

~~~
sjrd
The problem with wasm right now is that it gives you very little in terms of
interoperability with JavaScript. You simply cannot manipulate JS objects
(including DOM objects) from wasm.

Compiling a language like BuckleScript to wasm is therefore not possible at
the moment, simply because the interop features of BuckleScript cannot be
encoded in wasm.

Besides, there are other difficulties: wasm doesn't have any kind of managed
heap at the moment, which means that compiling a managed language to wasm
requires to embed an entire GC in your production code! It's much better to
take advantage of all the VM features offered to JS, like a GC, when compiling
a managed language to the Web platform.

------
1_listerine_pls
Advantages?

------
sheerun
Could somebody compile Flow to JavaScript?

~~~
phpnode
The flow parser is already available in js, it doesn't seem impossible to
bring the rest of it to the browser but I'm not aware of anyone working on it

