46

Hello I'm using uglifyJs to minify my javascript files, it's working well with one file at a time, what I'm loking for is to minify all the javascript files present in a folder called JS into a folder called JSM, to be clear I have 2 files inside my JS folder called test1.js and test2.js and I want to run uglify against that folder and generate test1.min.js and test2.min.js inside the JSM folder, so is there a way to do this? a command like :

uglifyjs -c -m JS/*.js JSM/*.min.js

Or any idea that can help me.

Thanks.

raina77ow
  • 91,589
  • 12
  • 180
  • 210
OussamaLord
  • 997
  • 4
  • 25
  • 39

8 Answers8

91

I know it might seem like a huge step but I would really recommend using grunt. It's really simple once you get the hang of it.

Here's a crash course:

  1. Install NodeJS
  2. Install Grunt CLI (just enter this in console/terminal):

    npm install -g grunt-cli
    
  3. Create a simple package.json file in the root of your project:

    {
      "name": "my-project-name",
      "version": "1.0.0",
      "devDependencies": {
        "grunt": "~0.4.2",
        "grunt-contrib-uglify": "~0.2.4",
        "grunt-contrib-watch" : "~0.5.3"
      }
    }
    
  4. Once you have that, just type: npm install to the console (in the root of your project). This will install the necessary grunt plugins/dependencies (from the package file above).

  5. Now create a simple gruntfile.js in the root of your project (it's a kind of config for your project):

    module.exports = function (grunt) {
        grunt.initConfig({
    
    
        // define source files and their destinations
        uglify: {
            files: { 
                src: 'js/*.js',  // source files mask
                dest: 'jsm/',    // destination folder
                expand: true,    // allow dynamic building
                flatten: true,   // remove all unnecessary nesting
                ext: '.min.js'   // replace .js to .min.js
            }
        },
        watch: {
            js:  { files: 'js/*.js', tasks: [ 'uglify' ] },
        }
    });
    
    // load plugins
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    
    // register at least this one task
    grunt.registerTask('default', [ 'uglify' ]);
    
    };
  6. Once that's done you just need to build it. Type in the console:

    grunt
    

    or - better - if you type execute the command below - grunt will monitor your source files for changes, and if you change any of them - it will build them automatically:

    grunt watch --force
    

You can then add more plugins, like: css minification, css preprocessors (less, sass, stylus), jshint, etc.

Dziad Borowy
  • 11,740
  • 4
  • 37
  • 51
  • 1
    Hi, thanks for you help but I do not see how this will work or solve my issue, I did all the steps and I get this :Running "watch" task waiting... ,I had to modify the code in "gruntfile.js" you have some errors in your code. I just want something to run at on time that can do what I want (as described above), thanks – OussamaLord Jun 09 '13 at 14:00
  • Hi. Sorry for errors (lots of copy&paste). If you can see the "Running watch task..." that's great! just save your js file and grunt should build that. Or just use `grunt` command to build files once. – Dziad Borowy Jun 09 '13 at 17:40
  • Hi, sorry this is the new message I get, nothing is created in my jsm folder: `C:\npm>grunt --force Running "uglify:file1" (uglify) task Warning: Uglification failed. Used --force, continuing. Warning: Cannot read property 'min' of undefined Used --force, continuing. Running "uglify:my_plugins" (uglify) task Warning: Uglification failed. Used --force, continuing. Warning: Cannot read property 'min' of undefined Used --force, continuing. Done, but with warnings` – OussamaLord Jun 09 '13 at 18:22
  • Hi. Just make sure that the file structure in gruntfile.js represents what you have, e.g. do you have file1.js in your js folder? As for my_plugins node - you can remove this. I only added this to show you what you could do... – Dziad Borowy Jun 09 '13 at 18:49
  • I updated the `gruntfile.js` in my response to reflect your file structure. – Dziad Borowy Jun 09 '13 at 18:50
  • Hi, sorry to boder you again but everything seems working I have `test1.js` in my `js` folder a `jsm` folder empty and the `gruntfile.js` with these changes : `.... uglify: {test1: { src: [ 'js/test1.js' ],dest: 'jsm/test1.min.js'}},watch: { js: { files: 'js/**/*.js', tasks: [ 'uglify' ] },} ...` Now I get : `Running "watch" task Waiting...` but nothing is created in jsm folder, what am I doing wrong? – OussamaLord Jun 09 '13 at 19:57
  • if you run `grunt watch` - that will watch for changes in files, and if you do not change anything - nothing will happen. If you want to uglify your files "now" - use just `grunt` (without watch) – Dziad Borowy Jun 09 '13 at 22:20
  • Hi, AWWWESOOME, thanks this is working , however this will not solve my issue, I see that I have to specify myself the files names in `gruntfile.js` `uglify: { test1: { src: [ 'js/test1.js' ], dest: 'jsm/test1.min.js' }.....` so what I wanted to do is uglifying all the content (files) inside `JS` folder without having to put the names of the files to uglify in the `gruntfile.js` file. Anyway thanks again. – OussamaLord Jun 09 '13 at 23:28
  • 7
    you can do better - with masks, you can uglify all files into one: `uglify: { tests: { src: [ 'js/*.js' ], dest: 'jsm/tests.min.js' } },` – Dziad Borowy Jun 10 '13 at 06:56
  • Hi, thanks a lot you are really awesome with `grunt`, we are close to end this topic, you were right it is uglifying all the files in `JS` folder into one file inside `JSM` folder, so what is the mask to uglify each file in `JS` folder in a separate file `*.min.js` inside JSM folder? and yes I know I asked you a lot of questions so Sorry this is the last one I will ask ;). – OussamaLord Jun 10 '13 at 09:07
  • Hi @OussamaLord, I updated my answer (and added comments) to do exactly what you want (I hope). I've also tested this and it now compiles each file separately. – Dziad Borowy Jun 10 '13 at 10:16
  • HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH, I don't know how to thank you, you are awesome, now it's doing exactly what I want, thank you so much, so this topic is closed now. Show me how can I leave feedback for you, you deserve it after all ;) – OussamaLord Jun 10 '13 at 10:28
  • 1
    You can mark my answer as "answer" (to close the topic) and click the up arrow next to it :-) And I'm happy to help! – Dziad Borowy Jun 10 '13 at 10:43
  • Don't we need a clean up first??? I think mine is going out of controller, and appending the script at the end of the min file... getting too large... – Val May 19 '14 at 15:55
