Before getting started, we needed to convince ourselves of the need for ES6. Yes, ES6 is cool, our industry peers are using it, and engineers can learn new stuff (good for their careers), but how effective is it as a technology, for our product as well as the overall organization? Also, engineers are comfortable with ES5 and things are going well. So why ES6?
- ES6 represents the biggest change to the language since its inception. Although there have been five earlier editions to the language, all of them were incremental revisions, none at this scale. Also, going forward there will be ongoing new additions to the language, some of which built on top of ES6 concepts. So the sooner we start adopting ES6, the more likely we can leverage the new powerful features.
Object.assign) required many lines of code or a custom abstraction or an external library. ES6 has now made it easy and straightforward, thus increasing productivity.
Now that we had some answers to the question “Why pursue ES6?” the next step was to deep dive into ES6 features and figure out which of them are most useful to our world. Which should we start with?
At a high level, ES6 features can be grouped under two buckets: syntactic sugars and new features. Syntactic sugars are those which are technically possible now but require many lines of code or a custom abstraction or a library to achieve (such as classes and default parameters). New features, as the name suggests, are something newly introduced in ES6. The inspiration for the new feature could be from either a popular library or another language, or it could be a completely new feature (such as the
Promise object, generators, and the
Proxy object). With this background, we did some deep dives, followed by discussions with a few folks, and finally shortlisted the below set of ES6 features to get started on.
- Block Scoping
- Extended Parameter Handling: Default Parameters, Rest Parameters, and the Spread Operator
- Arrow Functions
- Template Literals
Below are some of the reasons why only the above features were shortlisted:
- Common use case: The above list covers most of our day-to-day coding use cases. We went through a major portion of our critical code and observed that these were the missing patterns and features for which a library was used or sometimes handwritten. With the code in front of us, we were looking at the features that can be immediately applied, most of which made it to the final list. ES6 offers some powerful features like Proxies, Reflection, and Symbols. But as the saying goes, “With great power comes great responsibility”. These power features need to be used wisely to get the most benefit out of them. Also, use of these features in application code is very rare, and they are more suited for meta programming or building libraries.
- Performance: The other important criterion for a feature to be shortlisted was performance, both native and transpiled (ES6 to ES5) performance. The Six Speed performance comparison was a good place to start with. In addition, we did a little bit of our own benchmarking. With all results in hand, the above features were selected. Most of the shortlisted features had identical performance when compared to the ES5 equivalent or just native ES6. Features like
Set are useful, but our tests indicated that they still need more maturity to be ready for prime time. Also, we did not feel the desperate need to use them right away.
- Productivity and debugging: Before shortlisting the features, we tried using a lot of them in internal projects just to get a feel of the whole process. The features that we shortlisted were the ones that boosted our productivity tremendously after a short learning curve. Some of these features were so appealing that we immediately started missing them when writing in ES5. Another aspect to it is debugging. The shortlisted features were easy to debug even in the transpiled version, as most of them are simple wrappers that don’t affect the core logic.
This exercise also helped us decide what ES6 features to avoid now. One of these is the new ES6 generators. Although they bring in great functionality, they are still not ready for prime time. In addition to performance problems, we feel that the upcoming
Await feature offers a better alternative to generators, providing a much cleaner syntax and readability. So for now we are a strict NO to generators.
Now that we have a clear picture on ES6, the next thing was to put it in motion. The first obvious thing was to decide on a transpiler, and the unanimous choice was Babel. In the beginning, we will transpile all ES6 unconditionally to ES5. We know it is not ideal, as we are sending ES5 code even to browsers that support ES6. This is just a short-term solution until we figure out a smarter (browser-based or feature-based) transpiling mechanism, which is already in the works. The below steps highlight the things we have put in place to get started with ES6.
- Our module bundler and asset pipeline tool, Lasso, was updated to support ES6 transpilation through Babel. For now, we will only transpile files with the
- We created an ESLint config similar to
eslint-config-airbnb, which will enforce ES6 coding guidelines and code styles for the shortlisted features. It is an integrated part of developer IDEs and CI jobs, and violations will be reported for each build. Using non-recommended features (for example, generators) will also be reported as errors. This is a critical step to guide engineers in the right direction when starting with ES6, as they get trained with the best practices from day one.
- Our recommendation to developers newly starting with ES6 is to start writing unit tests with ES6. Unit testing seems to be a good place to try out and get comfortable with the various features and syntax of ES6. It can be used as a playground to ramp up in. Since unit tests are not shipped to production, developers can be more proactive and confident to try things that otherwise require caution. Once comfortable, you can get going with new application files created in ES6.
- We did a couple of internal Brown Bags to spread ES6 awareness and ramp up developers on new features. This will also be added as a part of our new hire training. It will be an ongoing activity, with the training content updated with our latest recommendations.
- As mentioned earlier, smart transpiling is something we want to set up in our build and release process. We do not have an exact answer yet, but it is at the top of our queue.
- We will onboard more ES6 features (especially the new module syntax) as and when our criteria are met.
This summarizes the path we took to bring ES6 into eBay. Our main goal was to organically adopt ES6, instead of it being a forcing function. Teams have slowly started using the new features and the feedback is very positive.
Lastly, two online resources “Understanding ECMAScript 6” and “Exploring ES6” have been incredibly helpful for our research and analysis. Huge thanks to Nicholas Zakas and Axel Rauschmayer for making it available.