The cost of small modules #2873

Open
jdalton opened this Issue Aug 15, 2016 · 24 comments

Projects

None yet
@jdalton
Contributor
jdalton commented Aug 15, 2016 edited

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.

@bebraw bebraw added the enhancement label Aug 15, 2016
@lukeapage
Contributor

Related: #2425 (comment)

@sokra
Member
sokra commented Aug 16, 2016 edited

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
acidicX commented Aug 16, 2016 edited

@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

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

@jdalton
Contributor
jdalton commented Aug 16, 2016 edited

@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

@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
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

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

@fundon fundon referenced this issue in vue-bulma/vue-admin Aug 22, 2016
Open

Rollup? #45

@schmod
schmod commented Aug 22, 2016 edited

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).
    • May be related to babel/babel-loader#231 -- including transform-runtime appears to result in more helpers being generated; not less.
    • The specific issues with Webpack 1 and _interopRequireDefault appear to be a Babel issue.
  • 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
schmod commented Aug 22, 2016 edited

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
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

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

@schmod
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.

@Kovensky
Collaborator
Kovensky commented Aug 23, 2016 edited

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
schmod commented Aug 23, 2016 edited

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 TheLarkInn added this to the future releases milestone Aug 25, 2016
@TheLarkInn
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).

@sokra sokra added P1: Urgent and removed P2: Required labels Sep 8, 2016
@istiti
istiti commented Nov 2, 2016

please apologize my ignoring, i dont understand: what this issue mean, plan to have rollup in webpack ?

@robwormald robwormald referenced this issue in angular/angular-cli Nov 2, 2016
Closed

rollup #2817

@nathanmarks

@sokra you mentioned this being possible. When you say possible are you talking about one or the other (Inlining vs module privacy)? Or is there a potential to be able to leverage both in the same project?

Also, if you have any initial thoughts/findings on being able to leverage rollup core it'd be great to hear what you discovered.

@TheLarkInn
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
aluanhaddad commented Jan 8, 2017 edited

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
NekR commented Jan 8, 2017

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

@jods4 jods4 referenced this issue in aurelia/framework Jan 14, 2017
Open

[Feature Request] Bundling with Rollup #642

@istiti
istiti commented Jan 19, 2017 edited

any ETA or news here ? I use cli and they let me know it depend on webpack team, any news about having rollup tree shaking instead uglify or some optomisation todo better

@mantastrunce

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

@istiti
istiti commented Jan 20, 2017

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

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