As most of us know, there are several problems/quirks/flaws with Javascript and this is known as the Javascript problem. However, like it or not, as long as we use browsers, we need Javascript.
So, what is the solution?
Pick your favorite language (hope it is not Javascript!) and hope that there is a transpiler that converts it to Javascript.
Essentially Javascript becomes a derived language A while back I had argued in a blog article about languages to learn (and in response to reader comments) that Javascript is a derived/assembly language. You let the transpiler author worry about generating the correct Javascript.
One of the advantages is that you can use the same language for both server and client components and transpile the client component to Javascript. A lot of code (including libraries) can be shared and lot of the debugging of code (not involving the UI) can be done without using the browser.
Many years ago I didn’t know Javascript (and I still don’t) and I wanted to write webapps. Using Java and Google Web toolkit java-to-javascript transpiler, I wrote couple of apps which have no server side functionality and can run offline in the browser once the Javascript is loaded. Using the Google App Engine, now called the "Google Cloud Platform", I could host these apps as math quiz and mortgage calculator. For apps that need server-side functionality, you can use the Google App Engine as I did when I wrote my music web-app called Ragamalika.
I have blogged about GWT and App Engine: here and here. GWT understands the quirks of different browsers and generates code optimized for them. Depending on the browser used, the corresponding optimized Javascript is rendered.
Java was an early pioneer for transpilers to Javascript but now you can be certain that there is a Javascript transpiler for your favorite language. And if your favorite language has static types, you get all its benefits including finding errors at compile-time than run-time, IDE support including re-factoring etc. And if are even more lucky (or rather made your own luck), your language of choice will have type-inference, which is like having the cake and eating it too!
Besides Java, some of the other languages which have such transpilers are Scala (Scalajs), Clojure (Clojurescript), C#, Haskell (Haste, Ghcjs, Fay) to name just a few.
The generated Javascript is generally not meant for human consumption, which is fine as we don’t expect assembly language to be readable. You can significantly reduce the size of the generated Javascript code by running the powerful Javascript optimizer called Closure from Google and compressing the result using an algorithm like zopfli.
With Haskell, you have at least 3 choices:
-
Ghcjs
can use all of Haskell. Can use all libraries (except those that have underlying native code dependencies)
-
Haste
A subset of Haskell. Size of generated Javscript is smaller than Ghcjs though this is a moving target.
-
Fay
A subset of Haskell.
A standard metric for showing off the capability of these transpilers is to write a "TODO" web app in as few lines as possible.
Todo MVC (In Java, Scala, Clojure and Haskell)
- Java (gwt)
- Scala/scalajs (react)
- Clojure
- Haskell
React from Facebook is a JavaScript library for building user interfaces using a declarative style. It uses the virtual-dom approach where one writes code as if the entire page is rendered on each change and React will only render the subcomponents that change.
So far, we have mentioned existing languages that can also have a Javascript transpiler. But there are also new languages, designed with the sole purpose of generating Javascript. I will mention 3 here: Purescript, Elm and Typescript.
If you want to generate readable, compact Javascript with no runtime, I would recommend Purescript, where you write in a beautiful, powerful, high-level language with the syntax of Haskell. You can check out a side-by-side view with purescript and the generated javascript. But if you don’t already know Haskell or don’t have a functional programming background, learning Purescript, while quite rewarding even if you don’t end up using it, requires a steep learning curve. Purescript is quite new and is heavily inspired by Haskell (which is over 20 years old) and it does some things better than Haskell (lessons learned). It uses strict evaluation to better match Javascript’s evaluation strategy. It tracks side effects with more granularity than Haskell (e.g. use of filesystem, console, process etc). Purescript compiler is written in Haskell.
Another well designed and powerful language, with haskell-like syntax, that solves the javascript-problem is Elm. Its error messages are designed for human consumption and are uncanny in their ability to pinpoint the error and provide suggested solution. It guarantees "No runtime exceptions", something it can do with the strong type system and compiler implementation. Checkout the famous time-traveling debugger where you can go back in time. If imitation is the best form of flattery then Elm’s creator, Evan Czaplicki has lot of imitators and lot of ideas have found their way into other languages. However, its type system is not very powerful when compared to Purescript — for e.g. it doesn’t have type classes. Elm compiles to HTML, CSS, and JavaScript. The Elm compiler is also written in Haskell.
Typescript (from Microsoft) is a superset of Javascript: it adds optional types, classes, and modules to JavaScript. AngularJS, a popular JavaScript framework for building Single Page Applications uses Typescript.
Another option, for developers who know Java syntax, is Jsweet. It uses Java syntax (but it is not Java) and transpiles to Typescript, which can be converted to Javascript.
Todo MVC (Languages created to generate Javascript)
This is by no means an exhaustive list.
My favorite languages are Haskell and F#. In addition to Java (GWT), I have used Haskell (ghcjs) to write webapps. More on that in a future article.