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

99

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

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

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

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

С точки зрения рубаки модулей 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');

};

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

  1. Как объединить и минимизировать все мои файлы css в папке /public/css/в один файл, скажемmain.min.css
  2. Почему 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 не должен вносить много серьезных изменений .

Джасдип Халса
источник

Ответы:

107

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
Хайме
источник
1
Ты гений! Мне никогда не приходило в голову, что, конечно, если бы я включил concatв ту же jsпапку, она бы выскочила и добавила! Я начал использовать cssmin, и он отлично работает! Еще раз спасибо.
Jasdeep Khalsa
1
Отлично, действительно здорово! Но имена файлов всегда concat.min.cssи concat.min.js. Если я что-то изменю, перезапущу и разверну, люди не получат самую последнюю версию, потому что браузер уже кэшировал ее. Там»каким - то образом случайно имя файла и связать их в соответствии с надлежащей <link>и <script>теги?
Tárcio Zemel
3
@ TárcioZemel Вы можете включить версию package.json в имя файла:concat.min-<%= pkg.version %>.js
Rui Nunes
1
Можно использовать .destтак cssmin: { css:{ src: '<%= concat.css.dest %>', dest: './css/all.min.css'}} `Это результат операцииconcat -> css
Иван Блэк
12

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

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

Для всех, кто заинтересован в объединении с оптимизатором requirejs, ознакомьтесь с этим постом

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

Аугусто Альтман Каранта
источник
Это очень интересно, но не имеет отношения к вопросу, поскольку RequireJS - это загрузчик модулей, он не объединяет и не
минимизирует AFAIK
Спасибо! Вы правы, RequireJS - это загрузчик модулей, который не объединяет и не минимизирует. Но r.js (оптимизатор RequireJS -> requirejs.org/docs/optimization.html ) делает это. В частности, он объединяет ваши модули, упорядочивая их по зависимостям. Ребята из Modernizr и jQuery воспользовались алгоритмом упорядочивания этого инструмента и использовали его специально как умный конкатенатор. Вы можете проверить их репозитории, чтобы узнать, что они делают.
Аугусто Альтман Каранта,
Используя concat или uglify grunt, результирующий файл составляется с использованием порядка указанных исходных файлов. В то время как RequireJS основан на зависимости. Другой подход позволяет достичь того же результата.
priyabagus
10

Я согласен с приведенным выше ответом. Но вот еще один способ сжатия 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;
    });
  });
}; 
Аншул
источник
В случае, если вы используете 'grunt-css', вам необходим модуль Locale Npm, поэтому убедитесь, что при установке 'grunt-css' он должен быть в модуле Locale Npm.
Аншул
7
Зачем вам делать всю эту сложность и вызывать jvm в процессе сборки? Просто тормозит все это без причины.
Майкл
3

Вам не нужно добавлять пакет 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']
        }
      }
    }
Inc33
источник
0

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

https://stackoverflow.com/a/33481683/1897196

Дональд
источник