Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The cost of small modules #2873

Closed
jdalton opened this issue Aug 15, 2016 · 37 comments
Closed

The cost of small modules #2873

jdalton opened this issue Aug 15, 2016 · 37 comments

Comments

@jdalton
Copy link
Contributor

jdalton commented Aug 15, 2016

I've seen rumblings of the-cost-of-small-modules as related to webpack growing in recent months.
The TL;DR is high file size and runtime cost of webpack's module scaffolding.

chart of file size per number of modules
runtime cost per number of modules

I'm wondering if there's a plan for a plugin or feature to address these issues.

@lukeapage
Copy link
Contributor

Related: #2425 (comment)

@sokra
Copy link
Member

sokra commented Aug 16, 2016

Yeah, this is definitely something we want to address. I've ran some experiments and it seem to be possible. The most difficult part of the process is the var renaming and inlining. I hope we can work together with @Rich-Harris and integrate the rollup core to do the heavy lifting.

This will be one important thing we'll do after the webpack 2 release. We concentrate on documentation and bug fixing now.

@acidicX
Copy link

acidicX commented Aug 16, 2016

@nolanlawson nice article! I'd also be interested in a real-world example with webpack v2 and tree shaking on large projects. It should improve exec time when dead code is eliminated from the bundle? Maybe that already comes close to rollup/cc?

