Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Webpack 4.x Mangling issue #234

Closed
Apidcloud opened this issue Feb 17, 2018 · 24 comments
Closed

Webpack 4.x Mangling issue #234

Apidcloud opened this issue Feb 17, 2018 · 24 comments

Comments

@Apidcloud
Copy link

Apidcloud commented Feb 17, 2018

Good evening!

I'm trying to use webpack 4.x with uglifyjs plugin, but I need to disable mangling, which seems to not be working as before. Using v1.1.8 with webpack 3.11 didn't change class names when mangle was set to false; but it is changing them with webpack 4.x.

The version of the underlying uglify-es in node_modules is 3.3.9 in both cases.

What could be the issue?

Here's part of webpack.config:

mode: "production",
  optimization: {
    minimizer: [
      new UglifyJSPlugin({
        uglifyOptions: {
          beautify: false,
          compress: true,
          comments: false,
          mangle: false,
          toplevel: false,
          keep_classnames: true, // <-- doesn't exist, I guess. It's in harmony branch
          keep_fnames: true //
        }
      })
    ]
  },

Thanks!

Edit: Just to make sure, cleaning yarn's cache didn't help either.

@michael-ciniawsky
Copy link
Member

michael-ciniawsky commented Feb 17, 2018

Why this should be different between webpack v3.0.0 && webpack v4.0.0 I don't understand tbh (e.g where you definitely using uglifyjs-webpack-plugin v1.0.0 with webpack v3.0.0), but keep_classnames was (re)added in todays release (v1.2.0) I published a few hours ago and was missing since uglifyjs-webpack-plugin v1.0.0. If upgrading to v1.2.0 doesn't solve the issue please provide more context about your setup. Current/Expected results, package.json && webpack.config.js etc

@Apidcloud
Copy link
Author

Apidcloud commented Feb 17, 2018

Updating to 1.2.0 doesn't seem to work either.

Still get stuff like class gameObject_GameObject instead of class GameObject.
The only changes are literally webpack 3.x (3.6 and 3.11) to webpack 4.x and changing the uglify configs from plugins to with webpack's config as shown above.

The options are the same, and yet the output differs (at least in class names, for some reason):

new UglifyJSPlugin({
        uglifyOptions: {
          warning: "verbose",
          ecma: 6,
          beautify: false,
          compress: false,
          comments: false,
          mangle: false,
          toplevel: false,
          keep_classnames: true,
          keep_fnames: true
        }
      })

It's really late here (4:40am), so for now I can only reference the repository branches:
https://github.com/scarlettgamestudio/scarlett-framework/tree/editor-issue-3 uses webpack 3.6 and sets uglifyjs 1.1.8 mangle to false, resulting in no changes in class names.

https://github.com/scarlettgamestudio/scarlett-framework/tree/pr/webpackV4 uses webpack 4.x, and sets uglifyjs 1.2.0 (tested with 1.1.8 as well) mangle to false and keep_classnames to true, but it changes class names.

