Blueprint by Tiny
Return to Tiny.cloud
Return to Tiny.cloudTry TinyMCE for Free
Search by
Time-lapse photo of highway road at dusk, a stream of white light on the left and red on the right.

A Tiny road to Reason

Andrew Herron

September 21st, 2020

Written by

Andrew Herron
Andrew Herron

Category

Engineering

Tiny is working on a real-time collaboration (RTC) solution for TinyMCE. This is the third in a series of blog posts documenting our journey and decisions along the way. The first covered our choice of collaboration algorithm, the second our choice of editor model.

Team Tiny has been quietly exploring ReasonML for many years. From humble beginnings in 2014 with OCaml experimentation, our first production deployment of ReasonML happened without fanfare in 2017. Our RTC team, launched in mid 2019, is building TinyMCE's model-based editing future in ReasonML. This post documents our journey so far and hopefully encourages others to join us in this fun new ecosystem.

Aren't we using TypeScript?

Our journey at the end of 2017 to find a suitable "alternative JS" language may have appeared to land on TypeScript, but if you read closely we quietly announced the use of both TypeScript and ReasonML for our future. We chose TypeScript for TinyMCE core and ReasonML for our premium PowerPaste plugin. TypeScript has been very good to us, but in the intervening years we have been hitting the limitations of the TypeScript language design.

While the language has made huge strides in recent years, some data structure patterns remain difficult or impossible to express in TypeScript. The compiler is slow on large projects. Code safety is also a major concern for us; as one of our cloud engineers puts it, TypeScript is "type safety by pinkie promise".  We could alleviate most of this concern with strict mode, but turning that on would require significant investment in code maintenance rather than simple refactoring. Given the large effort that would be required either way, we chose to invest more heavily in ReasonML as the complete solution to our needs.

We are big fans of strict static typing. Our previous major editor was written in Java, so the switch to JavaScript has been a big step down in code safety and ease of long-term maintenance. Our backend services did not make the switch; they were originally developed in Scala and now many are written in Haskell.

TinyMCE will continue to be built in TypeScript for a long time. We will never throw away a stable product just because we've found a better language, but we are absolutely willing to migrate to best-in-class technologies to ensure TinyMCE can remain a "modern" editor long into the future.  ReasonML is very good at integrating into TypeScript codebases so we can migrate to it at an appropriate pace.

What is ReasonML?

ReasonML, as we use it, is a compile-to-JavaScript language not unlike TypeScript. It's also very unlike TypeScript; it has guaranteed type safety, superb type inference, more advanced type system features than TypeScript, and the ability to compile to extremely fast native binaries.

ReasonML is a language without a compiler. The name is used as an umbrella project with community, libraries, and leveraging NPM for package management. But at the core it is a veil over the OCaml syntax to make it palatable to developers unfamiliar or uncomfortable with the ML code style (not "machine learning" - here ML refers to "meta language" from 1973). All of the power on offer is thanks to more than two decades of hard work from the OCaml community. ReasonML's JavaScript capabilities are provided by BuckleScript[1], leveraging the OCaml compiler to produce low-level JavaScript that can safely eschew many of the runtime checks normally found in hand-written code.

ReasonML was created in 2016 by Jordan Walke, the creator of React, and it is gathering steam amongst React developers while also starting to appeal to JS/TS developers outside of the React ecosystem. In Jordan's own words, Reason brings what people like about React to the programming language level.

More recently, Jordan has posted some great summaries of the project:

ReasonML is an umbrella project/sponsor for many subprojects, all of which have the goal of bringing fully type safe, fast compiling, fast executing code to the widest number of developers and today that means JavaScript developers.

- It's Just JavaScript With Types
- It's Usable
- It Has Full Type Safety

Pick two.

[...] TypeScript is aware of the tradeoffs, [choosing] the first two, and the result is a great developer/IDE experience for JavaScript programs (props!). Reason chooses the last two and creates a great experience for writing very safe web apps.

If you would like to learn more, the new community documentation site is a great place to start. There is also a ReasonML book, it is perhaps a little out of date by now but the fundamentals will all be the same. OCaml is a very stable foundation.

Addendum

[1] This post was delayed due to COVID-19, and in the meantime BuckleScript has been renamed to ReScript, introducing a new dedicated syntax. The goal is to resolve confusion for new users by offering a single complete toolchain instead of multiple distinct projects. We are keeping an eye on these developments, and working with the team, but until the new community direction settles and stabilises we will continue with our current path.

Why did we choose ReasonML?

ReasonML is our gateway to OCaml. OCaml is, in our opinion, the best general-purpose way to generate JavaScript from an ML-style language. An ML style offers everything we are looking for in a language (list from Wikipedia):

  • first-class functions
  • automatic memory management through garbage collection
  • parametric polymorphism
  • static typing
  • type inference
  • algebraic data types
  • pattern matching