21

If you're on Linux/Mac and have access to bash, you can use uglifyjs on multiple JS files like so:

rm *.min.js; for f in *.js; do short=${f%.js}; uglifyjs $f > $short.min.js; done
mmorrey
  • 103
  • 1
  • 5
Calpau
  • 841
  • 7
  • 19
  • 3
    How would you recursively go through a scripts folder? I have a javascripts folder, with directories inside of it like polyfills and libraries. Is there a way to run the for loop only recursively through the nested directories? – Costa Mar 31 '17 at 21:08
  • My solution run over any path recursively and uses `terser` as a replacement to `uglifyjs` because it doesn't support ES6+ https://stackoverflow.com/a/65232798/2015609 – mbnoimi Dec 10 '20 at 10:33
9

npm-only way:

  1. run:

    npm install uglifyjs-folder --save-dev
    
  2. and afterwards add to your package.json something like:

    "uglifyjs": "uglifyjs-folder js -eo jsm"
    
  3. then run:

     npm run uglifyjs
    

Please note, if you'd need to generate to the same folder as the source files are (js), following should do the job:

  1. run:

    npm install del-cli uglifyjs-folder --save-dev
    
  2. and afterwards add to your package.json something like:

    "uglifyjs": "del js/*.min.js; uglifyjs-folder js -eo js"
    
  3. then run:

     npm run uglifyjs
    
Peter Butkovic
  • 8,499
  • 10
  • 50
  • 71
8

Further to the above answer, I now have this set up in my .bashrc file:

alias minify='rm *.min.js; for f in *.js; do short=${f%.js}; uglifyjs $f > $short.min.js; done'
mmorrey
  • 103
  • 1
  • 5
2

You can use this configuration in gruntfile.js:

uglify: {
        all: {
            files: [{
                expand: true,
                cwd: '<path to js folder>',
                src: ['**/*.js', '!*.min.js'],
                dest: '<path to js folder>',
                ext: '.js'
            }]
        }
    }
Kop4lyf
  • 4,192
  • 1
  • 22
  • 30
1

uglify-js does not support ES6+ so I suggest to use terser (to install it run npm install terser -g) Below a shell script executing terser recursively for any path:

terser_path.sh

#!/bin/bash

####
# Tiny shell script for terser any JavaScript project
# usage:
# ./terser_path <path_to_your_project>
####

path="$1"

find $path -name '*.js' -type f | while read f
do
    folderpath=$(dirname "$f")
    filename=$(basename "$f") 
    extension="${filename##*.}"
    filename="${filename%.*}"
    nf=$folderpath/$filename.min.$extension

# ----- METHOD 1 : Replace the old file
#    terser "$f" --output "$f" --compress --mangle
# ----- METHOD 2 : Create .min.js file
    terser "$f" --output "$nf" --compress --mangle
     
done
mbnoimi
  • 374
  • 3
  • 19
  • This is great! I ran into an issue, however, where the function names are not being mangled. I tried adding --module to the the CLI command to tell it I'm using ES6 modules, which should also automatically enable --keep-fnames=false, but it still doesn't work for me. Adding `--keep-fnames=false` causes an error – I Stand With Israel Mar 02 '21 at 09:15
0

make a bat file with start at each row beginning

start uglifyjs app\main.js -mt sort -c -e -o app\main.ug.js
start uglifyjs app\lib.js -mt sort -c -e -r myfunctionname -o app\lib.ug.js
start uglifyjs app\controllers\bbbCtrl.js -mt sort -c  -o     app\controllers\bbbCtrl.ug.js
start uglifyjs app\controllers\aaaCtrl.js -mt sort -c -e -o app\controllers\aaaCtrl.ug.js
Fabio
  • 11
  • 3
0

you can use this npm module package

 npm i uglify-js-minify-css-allfiles
 npm i uglify-js clean-css
// making index.js file
const minifyAll = require('uglify-js-minify-css-allfiles');

// Folder Name (you will change all files in Folders)
minifyAll('../test/');

npm package site