-
-
Notifications
You must be signed in to change notification settings - Fork 179
Uglify Does Not Uglify Enough on Latest Webpack + React 16 #206
Comments
We were dealing with similar issues for a while. What it came down to was the following: Uglify looks for the presence of I see you already have Another thing, Finally, we had a problem with the Hope one of these things helps! Nick |
That's not correct. It's up to a webpack plugin to replace |
@kzc Thanks for the clarification! |
We were seeing the exact same thing until we set |
Some webpack plugin ordering issue apparently: |
To avoid
$ cat minify.js
var uglify = require("uglify-es");
var code = "if (process.env.NODE_ENV == 'production') prod(); else dev();";
var options = {
compress: {
global_defs: {
"process.env.NODE_ENV": "production"
}
}
};
var result = uglify.minify(code, options);
if (result.error) throw result.error;
console.log(result.code);
|
@kzc very strange all works fine without |
Those having issues with |
It seems to be a size problem. When I initially tried to reproduce this with a smaller project it worked, when I added more code it failed. I put together a test project (it's in the issue referred to earlier webpack/webpack#6328) The project is https://github.com/richtera/webpack-project-for-debugging and will easily show the problem. |
Which version of the UglifyJsPlugin accepts the global_defs option? |
|
I added a branch to my test project. I am observing errors also happen with global_defs usage (at least using webpack and [email protected]) Curious, I see other people have success with this and it would make a lot of sense that it'd work. It's almost like something is minifying the code before it gets to either DefinePlugin or this UglifyPlugin and it already says something like e.env.NODE_ENV where e=process. This is not something either plugins will understand of course. I had previously tried to make "process" a variable that didn't get mangled and also had no success. |
The fact that Uglify will not perform the $ cat test.js
function f(process) {
console.log(process.env.NODE_ENV);
}
console.log(process.env.NODE_ENV); $ bin/uglifyjs test.js -d process.env.NODE_ENV='"production"' -b
function f(process) {
console.log(process.env.NODE_ENV);
}
console.log("production"); |
Yes, agreed, however the uglified code is: "production"!==t.env.NODE_ENV&&(r=function(e){if(void 0===e)throw new Error("invariant requires an error message argument")}),e.exports=n}).call(t,n(0))},
function(e,t,n){"use strict";function r(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)
} and the original source is: /**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
'use strict';
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var validateFormat = function validateFormat(format) {};
if (process.env.NODE_ENV !== 'production') {
validateFormat = function validateFormat(format) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
};
} Something is just not right. |
Could it be because webpackJsonp wraps files into a function causing "globals" to be "locals"? |
If that original source file is run through:
it produces: "use strict";var validateFormat=function(t){}; I'm not a webpack expert, but I think there's some configurable option related to global. Just a thought - is your bundle including node polyfills for |
Not on purpose if it does. All I include is babel-polyfill. |
You can see my failing setup in the sample project https://github.com/richtera/webpack-project-for-debugging and will easily show the problem. |
I didn't attempt to build the sample project but just looking at the Try having |
Both the Webpack https://webpack.js.org/plugins/define-plugin/ https://reactjs.org/docs/optimizing-performance.html#webpack |
For good measure have the webpack config disable the node polyfills for the browser: https://webpack.js.org/configuration/node/#other-node-core-libraries https://stackoverflow.com/questions/40467141/webpack2-node-libs-browser-exclude |
I set node: { process: false } or false and either helped. I have also tried various sequences of UglifyJsPlugin and DefinePlugin as well as various different versions of UglifyJsPlugin and other Minify plugins. I think it all hinges on a problem with the DefinePlugin. |
If not a node polyfill or a plugin ordering issue, I'm out of ideas as to what is changing |
You are correct though.... /* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var validateFormat = function validateFormat(format) {};
if (process.env.NODE_ENV !== 'production') {
validateFormat = function validateFormat(format) {
if (format === undefined) { Looks like the system will not work if any of the node_modules used are compiled using webpack since they will have an internal definition of process and therefore will destroy the build. |
It's truly a ridiculous situation. There must be a naïve webpack text replacement plugin or loader out there that does not pay attention to JS scope or grammar. |
On second thought, concentrate on removing the node polyfills. Something must be misconfigured. Once the polyfills are gone, the variable replacements will work. https://webpack.js.org/configuration/node/ |
Maybe I didn't explain this well enough. Both of the modules react-sparklines and react-loading contain the process polyfill in their main file. .
.
.
/******/ ([
/* 0 */
/***/ (function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
.
.
. Any file included after that one in the bundle will get process injected instead of keeping the global. |
I added a branch in the demo project called worksWithoutSparklinesLoading which will not contain any references to NODE_ENV in the output files. This is just by removing the import of those two modules. |
I see. Nice detective work. The And the |
Turns out of all the modules I am using those two are the only ones without node:false or other ways of building the output file. I posted two pull requested to fix those two modules.
You can install temporarily directly from github.
|
@richtera I think the other thread would be interested in your finding: webpack/webpack#6328 |
I also had this issue with my production bundles. I was getting the Code follows: ...
const babelEnvs = {
development: {
plugins: ['react-hot-loader/babel'],
},
};
if (isProd && isClient) {
babelEnvs.production = {
plugins: ['minify-dead-code-elimination'],
};
}
// more webpack options here...
//...
// still use uglify
plugins: [new UglifyJsPlugin({
uglifyOptions: {
ecma: 8,
compress: {
warnings: false,
},
},
sourceMap: false, // true,
})]
// but also use babel dce
{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader',
options: {
babelrc: false,
presets: ['es2015', 'react', 'stage-2'],
plugins: [
['relay'],
'universal-import'
],
env: babelEnvs,
},
}],
},
// ... |
I found that the configuration from an article of Slack's blog works for me. The only difference is that for uglifyjs-webpack-plugin@ |
Where exactly do I set this 'devtool: false'?? Asking because I have not yet ejected my react app and don't want to.... |
@amrita-syn in your webpack config object.
|
So, essentially, can't without ejecting? |
@amrita-syn I unfortunately have no experience with create-react-app so I do not know how this would impact your project. You need a way to override your webpack config in either case. |
Hi,
Thanks for your work on this library. I recently upgraded to the latest version of webpack and react and I'm now seeing the following in my console (in Production).
My webpack config looks kind of like this:
Thanks,
Michael
The text was updated successfully, but these errors were encountered: