Как объединить и минимизировать несколько файлов CSS и JavaScript с помощью Grunt.js(0.3.x)

Примечание. Этот вопрос относится только к Grunt 0.3.x и оставлен для справки. Для получения помощи в последнем выпуске Grunt 1.x, пожалуйста, ознакомьтесь с моим комментарием ниже этого вопроса.

В настоящее время я пытаюсь использовать Grunt.js для установки автоматического процесса сборки для первого конкатенации, а затем для минимизации файлов CSS и JavaScript.

Мне удалось успешно объединить и уменьшить мои файлы JavaScript, хотя каждый раз, когда я запускаю grunt, он просто добавляется к файлу, а не перезаписывает их.

Что касается минимизирующего или даже конкатенационного CSS, я пока не смог это сделать!

В терминах grunt CSS-модулей я попытался использовать consolidate-css, grunt-css и cssmin, но безрезультатно. Не могу понять, как их использовать!

Моя структура каталогов выглядит следующим образом (являясь типичным приложением node.js):

  • app.js
  • grunt.js
  • /public/index.html
  • /public/css/[различные файлы css]
  • /public/js/[различные файлы javascript]

Вот что мой файл grunt.js в настоящее время выглядит в корневой папке моего приложения:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    concat: {
      dist: {
        src: 'public/js/*.js',
        dest: 'public/js/concat.js'
      }
    },
    min: {
      dist: {
        src: 'public/js/concat.js',
        dest: 'public/js/concat.min.js'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true
      },
      globals: {
        exports: true,
        module: false
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'concat min');

};

Итак, просто подведем итоги. Мне нужна помощь с двумя вопросами:

  • Как объединить и минимизировать все мои файлы css под папкой /public/css/ в один файл, скажем main.min.css
  • Почему grunt.js продолжает добавлять к конкатенированным и миниатюрным файлам javascript concat.js и concat.min.js в /public/js/ вместо их перезаписи при каждом запуске команды grunt?

Обновлено 5 июля 2016 г. - Обновление с Grunt 0.3.x до Grunt 0.4.x или 1.x

Grunt.js переместился в новую структуру в Grunt 0.4.x (теперь этот файл называется Gruntfile.js). Пожалуйста, смотрите мой проект с открытым исходным кодом Grunt.js Skeleton для помощи в настройке процесса сборки для Grunt 1.x.

Переход от Grunt 0.4.x в Grunt 1.x не должен вносить много важных изменений.

Ответ 1

concat.js включается в исходные файлы concat public/js/*.js. У вас может быть задача, которая удаляет concat.js (если файл существует) перед конкатенацией снова, передать массив, чтобы явно определить, какие файлы вы хотите конкатенации и порядок, или изменить структуру вашего проекта.

Если вы делаете последнее, вы можете поместить все свои источники под ./src и ваши встроенные файлы в ./dest

src
├── css
│   ├── 1.css
│   ├── 2.css
│   └── 3.css
└── js
    ├── 1.js
    ├── 2.js
    └── 3.js

Затем настройте задачу concat

concat: {
  js: {
    src: 'src/js/*.js',
    dest: 'dest/js/concat.js'
  },
  css: {
    src: 'src/css/*.css',
    dest: 'dest/css/concat.css'
  }
},

Ваша задача мин

min: {
  js: {
    src: 'dest/js/concat.js',
    dest: 'dest/js/concat.min.js'
  }
},

Встраиваемая минута задача использует UglifyJS, поэтому вам нужна замена. Я нашел grunt-css довольно неплохо. После его установки загрузите его в файл grunt

grunt.loadNpmTasks('grunt-css');

И затем настройте его

cssmin: {
  css:{
    src: 'dest/css/concat.css',
    dest: 'dest/css/concat.min.css'
  }
}

Обратите внимание, что использование похоже на встроенный мин.

Измените задачу default на

grunt.registerTask('default', 'concat min cssmin');

Теперь запуск grunt приведет к желаемым результатам.

dest
├── css
│   ├── concat.css
│   └── concat.min.css
└── js
    ├── concat.js
    └── concat.min.js

Ответ 2

Я хочу упомянуть здесь очень, ОЧЕНЬ, интересную технику, которая используется в таких огромных проектах, как jQuery и Modernizr для конкатенации.

Оба этих проекта полностью разработаны с помощью модулей requirejs (вы можете видеть это в своих репозиториях github), а затем они используют оптимизатор requirejs в качестве очень умного конкатенатора. Интересно, что, как вы можете видеть, ни jQuery, ни Modernizr не нуждаются в требованиях, чтобы работать, и это происходит потому, что они стирают ритуал requirejs, чтобы избавиться от requirejs в их коде. Таким образом, у них есть отдельная библиотека, которая была разработана с помощью модулей requirejs! Благодаря этому они могут выполнять вырезки своих библиотек и другие преимущества.

Для всех заинтересованных в конкатенации с оптимизатором requirejs, этот пост

Также есть небольшой инструмент, который абстрагирует весь шаблон процесса: AlbanilJS

Ответ 3

Я согласен с вышеприведенным ответом. Но вот еще один способ сжатия CSS.

Вы можете сконфигурировать свой CSS с помощью компрессора YUI:

module.exports = function(grunt) {
  var exec = require('child_process').exec;
   grunt.registerTask('cssmin', function() {
    var cmd = 'java -jar -Xss2048k '
      + __dirname + '/../yuicompressor-2.4.7.jar --type css '
      + grunt.template.process('/css/style.css') + ' -o '
      + grunt.template.process('/css/style.min.css')
    exec(cmd, function(err, stdout, stderr) {
      if(err) throw err;
    });
  });
}; 

Ответ 4

Вам не нужно добавлять пакет concat, вы можете сделать это через cssmin следующим образом:

cssmin : {
      options: {
            keepSpecialComments: 0
      },
      minify : {
            expand : true,
            cwd : '/library/css',
            src : ['*.css', '!*.min.css'],
            dest : '/library/css',
            ext : '.min.css'
      },
      combine : {
        files: {
            '/library/css/app.combined.min.css': ['/library/css/main.min.css', '/library/css/font-awesome.min.css']
        }
      }
    }

И для js используйте uglify следующим образом:

uglify: {
      my_target: {
        files: {
            '/library/js/app.combined.min.js' : ['/app.js', '/controllers/*.js']
        }
      }
    }

Ответ 5

Я думаю, что может быть более автоматическим, grunt task usemin позаботиться о том, чтобы делать все эти задания для вас, нужна только конфигурация:

fooobar.com/info/41470/...