Как хрюкать-обрезать несколько файлов script при сохранении структуры папок

Я не нашел хороший способ хрюкать - обрезать несколько файлов script, распространяемых по нескольким папкам, сохраняя при этом структуру папок, включая укрупненные файлы. Единственная причина, по которой я хочу это сделать, - увеличить производительность "старой" части веб-страницы, над которой я работаю.

Я нашел способ обойти это, чего я не хочу делать, поскольку это займет много времени, и это нужно сделать в этом ответе (они определяют каждую пару src и dest отдельно): как настроить файл grunt.js для минимального удаления файлов

Пример того, чего я хочу достичь:

**src dir (no uglify applied):**
src
 |- app1
    |- randomFile.js
    |- scripts
       |- file1.js
       |- file2.js
    |- libs
       |- file3.js
       |- file4.js
 |- app2
   |- scripts
       |- file1.js
       |- file2.js

**destination dir (uglify applied, same file name):**
dist
 |- app1
    |- randomFile.js
    |- scripts
       |- file1.js
       |- file2.js
    |- libs
       |- file3.js
       |- file4.js
 |- app2
    |- scripts
       |- file1.js
       |- file2.js

Btw, захотите сделать то же самое для CSS файлов, если это возможно.

Кто-нибудь знает, возможно ли это?

Ответ 1

Принцип в Rafa Heringer answer в сообщении, который вы связали с выглядит многообещающим, с небольшим завихрением:

uglify: {
    min: {
        files: grunt.file.expandMapping(['path/**/*.js', 'path2/**/*.js'], 'destination/', {
            rename: function(destBase, destPath) {
                return destBase+destPath.replace('.js', '.min.js');
            }
        })
    }
}

Единственная разница здесь - двойная звездочка между базовым путем и подстановочным именем файла с расширением. Это будет проходить через все подпапки и, надеюсь, выводить каждый найденный в его законной папке.

Вывод будет:

path/test.js => destination/path/test.min.js
path/subpath1/abc.js => destination/path/subpath1/abc.min.js
path/subpath2/yey.js => destination/path/subpath2/yey.min.js
path2/foo.js => destination/path2/foo.min.js

Когда дело доходит до того, чтобы сделать то же самое с CSS (используя плагин grunt-contrib-cssmin, упомянутый выше подход все равно будет работать, но вам нужно будет объединить его с соответствующими конфигурациями плагинов, которые должны быть на месте, чтобы вывести миниатюрный CSS так, как вы хотите.

PS: Не пробовал работать сам!

Ответ 2

Подобно ответу @DioNNiS, но хранит мини файлы в той же папке:

    uglify: {
        all: {
            files: [{
                expand: true,
                cwd: 'path/to/js/',
                src: ['*.js', '!*.min.js'],
                dest: 'path/to/js/',
                ext: '.min.js'
            }]
        }
    }

Ответ 3

На самом деле вы можете использовать следующий подход:

uglify: {
  all: {
    files: [{
      expand: true,
      cwd: 'js/',
      src: ['*.js', '**/*.js'],
      dest: 'js-min/',
      ext: '.min.js',
    }],
  },
}

Ответ 4

Ответ Уолласа замечательный, но если файлы, которые вы пытаетесь минимизировать, не существуют до начала grunt (т.е. если вы зависите от другой задачи), это не сработает, потому что карта создается перед любой задачей выполняется.

Я придумал решение для минимизации сгенерированных файлов по отдельности, используя пакет node uglify-js вместо grunt-contrib-uglify.

  • Добавьте uglify-js в свой пакет package.json
  • Добавьте один из следующих примеров в свой файл Grunfile (просто замените "ВАШИ ФАЙЛЫ ЗДЕСЬ" соответствующими глобусами, если вы используете пример 1).
  • Если вам нужно изменить миниатюрный файл назначения или расширение, используйте вместо этого пример 2. Он использует grunt.file.recurse с обратным вызовом, который предоставляет вам корневой каталог, подкаталог и имя файла для каждого файла (проще создать собственный путь назначения). Замените "FOLDER" на каталог, который вы хотите отсканировать, и создайте свой собственный "CUSTOM PATH HERE".

Пример 1: С grunt.file.expand

grunt.registerTask('uglifyFiles', 'Uglifies files', function () {
    var jsp = require("uglify-js").parser,
        pro = require("uglify-js").uglify,
        count = 0;

    grunt.file.expand(['YOUR FILES HERE']).forEach(function (abspath) {
        // Exclude already minified files (with extension .min.js)
        if (!abspath.match(/\.min\.js$/i)) {
            // Get Abstract Syntax Tree
            var ast = jsp.parse(grunt.file.read(abspath));
            // If mangling
            // ast = pro.ast_mangle(ast);
            // If squeezing
            ast = pro.ast_squeeze(ast);
            // Write new file
            grunt.file.write(abspath.replace(/\.js$/i, '.min.js'), pro.gen_code(ast));
            count += 1;
        }
    });

    grunt.log.oklns("Successfully uglified " + count + " files");
});

Пример 2: С grunt.file.recurse

grunt.registerTask('uglifyFiles', 'Uglifies files', function () {
    var jsp = require("uglify-js").parser,
        pro = require("uglify-js").uglify,
        count = 0;

    grunt.file.recurse('FOLDER', function callback(abspath, rootdir, subdir, filename) {
        // Exclude already minified files (with extension .min.js)
        if (!abspath.match(/\.min\.js$/i)) {
            // Get Abstract Syntax Tree
            var ast = jsp.parse(grunt.file.read(abspath));
            // If mangling
            // ast = pro.ast_mangle(ast);
            // If squeezing
            ast = pro.ast_squeeze(ast);
            // Write new file, using abspath or rootdir, subdir and filename
            grunt.file.write('CUSTOM PATH HERE', pro.gen_code(ast));
            count += 1;
        }
    });

    grunt.log.oklns("Successfully uglified " + count + " files");
});

Ответ 5

Это решение не работает для меня.

Это рабочий пример:

        path: {
            build: {
               src: 'assets',
               js: 'js',
               css: 'css'
            },
            js: 'js',
            css: 'css'
        },
        uglify: {
            scripts: {
                expand: true,
                cwd: '<%= path.js %>/',
                src: [
                    '**/*.js', 
                    '*.js',
                    //skip minified scripts
                    '**/!*.min.js', 
                    '!*.min.js'
                ],
                dest: '<%= path.build.src %>/<%= path.build.js %>/',
                rename: function (destBase, destPath) {
                    return destBase + destPath.replace('.js', '.min.js');
                }
            }
        },
        //same options for css minify
        cssmin: {
            styles: {
                expand: true,
                cwd: '<%= path.css %>/',
                src: [
                    '**/*.css',
                    '*.css',
                    //skip minified styles
                    '**/!*.min.css', 
                    '!*.min.css'
                ],
                dest: '<%= path.build.src %>/<%= path.build.css %>/',
                rename: function (destBase, destPath) {
                    return destBase + destPath.replace('.css', '.min.css');
                }
            }
        },
        //and watch it for changes
        watch: {
            js: {
                files: [
                    '<%= path.js %>/*.js',
                    '<%= path.js %>/**/*.js'
                ],
                tasks: [
                    'uglify:scripts'
                ],
                options: {
                    livereload: true
                }
            },
            css: {
                files: [
                    '<%= path.css %>/*.css',
                    '<%= path.css %>/**/*.css'
                ],
                tasks: [
                    'cssmin:styles'
                ],
                options: {
                    livereload: true
                }
            }
        }