You don’t need Babel

think twice before adding any complexities to your project

Zhenhua Cao
3 min readJul 18, 2018

It was a year ago when I started an internal tool project called “integration CLI”, which was a command line tool for setting up a complete environment for the product we’re working on and later run tests against this environment.

The tool was built in nodejs. Coming from a background of a large single page application app, I was so used to the Babel + Webpack toolchain, that as a no-brainer, I kicked off the project with a classic .babelrc configuration, and started coding with the freedom I was used to in the SPA world.

In the package.json of the project, I had a script called “build” and another “prepublish” script which invokes the “build” to ensure that the source code is compiled from “src” folder to “lib” before publish, and should I remember to ignore “src” from being included into the published package to reduce the download size.

Since it was a CLI tool, in order to test it conveniently locally, I had “npm link”ed the project, so whenever I invoke the CLI command, it should read my repo instead of somewhere in global node_modules folder. Given this, any time I made some changes (in the src folder), I should better remember to “npm run build” so that the CLI would reflect my changes (lib).

I didn’t consider it a problem until I started a new project. It was also a nodejs project but was actually more complicated since it did include a web server, and had a few source files that are running in the browser environment. I don’t remember why, but on the first day of the project, I somehow set up a goal for minimization — use the least possible external packages and be as raw as possible. I didn’t use babel for the new project given this constraint.

Interestingly, the new project went very well. I found that literally, the only style change I had to make is to replace “import/export” with “require/module.exports”, no matter it was the code running in nodejs, or the code running in a browser, both worked equally well. All the most useful features are already well supported, including arrow functions, array destruction, object destruction, Promise, even await/async, and it was an experience I feel mostly identical to the one with Babel. Oh, except due to the limitation I set, for React components, I used “React.createElement” instead of JSX syntax — and it was okay given there’re just a few components.

As a contrast, the new project had no such “build” command, no “prepublish” necessary, and the only source folder was “lib”. This was the “Wow” moment for me. Before this moment, I didn’t realize we can live so well without babel already.

Then I started migrating the first “integration CLI” project away from Babel, at the time the project was already not so small, with 20+ files and probably around a few thousand lines of code. It took less time than I originally expected to finish this migration. It was as simple as replacing import to “require” and export to “module.exports”, and that’s all. After the migration, I removed “build” and “prepublish”, uninstalled babel related dependencies, and happily ever never have to remember to compile whenever I made some changes.

Given this inspiration, I did some further minimization for the existing project, including removing the dependency to lodash.some, lodash.map and lodash.filter, and use Array native methods instead. A similar successful story.

This made me think twice.

I still remember once I had a 100 line file for AWS Lambda and after compilation, it became a few MegaBytes that is really hard to read. I recalled those days fighting with Webpack source map options and some of the out of memory issues when compiling in a container environment.

So I wrote this, hope there’re some inspirations for you.

--

--