andreypopp / autobind-decorator

Decorator to automatically bind methods to class instances

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Uglify errors in react scripts

harinair opened this issue · comments

I am running into an Uglify error that was traced to autobind-decorator@2.2.1

autobind-decorator@2.1.0 works fine. The following is the error:

Failed to compile.

Failed to minify the bundle. Error: static/js/main.d366c2d2.js from UglifyJs
Unexpected token: name (fn) [static/js/main.d366c2d2.js:396674,6]
    at compiler.run (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/@pearson-incubator/react-scripts/scripts/build.js:130:23)
    at emitRecords.err (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/webpack/lib/Compiler.js:269:13)
    at Compiler.emitRecords (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/webpack/lib/Compiler.js:375:38)
    at emitAssets.err (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/webpack/lib/Compiler.js:262:10)
    at applyPluginsAsyncSeries1.err (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/webpack/lib/Compiler.js:368:12)
    at next (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/tapable/lib/Tapable.js:218:11)
    at Compiler.compiler.plugin (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/webpack/lib/performance/SizeLimitsPlugin.js:99:4)
    at next (/Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/tapable/lib/Tapable.js:220:14)
    at /Users/ugangha/Sandbox/Pearson/Cite/greenville/node_modules/sw-precache-webpack-plugin/lib/index.js:98:18
    at <anonymous>
Read more here: http://bit.ly/2tRViJ9

This error is happening in a "let" statement. From what I read I feel Uglify cannot handle ES6 code and create react scripts does not convert all node modules to ES5 before feeding to Uglify. My assumption is some build option is changed from 2.1.0 to 2.2.1 so that the build is provided in ES6 not pure ES5.

I just ran into the exact same issue.

It's definitely a bug related to the contents of the package.json now having "module": "src/index.js", as added in this commit:

9edeabf#diff-b9cfc7f2cdf78a7f4b91a753d10865a2

@stevemao could you please remove modules from package.json?

The code pointed to by modules needs to be ES5 code but with ES6 modules (import/export).

The problem here is that src had ES6 code (including let etc).

You can read more about it here: https://github.com/rollup/rollup/wiki/pkg.module#wait-it-just-means-import-and-export--not-other-future-javascript-features

Who says that? Module entry is supposed to point to scripts with Es modules. Tools usually use this entry for tree shaking.

Did you read the link I posted? Basically the authors of webpack & rollup ALL say that modules should point to ES5 code with ONLY es6 modules. And since they are the ones who added it to package.json and implemented tree shaking they're probably the best authority on the subject.

On the other hand, you are using a deprecated minifier and wrong webpack config.

I'm using the latest version of webpack and the latest minifier that it supports. I maintain several projects that use webpack, so I hardly think I'm using a wrong webpack config. It worked fine until the version of autobind-decorator that broke the rules.

If you need to support old environment, you can use Babel env to transpile modern JavaScript to old version.

That is not how the spec for modules in package.json modules works. If you don't want to believe that then I guess people will need to find alternatives if they want to use autobind decorators with modern tools like webpack or rollup.

Have you tried bundling the latest of autobind-decorator with either rollup or webpack? I suggest you try...

I guess a year and a half is a long time in JS land. lol For what it's worth, Dan Abromov (author of create react app) also said the same thing (a year ago): webpack/webpack#1979 (comment)

If you want to deviate from the original intention of the modules field then that's your prerogative, but you're going against the grain (I have never seen a single other package that exports raw es6 source via the modules field) and you're forcing people to compile all of their node_modules, which is certainly not standard.

I guess I'll leave it here and let other users of this package chime in if they feel the need to.

In any case, speaking of "modern javascript" the new "class properties" proposal & babel-plugin let you just replace:

class Foo {
  @autobind
  aMethod() { }
}

with:

class Foo {
  aMethod = () => { }
}

This is a simpler alternative for our projects than having to compile all source in node_modules to be able to use new versions of this package...

I have never seen a single other package that exports raw es6 source via the modules field

I have seen many packages exporting modern javascript via the main field. This is also the reason why create-react-app compiles node_modules.

In any case, speaking of "modern javascript" the new "class properties" proposal & babel-plugin let you just replace:

That is already mentioned in the README and I think it's a good alternative
https://github.com/andreypopp/autobind-decorator#alternative

@stevemao interesting, can you share some examples of packages that are exporting es6 syntax (other than es6 modules) via the main or modules field? I’m curious if any of them are intended for use in the browser vs node.

