Danack
Danack

Reputation: 25701

Webpack UglifyJsPlugin not minifying code

I'm trying to get Webpack to minify my Javascript code when it's being run through Yarn. I believe I've got everything setup correctly, however the Javascript just isn't being minified.

I've built a docker box to reproduce this problem: https://github.com/Danack/ReactTest (which probably doesn't work on Windows)

I've tested that the Uglify code is working my minifying a test file by manually calling Uglify.minify(), and it is.

This is my Webpack config file:

var webpack = require("webpack");
var path = require("path");

// This is just to test whether uglify is working.
var UglifyJS = require('uglify-js');
var fs = require('fs');
var result = UglifyJS.minify('./src/compress_test.js', {
  mangle: true,
  compress: {
    sequences: true,
    dead_code: true,
    conditionals: true,
    booleans: true,
    unused: true,
    if_return: true,
    join_vars: true,
    drop_console: true
  }
});
fs.writeFileSync('./uglify_test/manual.min.js', result.code);

module.exports = {

  entry: "./src/compress_test.js",
  devtool: "source-map",

  output: {
    path: path.resolve('./uglify_test'),
    filename: "[name].js"
  },

  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      mangle: true,
      compress: {
        sequences: true,
        dead_code: true,
        conditionals: true,
        booleans: true,
        unused: true,
        if_return: true,
        join_vars: true,
        drop_console: true
      }
    })
  ]
};

To build project webpack -d --colors --watch --config ./webpack.config.js or npm run dev:build

I setup a simple Javascript file that has long variable names to make it easy to see if the JS is being minified or no.

// compress_test.js
function really_long_test_function_name(some_really_long_param_name_1, some_really_long_param_name_2) {


  var foo_really_long_var_name_1 = some_really_long_param_name_1 + "asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";
  var foo_really_long_var_name_2 = some_really_long_param_name_2 + "asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";

  var foo_really_long_var_name_3 = foo_really_long_var_name_1 + foo_really_long_var_name_2;
  var foo_really_long_var_name_4 = foo_really_long_var_name_1 + foo_really_long_var_name_3;
  var foo_really_long_var_name_5 = foo_really_long_var_name_1 + foo_really_long_var_name_4;
  var foo_really_long_var_name_6 = foo_really_long_var_name_1 + foo_really_long_var_name_5;
  var foo_really_long_var_name_7 = foo_really_long_var_name_1 + foo_really_long_var_name_6;
  var foo_really_long_var_name_8 = foo_really_long_var_name_1 + foo_really_long_var_name_7;
  var foo_really_long_var_name_9 = foo_really_long_var_name_1 + foo_really_long_var_name_8;


  return foo_really_long_var_name_9.length;
}

The javascript produced by calling Uglify manually, is nicely minified.

// manual.min.js
function really_long_test_function_name(a,p){var d=a+"asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";return(d+(d+(d+(d+(d+(d+(d+(p+"asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd")))))))).length}

The built javascript output of Webpack isn't:

!function(l){function _(n){if(a[n])return a[n].exports;var o=a[n]={i:n,l:!1,exports:{}};return l[n].call(o.exports,o,o.exports,_),o.l=!0,o.exports}var a={};_.m=l,_.c=a,_.i=function(l){return l},_.d=function(l,a,n){_.o(l,a)||Object.defineProperty(l,a,{configurable:!1,enumerable:!0,get:n})},_.n=function(l){var a=l&&l.__esModule?function(){return l.default}:function(){return l};return _.d(a,"a",a),a},_.o=function(l,_){return Object.prototype.hasOwnProperty.call(l,_)},_.p="",_(_.s=0)}([/*!******************************!*\
  !*** ./src/compress_test.js ***!
  \******************************/
function(module,exports){eval('\n\nfunction really_long_test_function_name(some_really_long_param_name_1, some_really_long_param_name_2) {\n\n\n  var foo_really_long_var_name_1 = some_really_long_param_name_1 + "asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";\n  var foo_really_long_var_name_2 = some_really_long_param_name_2 + "asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";\n\n  var foo_really_long_var_name_3 = foo_really_long_var_name_1 + foo_really_long_var_name_2;\n  var foo_really_long_var_name_4 = foo_really_long_var_name_1 + foo_really_long_var_name_3;\n  var foo_really_long_var_name_5 = foo_really_long_var_name_1 + foo_really_long_var_name_4;\n  var foo_really_long_var_name_6 = foo_really_long_var_name_1 + foo_really_long_var_name_5;\n  var foo_really_long_var_name_7 = foo_really_long_var_name_1 + foo_really_long_var_name_6;\n  var foo_really_long_var_name_8 = foo_really_long_var_name_1 + foo_really_long_var_name_7;\n  var foo_really_long_var_name_9 = foo_really_long_var_name_1 + foo_really_long_var_name_8;\n\n\n  return foo_really_long_var_name_9.length;\n}\n\n\n\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjoz **** SOURCE_MAPPING_NOT_SHOWN_HERE***')}]);