OCaml is also immutable by default, which is a huge plus. The only missing feature we would prefer to have is side-effect tracking, but OCaml will (eventually, hopefully) offer this as well. This is part of why we like the OCaml type system so much; it supports beautiful functional and immutable code, but if you need to get dirty in a hot code path, you can, without sacrificing other features of the language.

ReasonML compares well to other compile-to-JS languages

We certainly evaluated many options along the way. TypeScript was a great start, but it is unsound by design and restricted by the adherence to being "JavaScript with types". PureScript and Elm have their place, as does Haskell+GHCJS, but the target audience prefers language features over easy integration into existing JavaScript applications. We have found the OCaml semantics and the code structure it encourages to be a perfect fit for JavaScript, resulting in generally clean and easy-to-integrate code. Since 2015, every developer who has joined the TinyMCE editor team has learned functional programming by completing a coursera course in SML. This has been very successful and helped to justify further investment in ML-style languages.

ReasonML offers best-in-class performance

TypeScript projects are often busy waiting for tsc and/or webpack to build. ReasonML modules are compiled independently, with an extreme focus on speed, allowing builds to scale with multi-core CPUs for insanely fast build times. It's multiple orders of magnitude faster than TypeScript, incremental builds are generally complete in half a second or less (often under 100ms). This instant feedback, combined with strict static typing that picks up more errors than TypeScript, gives us greater confidence when developing that we're not making a mistake.

We don't see improvements only in build performance. Our development flow has improved as well. When developing in ReasonML many problems become data modelling and logic problems - the fun part of computer science. Compared to TypeScript we spend a lot less time on mundane tasks like data structures and fighting with the type system. We feel a lot more productive.

Why did we choose this time to invest in ReasonML?

The whole editor team had agreed that ReasonML was the future direction we wanted to take, but our real-time collaboration effort was really the first opportunity to validate that decision.

Near the end of our research phase in August 2019, the team spent a week building our first draft of TinyMCE collaboration experiments in TypeScript. We then launched a new project to see how long that would take in ReasonML, hoping it would prove to be the path forward. We recreated the entire draft in a day. This clearly demonstrated that we were so much more productive in ReasonML it would outweigh any costs associated with forging this new path; ReasonML has very few community-supported libraries, we've had to build a lot of things ourselves. We continue to believe it was the right choice.

Fun facts about Reason

  • It can export TypeScript types with genType. This means code can be gradually mitigated to ReasonML without impacting the rest of the project.
  • It powers all of Messenger.com. The team released a case study in 2017 describing a reduction from ~10 bugs a week to 10 in a year.

For more business-oriented facts to convince management, we recommend Yawar Amin's OCaml for Business article.

How did we choose ReasonML?

I personally kicked off our journey with my "Why OCaml, why now" post and began championing this new direction within the company. My message resonated with Hacker News in 2014 (and achieved even greater traction when it was reposted in 2015), giving me confidence to pursue it. The 2016 announcement of ReasonML and BuckleScript, offering friendly syntax and easier JS interop, helped convince management to approve our first experimental project in early 2017.

The experiment was successful, and Tiny quietly released our first ReasonML production code in October 2017. The changelog for a new major version of our premium PowerPaste plugin reads simply:

Added a brand new word import process that supports more types of images, is more reliable and easier to maintain.

The truth is that processing content from Microsoft Word is the entire point of the plugin, and that logic had been rewritten from scratch. We did not make a big splash about this - we didn't advertise it at all outside of some quiet celebration in the ReasonML Discord, because it was still unproven technology and the plugin is closed source.

This version has been one of our most successful launches from both product and development perspectives. The improved processing logic made possible by the OCaml type system has been very well received by customers, while ReasonML has absolutely delivered on the promises of stability, ease of maintenance, and ease of introducing the code to new developers.

Moving forward

To reiterate, TinyMCE will continue to be based on and primarily built with TypeScript for the foreseeable future. Nobody wants to drop decades of work on the floor and rewrite the editor. ReasonML is very good at integrating into TypeScript codebases and we don't want to rush this process.

The team is very excited to expand our use of ReasonML in premium plugins, beginning with real-time collaboration, and eventually look to introduce it to the open source core as well with features such as model-based editing.

The future is bright, and it's statically typed.

EngineeringCollaboration
Andrew Herron
byAndrew Herron

Andy is a Principal Engineer at Tiny.

Related Articles

  • The number 20.
    Engineering

    Lessons learned over 20 years as a web developer

    by Marty Friedel in Engineering
Subscribe for the latest insights served straight to your inbox. Delivered weekly.

Deploy TinyMCE in just 6 lines of code

Built to scale. Developed in open source. Designed to innovate.

Begin with your FREE API Key
Tiny Editor