51

I'm using UglifyJS to minify my JavaScript files. It's working well with one file at a time. What I'm looking for is to minify all the JavaScript files present in a folder called JS into a folder called JSM.

To be clear, I have two files inside my JS folder called test1.js and test2.js, and I want to run uglify_ against that folder and generate files 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.

0

10 Answers 10

95

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 Node.js

  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 file in the root of your project (it's a kind of configuration 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, and Stylus), JSHint, etc.

Sign up to request clarification or add additional context in comments.

14 Comments

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
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.
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
you can do better - with masks, you can uglify all files into one: uglify: { tests: { src: [ 'js/*.js' ], dest: 'jsm/tests.min.js' } },
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!
|
24

If you're on Linux or Mac and have access to Bash, you can use UglifyJS on multiple JavaScript files like so:

rm *.min.js; for f in *.js; do short=${f%.js}; uglifyjs $f > $short.min.js; done

2 Comments

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?
My solution run over any path recursively and uses terser as a replacement to uglifyjs because it doesn't support ES6+ stackoverflow.com/a/65232798/2015609
18

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
    

1 Comment

Any idea how to achieve this: source/js/desktop/file1.js, file2.js... source/js/mobile/file1.js, file2.js... and to output: output/js/desktop.min.js output/js/mobile.min.js So, files in source directories should be compiled in one file with directory name.
8

Further to Calpau's 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'

Comments

4

UglifyJS does not support ES6 (or later), so I suggest to use terser (to install it, run npm install terser -g). Below is 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

1 Comment

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
3

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'
            }]
        }
    }

2 Comments

This does not handle sub-folders? What should the "dest" be so that "app/app.js" and "mod/mod1.js" end up in "dest/app/app.min.js" and "dest/mod/mod1.min.js"?
same issue, this skips sub folders.
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

Comments

0

You can use this npm module package:

 npm i uglify-js-minify-css-allfiles
 npm i uglify-js clean-css
// Making the 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

Comments

0

Using UglifyJS with PowerShell on Windows:

Use PowerShell to iterate over all .js files in a directory (including child folders if -recurse is supplied) and call the UglifyJS command for each one.

Be aware that this code will overwrite the original files with the uglified version. If you don't needed this, change the parameters for the UglifyJS command.

Get-ChildItem "some directory path" -Recurse -Filter *.js |
Foreach-Object {
    echo $_.FullName
    uglifyjs $_.FullName -o $_.FullName
}

Comments

0

Using a Bash script worked for me. You could use different commands or flags instead of uglifyjs "$file" -o "${file%.js}.min.js" -c -m.

To minify all .js files in your current directory as well as in all the subdirectories (note: it doesn't have any depth limit, so how much deeply nested subdirectories you have, it would work on every .js file).

for file in $(find * -type f -iname "*.js"); do
    uglifyjs "$file" -o "${file%.js}.min.js" -c -m
done

Expected result: It will create minified .min.js files of every .js file inside your current directory, as well as in all the subdirectories.

Warning: It will loop through all the directories and subdirectories. To limit subdirectory depth, add -maxdepth <depth_limit_number>. For example, the first line could look like this, for file in $(find * -type f -iname "*.js" -maxdepth 3); do, to limit find for three subdirectories from your current directory. Use it at your own risk.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.