Issue 1:
Choose one: is this a bug report or feature request? feature request

Input Code

class MyComponent extends React.Component {
// ...
}

Babel Configuration (.babelrc, package.json, cli command)

{
"plugins": [ [ "transform-es2015-classes", { inline: true, loose: true } ] ]
}

Expected Behavior

Ideally, instead of inserting an inherits function into the scope, the code from the inherits function would be inserted into the compiled class function

var MyComponent = function(_reactComponent) {
MyComponent.prototype = Object.create(_reactComponent.prototype);
MyComponent.prototype.constructor = MyComponent;
MyComponent.__proto__ = _reactComponent;

function MyComponent { ... };

return MyComponent;
}(React.Component);

My basic testing (using the Rollup REPL) seems to imply that that would successfully be tree shaken. However, that is only true for the loose inherits, the full inherits still would not be tree shaken.

Current Behavior

An inherits function is inserted into the scope and called within the compiled class.

var inherits = function(subClass, superClass) { ... };

var MyComponent = function(_reactComponent) {
inherits(MyComponent, _reactComponent);

function MyComponent { ... };

return MyComponent;
}(React.Component);

Possible Solution

We could pass an inline: true option to the transform-es2015-classes plugin and it would inline the inherits code instead of inserting the helper function into the scope and calling that.

I'm not familiar enough with Babel to say whether adding an option to the plugin is a viable solution. Instead, this might have to be done with a separate plugin.

Context

I was experimenting with moving a project (React Router) to a single file build. Currently, our main and module builds are just the compiled files from our source. This allows users to cherry pick imports so that their bundles only include the files that they want. If we were to switch to a single file, users obviously could no longer cherry pick, so we would want to make our exports tree shake-able to have feature parity.

This isn't a React specific problem, but since React now encourages using class <C> extends React.Component, any React component package that does so will have this issue.

Issue 2:
Feature request

Minifiers like Uglify try to remove dead code from minified builds.

To completely remove a declaration, they have to prove that it is side-effect free.

Unfortunately in JS this is often not possible as pretty much anything can have arbitrary effects.

An important issue is that ES5 emit for class can't easily be determined to be side-effect free.

As a result, tree-shaking is ineffective. In simple words: no class is removed from the output, even if it is never used.

A very simple solution could be to have a hint for the minifier, inside a special comment.

If the emit added a /*#__PURE__*/ comment at the beginning of ES5 classes it could easily be detected and removed by Uglify.

var V6Engine = /*#__PURE__*/(function () {
function V6Engine() {
}
V6Engine.prototype.toString = function () {
return 'V6';
};
return V6Engine;
}());

This is an important enhancement that can dramatically reduce the size of unused code, especially in large libraries.

Uglify|JS already supports this annotation: mishoo/UglifyJS#1448

Original UglifyJS discussion: mishoo/UglifyJS#1261

For reference, implementation details are here: mishoo/UglifyJS@1e51586

The issue was originally raised at Webpack: webpack/webpack#2867