The long variable names are still there.

What do I need to do to make webpack actually minify the Javascript that it outputs?

In case it matters, I'm using Yarn 0.23.4 and Node 7.10.0

Upvotes: 0

Views: 12039

Answers (5)

prasanth shenoy
prasanth shenoy

Reputation: 235

if you are using the newer version of uglifyjs-webpack-plugin then you can use the code plugin setting like below and it should be working . there are a couple of minor changes here with respect to the uglify options :

new UglifyJsPlugin({ 
            uglifyOptions: {
                mangle: true,
                output: {
                    comments: false
                }
            },
            sourceMap: true,
            exclude: [/\.min\.js$/gi]
       })

Upvotes: 1

Kirill Matrosov
Kirill Matrosov

Reputation: 5990

You use -d. It is shortcut for --debug --devtool eval-cheap-module-source-map --output-pathinfo

This part --devtool eval-cheap-module-source-map rewrites your devtool in config and leave

original source (lines only)

Upvotes: 3

Preview
Preview

Reputation: 35796

It looks like you are trying to use uglify with the watch flag, which is intended to be used in development.

As you can see, it's wrapping your code in an eval statement and multiple wrappers that is messing with the uglification process. I also suspects it might purposely keeps the source unmangled for debugging purposes.

From your Dockerfile, you're running this command from your package, that makes me think that you are trying to use webpack as both your bundler and file server on production, which is not what it should be used for.

By taking your exact configuration and files, I had no problem generating the output minified file by simply declaring a script that look like:

"prod:build": "webpack"

Since you have dead_code: true and drop_console: true, you might have to set these to false with your current code, since the method is never called, what I did is call it with console.log and set drop_console to false

console.log(really_long_test_function_name('a', 'b'))

The result of the build will look like

!function(o){function n(t){if(r[t])return r[t].exports;var e=r[t]={i:t,l:!1,exports:{}};return o[t].call(e.exports,e,e.exports,n),e.l=!0,e.exports}var r={};n.m=o,n.c=r,n.i=function(o){return o},n.d=function(o,r,t){n.o(o,r)||Object.defineProperty(o,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(o){var r=o&&o.__esModule?function(){return o.default}:function(){return o};return n.d(r,"a",r),r},n.o=function(o,n){return Object.prototype.hasOwnProperty.call(o,n)},n.p="",n(n.s=0)}([function(o,n){console.log(function(o,n){var r=o+"asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd";return(r+(r+(r+(r+(r+(r+(r+(n+"asdjpajdpoadpsapodjpasojdpoajpdoaspdpasjd")))))))).length}("a","b"))}]);%

Running the webpack binary will take the webpack.config.js automatically. Also, don't need to specify mangle: true for the plugin, as it is already the default value.


To resume, do the normal production build with minification without the -watch option, and install something like nginx in your docker to serve your files in production.

Upvotes: 0

user2098856
user2098856

Reputation: 34

You don't need to manually include uglifyjs as it comes bundled with webpack.

You should only really need to minify when building for production, the minification will be applied automatically when you run webpack in production mode, i.e.:

webpack -p

or

webpack --optimize-minimize --define process.env.NODE_ENV="'production'"

For more details, checkout this website: https://webpack.js.org/guides/production-build/

Upvotes: 0

therebelcoder
therebelcoder

Reputation: 1018

In your code where you call the options, add:

new webpack.optimize.UglifyJsPlugin({
      mangle: true, { keep_fnames: false, screw_ie8: true },
      compress: true, { keep_fnames: false, screw_ie8: true }
})

I do not know the options you're trying to set? Are you sure they are webpack uglify options? Anyway, hope this helps.

EDIT:

Try this:

const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');

Check if that lib is in that directory to be sure.

new UglifyJsPlugin({
        beautify: false,
        comments: false,
        ...
      }),

This will call upon your the original Uglify plugin more directly... Try your previous set options on this.

Upvotes: -1

Related Questions