Recently I've been advocating a move to distributing uncompiled ES6 packages, and shipping ES6 to browsers that support it and compiling using a single simple preset (ES2015 except modules).<p>There are several big reasons:<p>1) ES5 "classes" cannot extend ES6 classes (it's not possible to emulate a super() call in ES5), so:<p>1a) All the extendable built-ins are basically ES6 classes. If you want to extend Array, Map, Set, HTMLElement, Error, etc. you really should use ES6, and deal with emulating extending those classes in the compilation step.<p>1b) Really useful patterns, like ES6 mixins ( <a href="http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/" rel="nofollow">http://justinfagnani.com/2015/12/21/real-mixins-with-javascr...</a> ) don't work when ES5 and ES6 versions are mixed in a prototype chain. That is, an ES6 mixin, compiled to ES5, can't be applied to an ES6 superclass. So if you distribute ES5 you're forcing everything above you on the prototype chain to be ES5.<p>2) It's much easier to debug uncompiled code, and all major browsers (as of Firefox 51) and node support ES6 well. Shipping uncompiled ES6 is a dream to work with comparatively.<p>3) ES6 is a much better compilation target for things like async/await because of generators.<p>4) ES6 is easier to statically analyze, so tools like TernJS and TypeScript (which can do analysis of regular JS too) can give better completions, etc.<p>5) It makes the pipeline from source -> packaging -> depending -> building for deployment much simpler.<p>Packages shouldn't assume too much about their eventual environment. That used to mean not assuming that the environment had ES6 or things like Promises. But times change and now that all the current environments support ES6, packages shouldn't assume that environments _don't_ support it.<p>So packages shouldn't directly depend on polyfills that most current environments have (Promise, Object.assign, new Array methods, etc.). Instead they should target standard ES6 and let the app developer who knows what they're targeting choose the necessary polyfills and down compilation. There's really too much bloat from packages forcing the inclusion of multiple Promise polyfills, or versions of core-js.<p>Also, it used to be that compiling dependencies was a major pain. You'd likely have to write custom build rules that compile and stage each dependency - because each dependency might have different language features and polyfill they might use. Now the packagers like WebPack and Rollup are so good at finding all dependencies statically, and we have a new stable plateau of language features in ES6, that the packager can compile everything it needs.<p>Of course if you use features beyond ES6, then those should be compiled to ES6. This implies a rule of thumb to move forward: Once all major browsers and node LTS have a feature, start assuming that feature and don't compile it out. For example, once Firefox and node LTS get the exponentiation operator, start distributing ES2016 (see <a href="http://kangax.github.io/compat-table/es2016plus/" rel="nofollow">http://kangax.github.io/compat-table/es2016plus/</a> ).