In any case, we only added a module entry to the package.json for modern browsers and tree shaking. So it's a new feature. The old main entry is still there any the files are not changed. If you want the old file you can still use the main entry so this is not a breaking change.

lol, except you can't use minification anymore with webpack without transpiling node modules first.

The right way to fix it is to use separate lib/es outputs like most other libraries do.

Happy to offer pointers if you're open to it. It's just a matter of forking your babel config to change the modules parameter to either preset-es2015 or preset-env...

A good example is here: https://github.com/react-bootstrap/react-bootstrap/blob/master/.babelrc.js

@jharris4 They use jsx in the src so they have to compile it. For those who want to use modern javascript and only target modern browsers/env what's your recommendation?

@stevemao, For now, we need to look at a workaround. The default create-react-app / react scripts does not support this code. And most devs use the create-react-app. Hence a lot of people who have autobind-decorator dependency will run into this error soon. I personally wasted a day before I tracked this issue to this library.

My recommendation is to create a 3.x version with ES6 features and maintain a 2.x release for ES5 until react start supporting ES6 by default. What do you think?

The default create-react-app / react scripts does not support this code.

It does. I'm using create-react-app too.

I think we can add a note on README.

I have added a note just now on readme. let me know if it makes sense

ya, I wasted a couple of hours tracking this down myself.

Definitely should have been a version bump as this is definitely a breaking change.

As a workaround, I've just switched to class properties like I posted earlier. so I'm not using this package anymore...

@stevemao I don't have a good answer for how to allow npm packages to be consumed in es6+ only mode. As far as I know nobody has really solved this problem yet, but maybe a new next field in package json to complement the existing main and module fields would be the way to go. I've already weighed in on how module is NOT the place for es6 only code, so not much else I can add despite the fact that I understand your motivation here...

Definitely should have been a version bump as this is definitely a breaking change.

If we pointed main to a ES6 script then it would have been a breaking change.

Thanks @jharris4 . I personally periodically improve my build script and look up create-react-app as a good reference. They have removed deprecated uglify-js and they also compile node_modules (but only from standard javascript).

Related Bug:
react-dnd/react-dnd#1152

I couldn't build my app built on Create-React-App using React DnD. Thanks @harinair for pointing to the related thread. If others are experiencing this, the workaround with react dnd is to pin autobind-decorator to version 2.1.0. Since then, I'm able to build just fine.

@shouvik44 did you read the blog I linked?

@stevemao I read through it, but I didn't understand how to take action. I can't stop using react-DnD, and the older version of autobind-decorator works well for my current needs.

@stevemao

I don’t necessarily agree. That article was published a long time ago when es6 was new (the future javascript). Some people only want to target modern browsers (with full support of modern JavaScript), are they forced to run es5 code only?

LOL.
Most of the people only want their apps to just work and not break suddenly.
Are you forcing those people to hack around your preference of putting incompatible js syntax in the release just because you like it more?
The module entry is clearly for ES5 syntax with only ES6 modules, as @jharris4 already said.

@stevemao

I have seen many packages exporting modern javascript via the main field. This is also the reason why create-react-app compiles node_modules.

And that means that they do it wrong.
If someone jumps from a bridge will you jump too?
I guess you do...

@stevemao

In any case, we only added a module entry to the package.json for modern browsers and tree shaking. So it's a new feature. The old main entry is still there any the files are not changed. If you want the old file you can still use the main entry so this is not a breaking change.

Man, you don't get it: bundlers do always prefer the module entry ignoring main.
So you're consciously and willingly breaking everyone's projects because you know Webpack won't compile them and you're fine with that.
Well, no wonder react-dnd moved away from using this package.

@stevemao

For those who want to use modern javascript and only target modern browsers/env what's your recommendation?

OBVIOUSLY, introduce a new main:next entry or whatever else and coordinate between bundlers so that they support it.

@stevemao

If we pointed main to a ES6 script then it would have been a breaking change.

You don't get it, introducing module already is a breaking change because it takes priority over main.

@catamphetamine If I have to argue with you I'll repeat what I have said. Your arguments haven't been constructive and convincing but rather mocking and attempting to taunt me. I suggest be patient and read the babel blog again rather than believing in what you think is right. Coz it's not.

@catamphetamine If you want to learn how to discuss with people properly in a constructive way, have a look at #78 by @lroling8350. That issue so far has provided really good value. And I really appreciate everyone's inputs. Peace.