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.
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 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:
- It's Usable
- It Has Full Type Safety
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.
 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?
- 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
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.
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.