I was initially going to title this post "Why I Stopped Using Babel", but that would make it sound like there was some problem with Babel. I have had no issues whatsoever with Babel. The transpilation time was almost negligible (~1s for my code, combined with ~4s of browserify run time), it didn't perceivably impact performance (even when I was profiling inner loops written in ES6), and it never caused any bugs. On the whole, Babel is excellent software and if you want to use ES6 now, I highly recommend it. But there's the catch: you have to want to use ES6 now. And slowly, over the course of a couple of months, my desire to do so was sapped away (through no fault of Babel, and almost no fault of ES6).
The problems I had were mostly with integration. Two very important pieces of my workflow are Tern and Istanbul. Tern provides auto completion and type-guessing that is integrated into Emacs. Istanbul provides code coverage reports. Neither of them support ES6. With Istanbul, it was possible to work around it by running babel on my code and then covering the ES5 output. However, the coverage reports were then off because of the extra code that babel has to insert in order to properly simulate ES6 in ES5. Tern, on the other hand, did not have an option. If I chose to use only fat arrows, it would be workable because I discovered I could copy and past the code for normal functions to those and it worked more or less as expected. However, everything else was a wash.
So why not ditch Tern and put up with the Istanbul workaround until it gets ES6
support? As I used ES6 over the summer, I came to realize that in 99% of my
usage, it wasn't much of an improvement.
let is certainly useful (and the way
it always should have been), arrow functions are awesome, and
for(a of as)
finally gives a sane looping construct in the language. Other than that, the
only feature that's really exciting is destructuring, and while it is a bit of
a pain to destructure complex data by hand, it isn't something that I have to
do often. Classes were not of any use to me for this project either. None of my
data made sense to represent as a class. Although in theory my React components
would make sense as classes, I'd rather use the old, well-documented, clear
method that has support for mixins (which would have to be implemented through
inheritance were I to use ES6 classes).
The decision ultimately came down to three things:
- I wasn't getting much (just
for of, fat arrows, and destructuring) from ES6
- ES6 vs ES5 is just one more thing my team would have to pick up after I'm gone.
- ES6→ES5 transpilation is a thing that somebody would have to support after I'm gone, and there is no telling how long it will be before it is no longer needed.
In the interest of making the life of my successor a tiny bit easier to manage, I ultimately chose to ditch ES6 for ye olde ES5. I had to throw out a bunch of the ES6 prototype code anyway, so there was very little additional cost in stripping it out of the code. Ultimately, I believe that this was the right decision for this project. Although losing those few additional features I was using was a bit painful, gaining the proper support of my tools and losing the incidental complexity of transpilation was worth it I think.
I'll probably still use ES6 with Babel for small side projects. (Anything large won't be in JS, even if it compiles to it!) If you want to try out ES6, Babel is a very safe and easy way to do it. I look forward to the day that ES6 has widespread support and Babel is…well, still needed for ES7 transpilation, but that's for another day.
I don't like the
import syntax and don't even get me started on classes and
inheritance in ES6.