Tree shaking is presented as a webpack 2 feature and is really a property of ES modules: the imports have to be statically analysable, which means Babel must not have turned them into CommonJS first.
// .babelrc — the setting that makes or breaks it
{
"presets": [["env", { "modules": false }]]
}
With modules left at its default, Babel rewrites import into require before webpack sees it, and every module is included whole. The other half is that a dependency published only as CommonJS cannot be shaken either, however the application is configured — which is why the bundle often barely shrinks and the configuration looks correct. Side effects declared in package.json are what tell the bundler a module is safe to drop.