If you have the time to test it, run yarn and then yarn build:deploy:editor
It should produce the following build: build/dist/scarlett.framework.min.js, where class names are renamed (and I don't want to).
search for class gameObject and you'll see that it produced class gameObject_GameObject instead of class GameObject.

@sokra
Copy link
Member

sokra commented Feb 18, 2018

Could you try with optimization.minimize: false and add the plugin to plugins directly? I want to figure out if this is a webpack or uglifyjs-webpack-plugin issue.

@sokra
Copy link
Member

sokra commented Feb 18, 2018

@Apidcloud
Copy link
Author

Apidcloud commented Feb 18, 2018

Just tried, but the result is the same. I'll try to determine the real reason or create a simpler user case, as only some classes have the problem (with webpack 4.x + uglifyjs plugin).

That file you mentioned is only used with the webpack 3.x branch via the env variable in the script.

Thanks!

@Apidcloud
Copy link
Author

Apidcloud commented Feb 18, 2018

Was able to reproduce/isolate the issue within a way smaller repository using webpack 4.0.0-beta.2: https://github.com/Apidcloud/scarlett-blast/tree/issueWebpack

I basically mirrored what's happening in the other one (see demo/src - it only contains 2 classes now, namely Logger and Game).

After running yarn build, the class Logger is fine, but class Game appears as class game_Game (see build/bundle.min.js)

I'll keep investigating 😄

Edit: Hmmm. Removing the import of class Logger within class Game seems to solve the issue for that class only.

For instance, importing Game within class CustomShader makes it class customShader_CustomShader, whereas removing the import makes it work again as class CustomShader.

So basically, it's not affecting isolated classes, but rather the ones that are dependent on others.

Edit 2: It seems to be happening only with mode: 'production', so I'm left to conclude it's a problem with webpack itself, rather than with the plugin, which seems to be keeping the class names (option keep_classnames: true) properly when webpack is in development mode.

@alexander-akait
Copy link
Member

@Apidcloud thanks for minimum reproducible test repo!

@Apidcloud
Copy link
Author

You're welcome 😄

I've branched out the issue so you can keep testing in the same repository: https://github.com/Apidcloud/scarlett-blast/tree/issueWebpack

@alexander-akait
Copy link
Member

/cc @kzc

@kzc
Copy link

kzc commented Feb 20, 2018

Still get stuff like class gameObject_GameObject instead of class GameObject

It's most likely a webpack 4 module hoisting and/or export renaming issue from the description. I'm not going to build either project, but you can verify it by disabling uglify and searching the resultant webpack output for gameObject_GameObject.

See also:

webpack/webpack#5463 (comment)
webpack/webpack#5463 (comment)

By the way, I don't follow the uglify project any longer. If you think it's an uglify issue submit a bug report to that project with a self contained JS input file with no third party tools/libraries/webpack involved.

@Apidcloud
Copy link
Author

In one of my latest replies, I mentioned that I don't think it's an uglify js issue, as it works well with webpack 3.x, but it doesn't with webpack 4.x 'production' mode. But I only found out that 2 days ago and thus creating the issue here.

Also, that's precisely why I linked https://github.com/Apidcloud/scarlett-blast/tree/issueWebpack

There are no third party tools or libraries involved in there. Classes have nothing inside.

@kzc
Copy link

kzc commented Feb 20, 2018

Could you try with optimization.minimize: false and add the plugin to plugins directly? I want to figure out if this is a webpack or uglifyjs-webpack-plugin issue.

Set optimization.minimize: false and remove the uglify plugin from the webpack config file altogether. If gameObject_GameObject or game_Game is in the webpack output, then it's a webpack issue.

@kontrollanten
Copy link

I'm also experiencing problem with passing uglifyOptions in Webpack 4. I tried the following:

optimization: {
  minimizer: [
    new UglifyJSPlugin({
      uglifyOptions: { ... },
    }),
  ],
},

But I get

Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead

from Webpack.

I though that the options should be sent to optimization.minimize, but it only takes a boolean. Does anyone have a clue about where to configure UglifyJSPlugin in Webpack 4?

@michael-ciniawsky
Copy link
Member

michael-ciniawsky commented Feb 28, 2018

@kontrollanten Are you requiring the plugin from const { UglifyJSPlugin } = require('webpack').optimize atm ? If, I think that export was removed and you need to const UglifyJSPlugin = require('uglifyjs-webpack-plugin') it instead. Doesn't optimization.minimize accept an {Object} to pass uglifyOptions (Not sure here) ?

@kontrollanten
Copy link

kontrollanten commented Feb 28, 2018

No, I tried that now though. But then I get

TypeError: UglifyJSPlugin is not a constructor

And when try without new, I'll get

TypeError: UglifyJSPlugin is not a function

Edit: Typo error :-) When I import UglifyJsPlugin instead, I get the same error as above (Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead).

@michael-ciniawsky
Copy link
Member

Please show the relevant part of your webpack.config.js :)

@michael-ciniawsky
Copy link
Member

michael-ciniawsky commented Feb 28, 2018

const UglifyJSPlugin = require('uglifyjs-webpack-plugin')

...

optimization: {
  minimizer: [
    new UglifyJSPlugin({
      uglifyOptions: { ... }
    })
  ]
}

Doesn't work ?

@kontrollanten
Copy link

It seems that the following is working. The exception was thrown through offline-plugin.

const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

...

  optimization: {
    minimizer: [
      new UglifyJSPlugin({
        uglifyOptions: {
          output: {
            comments: false
          },
          compress: {
            unsafe_comps: true,
            properties: true,
            keep_fargs: false,
            pure_getters: true,
            collapse_vars: true,
            unsafe: true,
            warnings: false,
            screw_ie8: true,
            sequences: true,
            dead_code: true,
            drop_debugger: true,
            comparisons: true,
            conditionals: true,
            evaluate: true,
            booleans: true,
            loops: true,
            unused: true,
            hoist_funs: true,
            if_return: true,
            join_vars: true,
            cascade: true,
            drop_console: true
          }
        }
      }),
    ]
  },

Now I have a lot of other errors thrown from other plugins. The investigation continues. Thanks for your quick response and a great plugin!

@ketabi
Copy link

ketabi commented Apr 11, 2018

Look at:
https://stackoverflow.com/a/49767690/6200607
for more information.

@cihati
Copy link

cihati commented Jul 13, 2018

I needed to upgrade offline-plugin -- a relevant issue was fixed at 5.0.3 I believe.

@valera1401
Copy link

Why this issue is closed ? The problem still exists. Mangle can't be disabled.

@gmfun
Copy link

gmfun commented Jul 25, 2018

@sokra Seems to be problem with webpack, because minimize: false is also changing the class name. Facing this issue with webpack@4.16.2. Not sure but could it be a problem with babel?

@kindofone
Copy link

I installed uglifyjs-3-webpack-plugin:

npm i -D uglifyjs-3-webpack-plugin

Required it in my webpack.config.js instead of the built-in uglifyjs-webpack-plugin:

const UglifyJsPlugin = require("uglifyjs-3-webpack-plugin");

Now mangle: false is working again! 🎉

@KevinBrogan
Copy link

guys, i found the solution.

optimization:
{
	concatenateModules: false
}

If that is turned on, you end up with classes that are named class_Class and class_OtherClass

Minimization is still an issue if you need the class names, but that can be fixed by using the minimizer options.

Default production webpack 4 config for me is now:

mode: 'production',
optimization:
{
	concatenateModules: false,
	minimizer:
	[
		new TerserPlugin
		(
			{
				terserOptions:
				{
					keep_classnames: true
				}
			}
		)
	]
}

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

No branches or pull requests