Search code examples
gulprequirejsrequirejs-optimizer

RequireJS: Uglification Not Working


I must be making a mistake somewhere, but it's not being written to stdout during optimization. I'm trying to optimize a file via requirejs, but the output isn't being minified. According to the documentation, UglifyJS should minify the code.

At any rate, the following code is trivial, but it isolates the problem.

src/index.js:

require(['config'], function () {
    require(['myMod'], function (myMod) {
        console.log(myMod.x());
    })
})

src/myMod.js:

define(function () {
    let myMod = {
        x: 5
    };

    return myMod;
})

src/config.js:

define(function () {
    require.config({
        baseUrl: 'src'
    });
})

And here's the gulp task that is performing the optimization:

gulp.task('optimize', function (cb) {
    let config = {
        appDir: 'src',
        dir: 'dist/src',
        generateSourceMaps: true,
        preserveLicenseComments: false,
        removeCombined: true,
        baseUrl: './',
        modules: [{
            name: 'index',
            include: ['myMod']
        }]
    }

    let success = function (buildResponse) { console.log(buildResponse); cb() },
        error = function (err) { console.log(err); cb(err) }

    rjs.optimize(config, success, error)
})

After running the task, dist/src/index.js has all of the other modules included in it. However, it's not minified, and none of the variables have been renamed. Instead, it's as if the files were just concatenated, nothing more. Could someone tell me (1) why is it not being minified? (2) is UglifyJS throwing an error? If so, is there a way to see it when the gulp task is being run?

EDIT Here's a link to RequireJS docs where it talks about using the optimizer in node, which is done in the gulp task mentioned above. It's at the bottom under "Using the optimizer as a node module".

http://requirejs.org/docs/node.html


Solution

  • RequireJS' optimizer bundles UglifyJS2. UglifyJS2 does not handle ES6 or higher. If I take the options you use in your gulpfile, and plunk them into a separate file that I name options.js, and issue this command:

    $ ./node_modules/.bin/r.js -o options.js
    

    Then I get this output:

    Tracing dependencies for: index
    Uglify file: /tmp/t33/dist/src/index.js
    Error: Cannot uglify file: /tmp/t33/dist/src/index.js. Skipping it. Error is:
    SyntaxError: Unexpected token: name (myMod)
    
    If the source uses ES2015 or later syntax, please pass "optimize: 'none'" to r.js and use an ES2015+ compatible minifier after running r.js. The included UglifyJS only understands ES5 or earlier syntax.
    
    index.js
    ----------------
    config.js
    index.js
    myMod.js
    

    As you can see, UglifyJS does fail to minify your file, and RequireJS just skips the minification step for that file. Since this is not an outright error, the file is still output, just not minified.

    If you change let to var in myMod.js, then the issue disappears.

    Unfortunately, since this is not an execution failure (r.js still runs, it just does not minify the file), the error is not signaled to the errback handler you pass to rjs.optimize. I don't see a way to catch such error in a Gulpfile. The safe thing to do is to set optimize: "none" and perform the minification as an additional build step after running rjs.optimize.