1

I want to uglify all the .js files in a directory using grunt. But the problem is, there are folders ending in .js. I believe grunt-uglify is not able to distinguish between the folder ending in .js. Also, there are .js files in .js folder. Can someone tell me what to do? I am very new to this

My Project structure ->

MyProject/app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/FileSaver.js

where FileSaver.js is a folder which contains .js files. It is failing at FileSaver.js

Package.json

{
  "name": "App",
  "description": "App",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
  "express": "3.x",
  "grunt-contrib-copy": "^1.0.0"
},
 "devDependencies": {
   "grunt": "^0.4.5",
   "grunt-cli": "^1.2.0",
   "grunt-contrib-clean": "^1.1.0",
   "grunt-contrib-copy": "^1.0.0",
   "grunt-contrib-jshint": "^1.1.0",
   "grunt-contrib-requirejs": "~0.4.1",
   "grunt-contrib-symlink": "^1.0.0",
   "grunt-contrib-uglify": "^2.3.0",
   "grunt-contrib-watch": "^1.0.0",
   "grunt-exec": "^3.0.0",
   "grunt-git": "^0.3.7",
   "grunt-text-replace": "^0.4.0",
   "jasmine-core": "^2.8.0"
  },
  "scripts": {
    "test": "grunt travis --verbose"
 }
  }

My GruntFile.js

module.exports = function (grunt) {

grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),
    uglify :{
        files :{
            'build/dest.js': 'app/*.js'
        }
    }

});
  grunt.loadNpmTasks('grunt-contrib-uglify');

};

Rob
  • 14,746
  • 28
  • 47
  • 65
chan
  • 274
  • 1
  • 5
  • 24
  • 1
    Well, `app/*.js` matches anything that ends in `.js` (also, please use the search before you ask a new question). – Felix Kling Sep 20 '17 at 01:21
  • 1
    You probably shouldn't have folders who's names end with `.js`; its confusing convention. Instead, try using a hyphen or nesting folders (`dest.js` becomes `dest-js` or `dest/js`) – treyhakanson Sep 20 '17 at 01:23
  • 1
    First of all it's better to avoid .js for folder names. It's not the best practice. Just try adding 'app/**/*.js'. But I'm not sure this will work. But give it a try. – Thusitha Sep 20 '17 at 01:26
  • @FelixKling The question you are referring to involves ignoring such folders. I am trying to access that folder which contains the actual .js file – chan Sep 20 '17 at 03:41
  • Whoops, ok..... – Felix Kling Sep 20 '17 at 04:09

1 Answers1

0

Firstly, (as noted in the comments), naming folders with a .js suffix is bad practice. You really need to change your projects folder nomenclature if you can. However, if that's not feasible, it is possible to get grunt-contrib-uglify to ignore folders whose name ends in .js.

This entails dynamically generating the configuration object for the uglify Task via the use of a custom helper function (namely configureUglify in the example gist below). The resultant configuration will be very similar to this example shown in the uglify documentation, whereby each .js file is defined in an Array. The main difference being is that instead of manually defining each filepath we dynamically generate it instead.


Gruntfile.js

module.exports = function (grunt) {

  grunt.initConfig({
    uglify : {
      // <--  // Intentionally empty, will be auto generated.
    }
  });

  /**
   * Helper function creates config object for uglify Task.
   */
  function configureUglify() {
    var glob = 'app/**/*.js',
      config = {},
      jsFiles = [];

    grunt.file.expand({ filter: 'isFile' }, glob).forEach(function (filePath) {
      jsFiles.push(filePath)
    });

    config.target = {
      files : {
        'build/dest.js' : jsFiles
      }
    }

    grunt.config('uglify', config);
    grunt.task.run(['uglify']);
  }

  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.registerTask('uglifyJs', configureUglify);
  grunt.registerTask('default', ['uglifyJs']);
};

Notes

  1. The configureUglify helper function (above) utilizes grunt.file.expand to iterate over each path found via the glob pattern 'app/**/*.js'.

  2. The { filter: 'isFile' } part ensures that only paths to files ending in .js are processed (i.e. The folder FileSaver.js or any other folder whose name ends in .js are simply ignored ).

  3. The globbing pattern 'app/**/*.js' will find all .js files stored in the app directory, including any found in sub-folders. If you want to uglify only the files stored in folder named FileSaver.js then change the glob pattern to:

var glob = 'app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/FileSaver.js/**/*.js'
  1. Running $ grunt via your commandline using the Gruntfile.js example gist provided will result in a single file named dest.js saved to the build folder/directory.

Important

When combining multiple files into one single .js file (e.g. dest.js) the order in which the files are combined is often important to ensure the application functions correctly. So you may find that explicitly defining the paths Array in your Gruntfile.js, (instead of dynamically as above, which does not guarantee the correct order), better achieves your requirements. For example:

grunt.initConfig({
  uglify: {
    my_target: {
      files: {
        'build/dest.js': [
           'app/assets/lib/foo.js',
           'app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/baz.js',
           'app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/FileSaver.js/a.js',
           'app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/FileSaver.js/b.js',
           'app/assets/lib/amcharts/dist/amcharts/plugins/export/libs/FileSaver.js/c.js'
        ]
      }
    }
  }
});

Also, typically the single resultant uglified/minified .js file is named with a .min.js suffix - this is just general good practice. So you may want to consider changing 'build/dest.js' to 'build/dest.min.js'

RobC
  • 22,977
  • 20
  • 73
  • 80
  • When I run the grunt command, I am getting this error -> app/shared/api.service.js failed. Warning: Uglification failed. Unexpected token: name (nodeResolve). – chan Sep 20 '17 at 17:41
  • My guess is that the file is written in ES6 and probably `imports` a [ES6 class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). However, `grunt-contrib-uglify` (`master`) handles ES5 only. The [harmony](https://github.com/gruntjs/grunt-contrib-uglify/tree/harmony) branch supports ES6+. Which version of JavaScript does your project utilize? Also please note that this issue has nothing to do with your original post; "_uglify not able to distinguish between folder and file ending in .js_", which my answer provides a solution to. – RobC Sep 21 '17 at 14:24
  • See this [issue](https://github.com/gruntjs/grunt-contrib-uglify/issues/491) in the `grunt-contrib-uglify` github repo for further info on how to install the harmony version.... `npm install git://github.com/gruntjs/grunt-contrib-uglify.git#harmony --save-dev` – RobC Sep 21 '17 at 14:35