Почему рекомендуется использовать concat, а затем uglify, когда последний может делать оба?

Я продолжаю видеть рекомендацию о том, чтобы JS-файлы были готовы к производству, а затем uglify.

здесь, в одной из задач Йомена.

по умолчанию поток: concat - > uglifyjs.

учитывая, что UglifyJS может выполнять как конкатенацию, так и минификацию, зачем вам когда-либо понадобятся оба одновременно?

спасибо.

2 ответов


запуск базового теста, чтобы увидеть, есть ли разница в производительности между выполнением concat а то uglify и просто uglify.

пакета.в JSON

{
  "name": "grunt-concat-vs-uglify",
  "version": "0.0.1",
  "description": "A basic test to see if we can ditch concat and use only uglify for JS files.",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "^0.5.0",
    "grunt-contrib-uglify": "^0.6.0",
    "load-grunt-tasks": "^1.0.0",
    "time-grunt": "^1.0.0"
  }
}

Gruntfile.js

module.exports = function (grunt) {

    // Display the elapsed execution time of grunt tasks
    require('time-grunt')(grunt);
    // Load all grunt-* packages from package.json
    require('load-grunt-tasks')(grunt);

    grunt.initConfig({
        paths: {
            src: {
                js: 'src/**/*.js'
            },
            dest: {
                js: 'dist/main.js',
                jsMin: 'dist/main.min.js'
            }
        },
        concat: {
            js: {
                options: {
                    separator: ';'
                },
                src: '<%= paths.src.js %>',
                dest: '<%= paths.dest.js %>'
            }
        },
        uglify: {
            options: {
                compress: true,
                mangle: true,
                sourceMap: true
            },
            target: {
                src: '<%= paths.src.js %>',
                dest: '<%= paths.dest.jsMin %>'
            }
        }
    });

    grunt.registerTask('default', 'concat vs. uglify', function (concat) {
        // grunt default:true
        if (concat) {
            // Update the uglify dest to be the result of concat
            var dest = grunt.config('concat.js.dest');
            grunt.config('uglify.target.src', dest);

            grunt.task.run('concat');
        }

        // grunt default
        grunt.task.run('uglify');
    });
};

на src, Я поместил кучу JS-файлов, включая несжатый источник jQuery, скопированный несколько раз, разбросанный по подпапкам. Гораздо больше, чем обычно имеет обычный сайт/приложение.

получается время, необходимое для объединения и сжатия всех этих файлов, по существу одинаково в обоих сценариях.
за исключением при использовании sourceMap: true опция on concat (см. ниже).

на моем компьютере:

grunt default      : 6.2s (just uglify)
grunt default:true : 6s   (concat and uglify)

стоит отметить, что в результате main.min.js одинаково в обоих случаях.
Кроме того,uglify автоматически заботится об использовании правильного разделителя при объединении файлов.

единственный случай, когда это происходит вопрос при добавлении sourceMap: true до concat options.
Это создает рядом с main.js, и результаты в:

grunt default      : 6.2s (just uglify)
grunt default:true : 13s  (concat and uglify)

но если производственная площадка загружает только min версия, эта опция бесполезна.

я нашел майора минус С помощью concat до uglify.
Когда в одном из файлов JS возникает ошибка,sourcemap будет ссылка на сцепленные main.js файл, а не исходный файл. А когда uglify делает всю работу, это будет ссылка на оригинальный файл.

обновление:
Мы можем добавить еще 2 варианта uglify вот ссылка uglify sourcemap к concat sourcemap, таким образом, обрабатывая "недостаток", о котором я упоминал выше.

    uglify: {
        options: {
            compress: true,
            mangle: true,
            sourceMap: true,
            sourceMapIncludeSources: true,
            sourceMapIn: '<%= paths.dest.js %>.map',
        },
        target: {
            src: '<%= paths.src.js %>',
            dest: '<%= paths.dest.jsMin %>'
        }
    }

но это кажется совершенно ненужным.

вывод

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


в Примере, который вы упомянули, который я цитирую ниже, файлы сначала объединяются с concat а потом uglified/уменьшен uglify:

{
  concat: {
    '.tmp/concat/js/app.js': [
      'app/js/app.js',
      'app/js/controllers/thing-controller.js',
      'app/js/models/thing-model.js',
      'app/js/views/thing-view.js'
    ]
  },
  uglifyjs: {
    'dist/js/app.js': ['.tmp/concat/js/app.js']
  }
}

то же самое может быть достигнуто с:

{
  uglifyjs: {
    'dist/js/app.js': [
      'app/js/app.js',
      'app/js/controllers/thing-controller.js',
      'app/js/models/thing-model.js',
      'app/js/views/thing-view.js'
    ]
  }
}

как правило, задание clean затем будет выполняться после задач, которые пишут во временную папку (в этом примере concat) и удалите все содержимое в этой папке. Некоторые люди также любят бегать clean перед задачами, как compass, чтобы удалить такие вещи, как случайно названные спрайты изображений (которые генерируются каждый раз при выполнении задачи). Это заставит колеса крутиться даже самых параноиков.

это все вопрос предпочтений и рабочего процесса, как и при запуске jshint. Некоторые люди любят запускать его перед компиляцией, другие предпочитают запускать его в скомпилированных файлах.

сложные проекты с невероятным количеством JavaScript файлы-или с все более широким числом коллег и участников, может выбрать объединить файлы вне uglify просто, чтобы держать вещи более читабельным и поддерживаемым. Я думаю, что это было рассуждениеYeoman'ы выбор поток преобразования.

uglify может быть заведомо медленным в зависимости от конфигурации проекта, поэтому может быть небольшой выигрыш в объединении его с concat первый - но это должно быть подтверждено.

concat также поддерживает разделители uglify не так далеко, как README.md файлы обеспокоены.

concat: {
  options: {
    separator: ';',
  }
}