(I'm guessing you ran the bench on webpack v1)

// edit
whoopsie, corrected the @ mention

@timmywil
Copy link

@acidicX Yes, it was just v1, but Nolan Lawson wrote the article.

@jdalton
Copy link
Contributor Author

jdalton commented Aug 16, 2016

@acidicX I didn't write the post, @nolanlawson did 😸

Tree shaking may reduce the module count some, but the issue still exists. I can still
see the overhead even when creating bundles with babel-plugin-lodash (tree-shaking) and
lodash-webpack-plugin (short circuit modules).

@nolanlawson
Copy link

@acidicX Yep, in the benchmark I didn't focus on tree-shaking because I wanted to isolate the cost of modules in non-dead code. Up to now I found everyone had been focusing on the tree-shaking aspects of Rollup, whereas to me the scope-hoisting was the really exciting part. 😃

@schmod
Copy link

schmod commented Aug 18, 2016

I previously noted elsewhere that Webpack 2 can produce significantly less efficient bundles compared to Webpack 1 in some cases.

Apart from switching to scope-hoisting (which would likely require a very large development effort), there are a few areas where we could likely make small improvements in the short-term.

I've specifically noticed that transpiled ES6 modules can produce an awful lot of boilerplate code.


Take a fairly simple module:

import angular from 'angular';
import moment from 'moment';

export default angular.module('foo', [])
.run(function(){
    window.foo = moment();
});

Even without considering the weight of the external dependencies, it's evident that the ES6 transpilation process adds an incredible amount of bloat, particularly when dealing with default exports and imports:

webpackJsonp([1],{

/***/ 103:
/***/ function(module, exports, __webpack_require__) {

    /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
    /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __WEBPACK_IMPORTED_MODULE_0_angular__ && __WEBPACK_IMPORTED_MODULE_0_angular__.__esModule ? function() { return __WEBPACK_IMPORTED_MODULE_0_angular__['default'] } : function() { return __WEBPACK_IMPORTED_MODULE_0_angular__; }
    /* harmony import */ Object.defineProperty(__WEBPACK_IMPORTED_MODULE_0_angular___default, 'a', { get: __WEBPACK_IMPORTED_MODULE_0_angular___default });
    /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_moment__ = __webpack_require__(0);
    /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_moment___default = __WEBPACK_IMPORTED_MODULE_1_moment__ && __WEBPACK_IMPORTED_MODULE_1_moment__.__esModule ? function() { return __WEBPACK_IMPORTED_MODULE_1_moment__['default'] } : function() { return __WEBPACK_IMPORTED_MODULE_1_moment__; }
    /* harmony import */ Object.defineProperty(__WEBPACK_IMPORTED_MODULE_1_moment___default, 'a', { get: __WEBPACK_IMPORTED_MODULE_1_moment___default });



    /* harmony default export */ exports["default"] = /* harmony import */__WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('foo', []).run(function () {
        window.foo = /* harmony import */__WEBPACK_IMPORTED_MODULE_1_moment___default.a.bind()();
    });

/***/ }

},[103]);

Sadly, Uglify can't improve on this much:

webpackJsonp([ 1 ], {
    103: function(e, n, t) {
        var o = t(1), u = o && o.__esModule ? function() {
            return o["default"];
        } : function() {
            return o;
        };
        Object.defineProperty(u, "a", {
            get: u
        });
        var r = t(0), f = r && r.__esModule ? function() {
            return r["default"];
        } : function() {
            return r;
        };
        Object.defineProperty(f, "a", {
            get: f
        }), n["default"] = u.a.module("foo", []).run(function() {
            window.foo = f.a.bind()();
        });
    }
}, [ 103 ]);

It seems like there are some targeted optimizations that we can make around modules that only have a single export.

@YurySolovyov
Copy link

@schmod can you add rollup to your examples just for comparison?

@schmod
Copy link

schmod commented Aug 22, 2016

It's not an apples-to-apples comparison. Rollup doesn't provide a module system of its own, and instead asks if we want to target AMD, CJS, UMD, ES6, or an IIFE.

If we only have a single chunk, and no external dependencies (like the CommonsChunkPlugin I used to separate Angular and Moment from my "application" in the above example), this doesn't matter.

In fact, if you only have a single chunk, there are few benefits of having a module system at runtime at all. In this situation, Rollup's approach is clearly superior.

If we do want to have multiple chunks, asynchronous loading, and many of the other things that Webpack provides, we still need a module system, and things get a lot more complicated. It's less obvious as to how we can take advantage of rollup's scope-hoisting without adding any unnecessary overhead at runtime.

tl;dr; Rollup and Webpack have substantially different purposes


That being said, while a direct comparison isn't possible, Rollup handles ES6 modules more efficiently, even without scope-hoisting.

If rollup treats our libraries as opaque external dependencies, and targets CJS, we get a reasonably efficient bundle:

'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var angular = _interopDefault(require('angular'));
var moment = _interopDefault(require('moment'));

var index = angular.module('foo', [])
.run(function(){
    window.foo = moment();
});

module.exports = index;

In this example, _interopDefault is only declared once, and Rollup is smart enough to map export default to module.exports for my own module. The generated sources can be minified efficiently.

_interopDefault is really only useful when importing ES6 modules, but Rollup doesn't know it's unnecessary, because Angular and Moment are completely opaque to Rollup in this configuration.

If I want to dispense with a "real" module system entirely, Rollup can generate an IIFE that imports Angular and Moment from the global scope:

var myMod = (function (angular,moment) {
'use strict';

angular = 'default' in angular ? angular['default'] : angular;
moment = 'default' in moment ? moment['default'] : moment;

var index = angular.module('foo', []).run(function () {
    window.foo = moment();
});

return index;

}(angular,moment));

The resulting bundle is (surprisingly) a bit less efficient, as there's no reusable _interopDefault function. Otherwise, the resulting bundle can be minified efficiently.

"use strict";
function e(e) {
    return e && "object" == typeof e && "default" in e ? e["default"] : e;
}
var n = e(require("angular")), t = e(require("moment")), o = n.module("foo", []).run(function() {
    window.foo = t();
});
module.exports = o;

If we want Rollup to behave a little more like Webpack, the node-resolve and commonjs plugins can be used to pull our external modules into a single bundle.

var myMod = (function () {
'use strict';

var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}

function interopDefault(ex) {
    return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex;
}

function createCommonjsModule(fn, module) {
    return module = { exports: {} }, fn(module, module.exports), module.exports;
}

// rollup dumps entire source of angular.js here...

var index$1 = createCommonjsModule(function (module) {
module.exports = angular;
});

var angular$1 = interopDefault(index$1);

var moment = createCommonjsModule(function (module, exports) {

// and the source of moment gets dumped in here.

});

var moment$1 = interopDefault(moment);

var index = angular$1.module('foo', [])
.run(function(){
    window.foo = moment$1();
});

return index;

}());

The result is a lot less efficient (1.32MB). Angular is packaged as weird pseudo-IIFE, while Moment is packaged as a UMD module. Rollup creates a few helper functions to deal with these things.

This is the worst-of-all-worlds scenario – we've got the overhead of a module system, with none of the benefits.

This reveals one of the key drawbacks of Rollup -- only native ES6 sources benefit from tree-shaking and scope-hosting. Even though Moment is written with ES6 modules, it's bundled into a UMD module for NPM.

An apples-to-apples size comparison is particularly difficult in this scenario, because Webpack greedily bundles all of Moment's locale files (via a dynamic require()), and produces a huge 1.7MB bundle. See moment/moment#1435) for some context.

Rollup doesn't know how to handle this, and silently ignores the require() in Moment's source (which seems less-than-ideal).


If I use the bundle-loader plugin to mitigate this, the resulting bundle is 1.41MB; only about 10KiB larger than the equivalent Rollup bundle (most of which is occupied by the huge manifest that bundle-loader jams into the main bundle):

/* 5 */
/***/ function(module, exports, __webpack_require__) {

    var map = {
        "./af.js": 6,
        "./ar-ma.js": 8,
        "./ar-sa.js": 10,
        "./ar-tn.js": 12,
....

Plus one of these for each locale:

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

    var cbs = [], 
        data;
    module.exports = function(cb) {
        if(cbs) cbs.push(cb);
        else cb(data);
    }
    __webpack_require__.e/* nsure */(1, function(require) {
        data = __webpack_require__(7);
        var callbacks = cbs;
        cbs = null;
        for(var i = 0, l = callbacks.length; i < l; i++) {
            callbacks[i](data);
        }
    });

It's a larger bundle than Rollup, and it seems like there are opportunities to make bundle-loader (a lot) more efficient in this kind of scenario. However, this kind of dynamic loading isn't easily achievable with Rollup, whereas Webpack supports it extensively.


But, wait. Wasn't Moment written with native ES6 modules? Rollup can take advantage of that by enabling jsnext:main support in rollup.config.js:

plugins: [ json(), nodeResolve({ jsnext: true }), cjs({ exclude: ['node_modules/moment/**'] }) ],

With this configuration Rollup hoists all of Moment's internals into the same scope as our main application, and produces a bundle that's a whopping 2KB smaller (1.30MB).

Note that I had to explicitly tell rollup's CJS plugin not to process Moment's sources, because it wasn't smart enough to identify Moment's jsnext:main entry as an ES6 module. Also, locales aren't included in the bundle.


Wait. Can Webpack 1 take advantage of ES6 sources?

Kind of.

If I allow babel-loader to process my node_modules folder, and include moment via import moment from 'moment/src/moment', Webpack packages Moment by bundling its ~100 modules individually, and produces a 1.45MB bundle.

The same configuration with import moment from 'moment' produces a 1.41MB bundle.

So, where does that leave us?

My example primarily shows how Webpack and Rollup behave when importing large external libraries from NPM. In many ways, it is a contrived example that does not demonstrate the good features of Rollup or Webpack.

Among other things, I didn't import any of my own sources, and the two libraries I used both happen to publish pre-bundled sources to NPM.

In practice, most users are going to be importing lots of their own modules, and a small handful of external libraries. In this scenario, the advantages of Rollup are more evident, as there is virtually no cost associated with splitting my own source code into lots of small files. There would be a similar advantage when importing "native" CJS modules from NPM.

On the other hand, working with external libraries in Rollup was far from straightforward. Few existing libraries are written in ES6 to take advantage of tree-shaking, and I needed to explicitly remind Rollup's CJS preprocessor to ignore Moment's ES6 sources. The reward for all of this effort was underwhelming -- while Moment's written with ES6 modules, it doesn't expose an API that benefitted at all from tree-shaking. jsnext:main isn't standardized, and Rollup fails to offer a good solution for dynamic loading.

However, a few of the advantages that Rollup demonstrated could be easily incorporated into Webpack 2 without major architectural changes:

  • Reusable ES6 helper methods (Webpack generates these for each module -- they could very easily be hoisted into a higher scope to promote reuse).
  • No unnecessary ceremony around export default when a module only has one export.
  • Generated modules and helper methods can be minified efficiently (without sacrificing readability of the unminified code). Webpack adds property names like __esModule and default, which cannot be effectively minified without providing hints to the minifier.
  • Bonus: Optimize bundle-loader – it's staggeringly inefficient.

Before resorting to scope-hoisting, there are also other small optimizations that could be done -- if a module is only used once, it can likely be safely inlined into the consuming module's scope as an IIFE (or similar).


I also haven't investigated runtime performance. @nolanlawson clearly demonstrated that Webpack has a surprising amount of runtime overhead. It seems unlikely that any of the small tweaks that I discuss will have much impact in this area.

It's also worth noting that a large application built with Rollup will have a relatively "flat" lexical scope hierarchy (with one extremely crowded layer). I'd be interested to see some investigation into how well modern JS engines (and GC) can deal with that.

My concerns may be unwarranted, but it's possibly worth considering the implications of putting thousands of variables into a single scope.


Apologies for the rambling deep-dive. Investigating this has been fairly enlightening!

@schmod
Copy link

schmod commented Aug 22, 2016

So, after posting that, I decided to investigate whether or not Webpack 2 has improved since beta.6.


why didn't I do that first. [facedesk]


The good news is that most of my concerns have been addressed.

Using the same example as previously, Webpack 2.1.0-beta.21 generates the following bundle:

webpackJsonp([0],{

/***/ 106:
/***/ function(module, exports, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_moment__ = __webpack_require__(0);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_moment___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_moment__);



/* harmony default export */ exports["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('foo', []).run(function () {
    window.foo = __WEBPACK_IMPORTED_MODULE_1_moment___default()();
});

/***/ }

},[106]);

