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

[webpack2] Tree shaking and "unused harmony default export" #2866

Closed
tleunen opened this issue Aug 13, 2016 · 13 comments
Closed

[webpack2] Tree shaking and "unused harmony default export" #2866

tleunen opened this issue Aug 13, 2016 · 13 comments

Comments

@tleunen
Copy link

tleunen commented Aug 13, 2016

I'm running webpack 2 beta 20 and for a development build, I can see a lot of unused harmony default export in my UI library (which is normal since I don't use everything that is available in the library).

I checked the code and instead of exporting the class with the webpack require function, i see this, which seems ok.

/* unused harmony default export */ var _unused_webpack_default_export = ComponentA;

But when I build the app in a production environment, the component is still there, even if it has been marked as unused.

The component is imported and exported from another file before my app really uses it.

export { default as ComponentA } from './ComponentA';

and inside that file, it's marked like this:

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19__ComponentA__ = __webpack_require__(622);
/* unused harmony reexport ComponentA */

I also checked the compiled code in production, and the code is there but as it's mentioned with the unused reexport, nothing is exported... No t.default = ...

From what I see, it seems there's an issue in the tree-shaking/code elimination. Can you confirm, or tell me what would be wrong in what I'm trying to do?

@tleunen
Copy link
Author

tleunen commented Aug 19, 2016

Tested with latest beta 21 and same issue.

@sokra
Copy link
Member

sokra commented Sep 7, 2016

I need a bit more information to fix this.

How does the app import module which is reexporting the ComponentA?

Could you create a minimal test repo which allows me to reproduce the issue?

@tleunen
Copy link
Author

tleunen commented Sep 7, 2016

@sokra See this repo: https://github.com/tleunen/webpack-2866 with this file resulted file: https://github.com/tleunen/webpack-2866/blob/master/dist/build.js

Only util31 is used in app.js, but all util1, util2 and util32 are in the resulted file.

@sokra
Copy link
Member

sokra commented Sep 8, 2016

Looks correct to me. The functions itself are removed by UglifyJs once you minimize the file.

Minimized file:

!function(t){function n(e){if(r[e])return r[e].exports
var u=r[e]={i:e,l:!1,exports:{}}
return t[e].call(u.exports,u,u.exports,n),u.l=!0,u.exports}var r={}
return n.m=t,n.c=r,n.i=function(t){return t},n.d=function(t,n,r){Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var r=t&&t.__esModule?function(){return t["default"]}:function(){return t}
return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="/",n(n.s=4)}([function(t,n,r){"use strict"
var e=(r(1),r(2),r(3))
r.d(n,"a",function(){return e.a})},function(t,n,r){"use strict"},function(t,n,r){"use strict"},function(t,n,r){"use strict"
function e(){console.log("util 3.1")}n.a=e},function(t,n,r){"use strict"
var e=r(0)
r.i(e.a)()}])

The minimized file only contains console.log("util 3.1").

@sokra sokra closed this as completed Sep 8, 2016
@eliseumds
Copy link

@sokra so was it a misunderstanding? Or was it fixed by someone recently?

@jippi
Copy link

jippi commented Sep 8, 2016

I assume the problem was not applying Uglifyjs ?

@tleunen
Copy link
Author

tleunen commented Sep 8, 2016

Hmm Ok, I didn't know webpack wasn't supposed to remove them, even in a dev mode. But in my real use case, it still doesn't work after uglify.

I updated the code with a more complex code @sokra,and everything is still in the final bundle.
See https://github.com/tleunen/webpack-2866

@sokra
Copy link
Member

sokra commented Sep 8, 2016

yeah, uglify-js is not that clever as you would except it to be. We are working on a solution, but this will take time. There is already another issue, so I'll keep this closed.

@tleunen
Copy link
Author

tleunen commented Sep 8, 2016

Can you point me to the issue you have in mind so I can keep tracking it?

@iamakulov
Copy link

Can you point me to the issue you have in mind so I can keep tracking it?

Looks like it’s #2867 (see #2867 (comment) and below).

@davidmoshal
Copy link

have run into the situation where /* unused harmony export */ exports es6 code for usused functions, e.g.:

let sum = (xs) =>
....
problem is that this causes older non-es6 browsers, such as IE 11 to fail to render the page.
Seems odd to included unused functions, in es6 !!

Stack:

webpack 2
awesomes-typescript
tsconfig set to export es5
Uglify not being used.
David

@iamakulov
Copy link

@davidmoshal

Uglify not being used

That’s because of this. Unused code is removed by a minifier (such as UglifyJS). Tree-shaking just makes it possible for minifier to remove it.

So, in your case, enabling UglifyJS will most likely solve the problem.

@davidmoshal
Copy link

davidmoshal commented Mar 16, 2017

@iamakulov thanks, enabling UglifyJS did NOT solve the problem, but it DID lead to a solution.

Recall that the problem initially surfaced when IE 11 refused to run ES6 code, by failing to run the main.js script which contained ES6 code:

/* unused harmony export */ 
let sum = (xs) =>

Enabling UglifyJS resulted in Uglify also complaining about the ES6 code !!

Fiddling with tsconfig.json did not help either.
Awesome-typescript was correctly emitting ES5 code,
but Webpack was adding unused code into the main.js as ES6 !!

This seems to have been for lodash which was set as a provided resource in webpack.

Adding babel-loader solved the problem, both for IE 11 and UglifyJS.

So it seems like something this is happening:

  1. awesome-typescript is emitting es5 correctly.
  2. webpack's tree shaking is adding unused JS as es6 (!!)
  3. Babel-loader is converting that unused JS to es5 correctly.
  4. UglifyJS is removing the unused JS correctly.

This workflow works, but doubles the transpilation time, so I'm only using this workflow for build scripts.

I'd suggest that emitting unused imports as es6 is a bug, not a feature.

David

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

7 participants