Much better. The improvement to the minified output is even more stark:

webpackJsonp([ 0 ], {
    106: function(n, o, u) {
        "use strict";
        var f = u(1), t = u.n(f), a = u(0), c = u.n(a);
        o["default"] = t.a.module("foo", []).run(function() {
            window.foo = c()();
        });
    }
}, [ 106 ]);

Putting it all together, in the "basic" example, Webpack 1 produces a 1.7MB bundle, and Webpack 2 produces a 1.66MB bundle.

Yawn.


Things are more interesting when we import Moment via ES6 (because that creates lots of modules) and minify the output.

Bundler transform-runtime Unminified Minified Min + gz
Webpack 1.13.2 yes 1.48MB 264KB 83KB
Webpack 1.13.2 no 1.45MB 245KB 78KB
Webpack 2.1.0-beta-21 yes 1.51MB 243KB 81KB
Webpack 2.1.0-beta-21 no 1.45MB 226KB 76KB
Rollup 0.34.10 no 1.27MB 212KB 73KB
Rollup 0.34.10 yes 1.27MB 212KB 73KB

There are no huge leaps forward, but it's worth noting Webpack 2 now outperforms Webpack 1 by a comfortable margin, which is a huge turnaround from the earlier betas.

This example has about a hundred modules in the final bundle. Webpack will perform less-favorably compared to Rollup as the number of modules increases.

Modules still have overhead, but we've trimmed most of the fat. Including Moment via its UMD bundle is still more efficient (Moment's own internal build process uses Esperanto, which is philosophically-similar to Rollup).

Still, Webpack 2 holds up a lot better compared to Rollup than I expected it to.


The next question to answer is why transform-runtime adds so much overhead.

@lukeapage
Copy link
Contributor

It might be because transform-runtime brings in slightly different babel runtimes which pull in and use corejs. The defaults ones are less strict.

In addition by default it polyfills your existing code, but that you can switch off.

@jokeyrhyme
Copy link

Can we use source maps to our benefit here? What if we detect when they are available, and inspect those for ES2015 modules?

@schmod
Copy link

schmod commented Aug 22, 2016

That was my thought too, but it doesn't seem like Rollup has a similar issue.

Digging a little further, it seems like rollup-plugin-babel actually does something similar to transform-runtime to provide and hoist the babel helpers.

However, unlike tranform-runtime, it doesn't appear to bring in core-js. In my example above, transform-runtime patched in the polyfills for some fairly well-supported ES5 features like Object.keys(), which likely accounts for a lot of the extra heft.

@Jessidhia
Copy link
Member

Jessidhia commented Aug 23, 2016

transform-runtime will use core-js in library mode, which does not polyfill anything. It's essentially a complete separate copy of core-js, and the transform changes your code that calls, say, Object.keys(), to (essentially) call require('core-js/library/fn/object/keys')() instead.

Even if you give the polyfill: false option to the plugin, code for the babel helpers (say, _asyncToGenerator) will still require core-js's library mode implementations.

AFAIK, if you polyfill at all, it's recommended to not use transform-runtime (or babel-runtime) in browser code, but babel-polyfill.

@schmod
Copy link

schmod commented Aug 23, 2016

transform-runtime will use core-js in library mode, which does not polyfill anything.

Incorrect usage of "polyfill" on my part -- you are correct.

AFAIK, if you polyfill at all, it's recommended to not use transform-runtime (or babel-runtime) in browser code, but babel-polyfill.

Babel's documentation about this particular issue is SUPER VAGUE, so it's unclear what's currently recommended.

babel-loader specifically recommends transform-runtime, even though my tests show it actually makes things worse in many cases (which I assumed this was due to babel/babel-loader#231 or babel/T7285).

rollup-plugin-babel implicitly does something similar to external-helpers, and consolidates all (used) helpers in a parent scope. It may be possible to adapt the same concept into babel-loader (and then go complain to the Babel people that transform-runtime does too many things).


That being said, I think we should move the module overhead conversation out of this ticket (possibly reopening #2425), and focus this discussion around bringing rollup-style scope-hoisting and merging to Webpack.

I'm curious about what @sokra has in mind, because it seems like this would require us to radically change the way that Webpack reasons about modules.

@TheLarkInn
Copy link
Member

I'm curious about what @sokra has in mind, because it seems like this would require us to radically change the way that Webpack reasons about modules.

@schmod Spot on. Last week we discussed the first steps were to simply add public api hooks to allow eliding of modules. (Which would then help make this possible).

@TheLarkInn
Copy link
Member

We are referring to leverage the same scope collapsing techniques.

The Chunk class in our source has the ability to split modules however we don't have functionality to combine modules (which would be along the lines of how we would accomplish this feature).

Some techniques that we would either implement or leverage from rollup would involve variable name deconflicting. Also there has been some research from the ember team which I met with last month ( @runspired @stefpenner ) and learned that browser engines favor more mixed scenario (not all rolled up into one module), rather the most commonly used modules rolled with edge modules in separate module wrappers in a webpack bundle. Hopefully this answers some questions.

@aluanhaddad
Copy link

aluanhaddad commented Jan 8, 2017

I realize this is largely unrelated, being a development time concern, but even with the recent improvements, the sheer textual bloat of the development bundles Webpack 2.2.0-rc.3 emits is a massive pain.
The following is the '@angular/core' exports section from an unoptimized Angular 2 bundle

/* harmony reexport (binding) */ __webpack_require__.d(exports, "Class", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["a"]; });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_core__ = __webpack_require__(542);
/* harmony reexport (binding) */ __webpack_require__.d(exports, "createPlatform", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["b"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "assertPlatform", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["c"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "destroyPlatform", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["d"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "getPlatform", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["e"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "PlatformRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["f"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ApplicationRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["g"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "enableProdMode", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["h"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "isDevMode", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["i"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "createPlatformFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["j"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgProbeToken", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["k"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "APP_ID", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["l"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "PACKAGE_ROOT_URL", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["m"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "PLATFORM_INITIALIZER", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["n"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "APP_BOOTSTRAP_LISTENER", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["o"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "APP_INITIALIZER", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["p"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ApplicationInitStatus", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["q"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "DebugElement", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["r"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "DebugNode", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["s"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "asNativeElements", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["t"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "getDebugNode", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["u"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Testability", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["v"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "TestabilityRegistry", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["w"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "setTestabilityGetter", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["x"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "TRANSLATIONS", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["y"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "TRANSLATIONS_FORMAT", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["z"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "LOCALE_ID", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["A"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ApplicationModule", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["B"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "wtfCreateScope", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["C"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "wtfLeave", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["D"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "wtfStartTimeRange", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["E"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "wtfEndTimeRange", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["F"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Type", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["G"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "EventEmitter", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["H"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ErrorHandler", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["I"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationTransitionEvent", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["J"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationPlayer", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["K"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Sanitizer", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["L"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "SecurityContext", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["M"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ANALYZE_FOR_ENTRY_COMPONENTS", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["N"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Attribute", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["O"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ContentChild", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["P"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ContentChildren", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["Q"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Query", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["R"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ViewChild", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["S"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ViewChildren", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["T"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Component", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["U"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Directive", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["V"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "HostBinding", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["W"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "HostListener", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["X"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Input", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["Y"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Output", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["Z"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Pipe", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_0"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AfterContentChecked", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_1"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AfterContentInit", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_2"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AfterViewChecked", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_3"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AfterViewInit", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_4"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "DoCheck", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_5"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "OnChanges", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_6"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "OnDestroy", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_7"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "OnInit", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_8"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "CUSTOM_ELEMENTS_SCHEMA", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_9"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NO_ERRORS_SCHEMA", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_10"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgModule", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_11"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ViewEncapsulation", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_12"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Version", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_13"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "VERSION", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_14"]; });
Object.defineProperty(exports, "__esModule", { value: true });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "forwardRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_15"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "resolveForwardRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_16"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Injector", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_17"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ReflectiveInjector", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_18"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ResolvedReflectiveFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_19"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ReflectiveKey", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_20"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "OpaqueToken", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_21"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Inject", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_22"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Optional", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_23"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Injectable", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_24"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Self", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_25"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "SkipSelf", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_26"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Host", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_27"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgZone", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_28"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "RenderComponentType", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_29"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Renderer", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_30"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "RootRenderer", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_31"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "COMPILER_OPTIONS", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_32"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "Compiler", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_33"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "CompilerFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_34"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ModuleWithComponentFactories", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_35"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ComponentFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_36"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ComponentRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_37"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ComponentFactoryResolver", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_38"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ElementRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_39"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgModuleFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_40"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgModuleRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_41"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "NgModuleFactoryLoader", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_42"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "getModuleFactory", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_43"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "QueryList", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_44"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "SystemJsNgModuleLoader", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_45"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "SystemJsNgModuleLoaderConfig", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_46"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "TemplateRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_47"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ViewContainerRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_48"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "EmbeddedViewRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_49"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ViewRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_50"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ChangeDetectionStrategy", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_51"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "ChangeDetectorRef", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_52"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "CollectionChangeRecord", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_53"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "DefaultIterableDiffer", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_54"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "IterableDiffers", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_55"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "KeyValueChangeRecord", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_56"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "KeyValueDiffers", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_57"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "SimpleChange", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_58"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "WrappedValue", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_59"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "platformCore", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_60"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "__core_private__", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_61"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AUTO_STYLE", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_62"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationEntryMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_63"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationStateMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_64"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationStateDeclarationMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_65"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationStateTransitionMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_66"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_67"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationKeyframesSequenceMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_68"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationStyleMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_69"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationAnimateMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_70"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationWithStepsMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_71"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationSequenceMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_72"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "AnimationGroupMetadata", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_73"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "animate", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_74"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "group", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_75"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "sequence", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_76"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "style", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_77"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "state", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_78"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "keyframes", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_79"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "transition", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_80"]; });
/* harmony reexport (binding) */ __webpack_require__.d(exports, "trigger", function() { return __WEBPACK_IMPORTED_MODULE_0__src_core__["_81"]; });

This all gets compressed decently with uglify for production but, as part of a 5-10MB development bundle, it makes the browser grind to a halt as soon as a breakpoint is hit, lagging for over 10 seconds on a powerful workstation.
Frankly it is also unreadable, with all of that comment text choking up the file.

Yes we all want to live in a better, more caring and less discordant JavaScript world where Node and the Browser learn to love each other, so I appreciate Webpack 2's asserted desire to be in harmony 😃 and embrace ES Modules but would you consider removing the /* harmony reexport (binding) */ and maybe using a shorter and less obnoxious prefix than __WEBPACK_IMPORTED_MODULE_ 😄?

@NekR
Copy link

NekR commented Jan 8, 2017

So there is rollup-loader now, isn't it a solution?

@PmegaOcalc
Copy link

@istiti Scope hosting is in plans for webpack 2 see https://webpack.js.org/vote/. Tree shaking is already implemented for webpack 2.

@elvisbegovic
Copy link

@mantastrunce and what mean "is in plans" any project board ? because here I can't find https://github.com/webpack/webpack/projects

@wegry
Copy link

wegry commented Jan 24, 2017

@NekR rollup loader doesn't seem to do scope hoisting, it does appear to do rollup's more aggressive tree shaking though.

@mantastrunce Webpack 2 relies in large part on uglify to drop unused variables. For modules containing a class that uses this, uglify will not remove it.

// export and dead code module

// export used elsewhere
export function a () {
  console.log('a called')
}

// Dropped by rollup but not by uglify because of `this` usage
const oldStyleClass = function (b) {
  return {
    b,
    c: this.b + 1
  }
}

One could argue thorough linting will catch the second case, unless you're dealing with sub-par code generation from a compiled to JS language.

@aluanhaddad
Copy link

aluanhaddad commented Feb 14, 2017

@wegry

// Dropped by rollup but not by uglify because of `this` usage
const oldStyleClass = function (b) {
  return {
    b,
    c: this.b + 1
  };
}

One could argue thorough linting will catch the second case, unless you're dealing with sub-par code generation from a compiled to JS language.

Or one could argue that a better solution would be to simply avoid using this and by extension, avoid using classes except where mandated by frameworks.

Classes have introduced exponential complexity and confusion to JavaScript while at the same time being, themselves, so fundamentally weak (not supporting multiple inheritance or declarative metadata) as to necessitate even more complexity just to make them a half way viable construct.

Factory patterns are preferable for so many reasons and yet we in the JavaScript world have become addicted to a class feature that pales in comparison to what is provided by other languages while having had better alternatives in JavaScript for almost 2 decades.

What I dislike most about classes, which by the way can be a very elegant in certain situations, is having to explain, over and over and over and over again, to people either learning JavaScript or people learning TypeScript, is that classes are not types.

Next time you see someone trying to use a class as an interface, give them a good talking too.

@TheLarkInn TheLarkInn modified the milestones: webpack 2.4 Feature release, future releases Mar 29, 2017
@andraaspar
Copy link

@aluanhaddad You could shorten __WEBPACK_IMPORTED_MODULE_ using a simple plugin like this.

@aluanhaddad
Copy link

@andraaspar I appreciate the suggestion and my comment was meant to be playful, but with 24GB of tri-channel DDR@1334 (7-7-7-1T), 8 logical cores@3.2ghz, and a 1TB SSD I should be OK by default.

@avindra
Copy link
Contributor

avindra commented Apr 19, 2017

@aluanhaddad All that matters is a single core running at 3.2 GHZ, since Webpack by default runs on one thread (and by extension, can only be used on a single core).

If you want to take advantage of all those cores, check out https://github.com/amireh/happypack

Or start diving into the shared memory spec and think about how Webpack can get it natively :)

@elvisbegovic
Copy link

Hope this will be better. When I build my project with angular-cli, it blocking at 92% of building and the rest of time is due to webpack bundle process which takes 70% of total time.
1mn angular compiler
2mn webpack bundle Uglify i think.

Cc @TheLarkInn

@andraaspar
Copy link

@aluanhaddad Not so much speed, rather than legibility of the compiled code is the issue. I get a lot of 200 character lines with bloat for no good reason.

@aluanhaddad
Copy link

@avindra that's an excellent point. Although some plugins, like awesome-typescript-loader, at times fork children, your point is well taken.

@andraaspar indeed, that is part of the issue.

@istiti I'm not talking about bundling speed. I am talking about the size of the development bundle. Webpack creates the bundle quite quickly and rebuilds are also very fast. The only complaint is the quantity of seemingly arbitrary text that it contains, specifically as relates to tools such as browser debuggers and editors.

@sokra
Copy link
Member

sokra commented May 22, 2017

fixed by Scope Hosting. See also https://medium.com/webpack/webpack-freelancing-log-book-week-5-7-4764be3266f5

Runtime and Size is now ~ rollup values plus 10ms and 500b (5000 modules, on mobile). We still include the runtime, that the difference.

@bhollis
Copy link

bhollis commented May 27, 2017

@sokra awesome! I read your post and it looks like it'll help a lot for modules that depend on a lot of little things but have a single export. But what about the lodash case, where the main chunk may be importing a ton of tiny modules which live in a separate vendor chunk? I think there will still be a lot of overhead there.

@elvisbegovic
Copy link

My english is poor... in summary does webpack tree shake as rollup now?!?

@elyobo
Copy link

elyobo commented May 28, 2017

@istiti as of webpack 2 it already did, this is something else.

@lukeapage
Copy link
Contributor

lukeapage commented May 29, 2017 via email

@elvisbegovic
Copy link

@elyobo maybe treeshaking is already here but not improved as rollup thats why I ask

@webpack-bot
Copy link
Contributor

For maintainers only:

  • webpack-4
  • webpack-5
  • bug
  • critical-bug
  • enhancement
  • documentation
  • performance
  • dependencies
  • question

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests