Frontender Magazine

Grunt для тех, кто считает штуки вроде него странными и сложными

Фронтенд-разработчикам часто советуют делать следующие вещи:

Конечно, этот список далеко не полон, но это такие вещи, которые делать просто необходимо. Вы могли бы смело назвать эти советы задачами.

Бьюсь об заклад, вы наверняка уже что-то слышали про Grunt. Что ж, Grunt — это, по сути, планировщик задач. Grunt может делать все эти задачи за вас. Стоит лишь установить его, что, кстати, не так уж и сложно, и эти операции будут происходить автоматически, так, что вам про них даже не придётся вспоминать.

Но, давайте посмотрим правде в глаза. Grunt — одна из тех новомодных штук, которой пользуются все эти крутые парни, но которая на первый взгляд выглядит странно и пугающе. Я вас понимаю. И эта статья для вас.

Пресекаем заблуждения в зародыше

Возможно, вы слышали про Grunt, но, по какой-то причине, никогда с ним не работали. Я уверен, это предположение относится к большинству из вас. Я также уверен, что большинство ваших сомнений перечислены ниже.

Мне не нужно то, что делает Grunt

Возможно, так оно и есть. Проверьте-ка ещё раз тот список задач в начале статьи. Эти рекомендации не просто неплохо было бы выполнять. Они — жизненно важная часть процесса веб–разработки в наше время. Если вы их уже соблюдаете, это замечательно. Вероятно, вы используете для этого разнообразные утилиты. Grunt помогает собрать их все, так сказать, под одной крышей. А если вы их ещё не используете, то, возможно, стоило бы, и тут вам может помочь Grunt. Ну а потом, когда вы уже будете их использовать, Grunt может сделать для вас ещё большее, что, в конечном итоге, будет означать, что вы лучше делаете свою работу.

Grunt работает на Node.js, а я его не знаю

Вам и не надо знать Node. Точно так же, как вам не нужно знать Ruby, чтобы пользоваться Sass. Или PHP, чтобы пользоваться WordPress. Или C++, чтобы пользоваться Microsoft Word.

Вещи, которые делает Grunt, я и так могу сделать, по-другому

Правда? Они все собраны в одном месте, настроены так, что запускаются автоматически, когда понадобятся, и есть у каждого члена команды, который работает над проектом? Рискну предположить, что это не так.

Grunt — консольная программа, а я всего лишь дизайнер

Я тоже дизайнер. И я предпочитаю использовать в работе приложения с графическим интерфейсом, если, конечно, он существует. Но я не думаю, что у Grunt1 такой интерфейс появится в ближайшее время.

Степень, в которой придётся работать с командной строкой, примерно такая:

  1. Перейти в папку с проектом.
  2. Напечатать grunt и нажать Return.

После установки, которая, повторюсь, не такая уж и сложная.

Хорошо. Устанавливаем Grunt

Необходимое условие для установки Grunt - наличие Node.js. Если Node.js у Вас не установлен, не беспокойтесь, это очень легко. вы просто скачиваете установочный файл и запускаете его. Давайте, просто кликните по большой кнопке Install на сайте Node.js.

Сам Grunt устанавливается на каждый проект отдельно. Вам нужно зайти в папку проекта и создать небольшой файл под названием package.json в его корне.

package.json в корне проекта

Содержимое файла package.json должно быть таким:

{
  "name": "example-project",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.1"
  }
}

Измените название проекта и укажите актуальную версию, главное, объявление devDependencies должно остаться таким же, как есть.

Это то, как Node обозначает зависимости в проекте. В Node для этого есть специальный пакетный менеджер под названием NPM.

Как только package.json будет находиться в нужном вам месте, откройте терминал, и перейдите в папку проекта. Парни вроде меня, которые мало смыслят в терминале, делают это примерно так:

Колхозный способ смены папки в терминале

Далее запустите команду:

npm install

После того, как она будет выполнена, в проекте появится новая папка с именем node_modules.

Пример папки node_modules

Другие файлы, которые вы видите на анимации в корне моего проекта, README.md и LICENSE, находятся там только потому, что я собираюсь выложить этот проект на Github, они не относятся непосредственно к установке Grunt.

Последний шаг — установка Grunt CLI (command line interface, интерфейс командной строки). Это то, что заставит терминал обрабатывать команду grunt. Без неё запуск grunt вернёт ошибку «Command Not Found» («Команда или файл не найдена»). Она устанавливается отдельно по причинам эффективности. Иначе, если бы у вас был десяток проектов, пришлось бы устанавливать десять копий GruntCLI.

Установка GruntCLI — всего одна строчка в терминале. Просто запустите команду:

npm install -g grunt-cli

После этого следует закрыть и заново открыть окно терминала. Это вообще хороший подход для того, чтобы убедиться, что всё работает как надо. Типа как перезагрузить компьютер после установки новой программы в старые добрые времена.

Давайте заставим Grunt объединить пару файлов

Представим, что в нашем проекте есть три отдельных файла JavaScript:

  1. jquery.js — библиотека, которую мы используем.
  2. carousel.js — плагин для jQuery, который мы используем.
  3. global.js — написанный нами файл, где мы настраиваем и вызываем наш плагин.

На продакшене нам надо объединить все эти файлы в один, для улучшения производительности (один http-запрос лучше, чем три). Нам нужно сказать Grunt, чтобы он это сделал для нас.

Но постойте, Grunt на самом деле ничего сам по себе не делает. Вы же помните, что Grunt — это всего лишь утилита для выполнения задач. А сами задачи нам придётся добавить. Пока что мы ещё не настраивали Grunt, чтобы он что-либо делал, поэтому давайте этим займёмся.

Официальный плагин Grunt для объединения файлов — grunt-contrib-concat

npm install grunt-contrib-concat --save-dev

Приятная особенность такого способа установки в том, что файл конфигурации package.json будет автоматически обновлён, и в него пропишется новая зависимость. Откройте его и убедитесь. Там появится новая строка:

"grunt-contrib-concat": "~0.3.0"

Вот теперь мы готовы использовать этот плагин. А чтобы его использовать, нам нужно начать настраивать Grunt и объяснять ему, что делать.

Указать Grunt, что ему делать, можно при помощи конфигурационного файла с названием Gruntfile.js2.

Точно так же, как и у файла package.json, у Gruntfile.js есть свой формат, которого нужно придерживаться. Я бы не стал заморачиваться по поводу того, что значит в нём каждое слово. Просто посмотрите на этот пример:

module.exports = function(grunt) {

    // 1. Вся настройка находится здесь
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        concat: {
            // 2. Настройка для объединения файлов находится тут
        }

    });

    // 3. Тут мы указываем Grunt, что хотим использовать этот плагин
    grunt.loadNpmTasks('grunt-contrib-concat');

    // 4. Указываем, какие задачи выполняются, когда мы вводим «grunt» в терминале
    grunt.registerTask('default', ['concat']);

};

Теперь нам нужно создать конфигурационный файл. Документация может быть ошеломляющей. Давайте сосредоточимся на простеньком примере.

Помните, у нас есть три файла JavaScript, которые мы пытаемся объединить. Мы перечислим пути к ним в src в качестве массива с путями к файлам (как строки в кавычках), и затем мы укажем файл назначения как dest. Файл назначения не обязательно должен существовать на данном этапе. Он будет создан в процессе, когда будет запущена соответствующая задача, которая склеит все файлы в один.

И jquery.js, и carousel.js являются библиотеками. Мы, скорее всего, не будем их изменять. И, для порядка в проекте, поместим их в отдельной папке /js/libs/. Файл global.js — то место, где мы пишем наш собственный код, поэтому он будет находиться прямо в корне папки /js/. Теперь нужно объяснить Grunt, как найти все эти файлы и склеить их в один файл production.js, названный так, чтобы показать, что он будет использоваться уже на настоящем, живом сайте.

concat: {
    dist: {
        src: [
            'js/libs/*.js', // Все JS в папке libs
            'js/global.js'  // Конкретный файл
        ],
        dest: 'js/build/production.js',
    }
}

Примечание: далее в этой статье будут приводиться такие же небольшие кусочки конфигурационного кода, как этот. Их цель — обратить внимание на важные места, однако, поначалу вы можете не понять, как каждый кусок будет интегрирован в большой файл. Если вы запутаетесь, и вам нужно будет посмотреть на эти примеры в контексте, просмотрите готовый полный файл конфигурации.

Когда конфигурация concat окажется на своем месте, откройте терминал и запустите команду:

grunt

И, смотрите, что происходит! Создан файл production.js, который является превосходным объединением трёх файлов. Лично для меня это был такой момент «Ух ты!». Незабываемое ощущение могущества, текущего в моих венах. Давайте наклепаем побольше таких штук!

А теперь заставим Grunt минифицировать наш JavaScript

Мы проделали столько дел для подготовки на предыдущих этапах, так что добавить ещё одну задачу для Grunt теперь относительно легко. Вот всё, что нужно сделать:

  1. Найти плагин для Grunt, который делает то, что нам нужно;
  2. Изучить стиль конфигурации этого плагина;
  3. Написать конфигурацию в соответствии с нашим проектом.

Необходимый нам плагин для минификации кода — grunt-contrib-uglify. Точно так же, как и в прошлый раз, мы запускаем команду npm для его инсталяции.

npm install grunt-contrib-uglify --save-dev

Затем меняем содержимое файла Gruntfile.js, для загрузки плагина:

grunt.loadNpmTasks('grunt-contrib-uglify');

И после этого конфигурируем его:

uglify: {
    build: {
        src: 'js/build/production.js',
        dest: 'js/build/production.min.js'
    }
}

Теперь обновим задачу по умолчанию (default), чтобы она запускала ещё и минификацию:

grunt.registerTask('default', ['concat', 'uglify']);

Очень-очень похоже на то, как настраивалось объединение файлов, верно?

Запускаем команду grunt в терминале и получаем на выходе немного изысканного, минифицированного JavaScript кода:

Minified JavaScript

Тот самый файл, production.min.js, который мы будем подключать в index.html.

Настраиваем Grunt на оптимизацию наших изображений

Теперь, когда вы уже освоили процесс, нужно лишь ещё раз пройти его по шагам. Нужный нам плагин Grunt для оптимизации изображений — grunt-contrib-imagemin. Установим его:

npm install grunt-contrib-imagemin --save-dev

Зарегистрируем в Gruntfile.js:

grunt.loadNpmTasks('grunt-contrib-imagemin');

Настроим:

imagemin: {
    dynamic: {
        files: [{
            expand: true,
            cwd: 'images/',
            src: ['**/*.{png,jpg,gif}'],
            dest: 'images/build/'
        }]
    }
}

Убедимся, что он запускается:

grunt.registerTask('default', ['concat', 'uglify', 'imagemin']);

Запускаем grunt и наблюдаем великолепное сжатие изображений:

Минифицированные изображения

Вам должно быть по душе то, как увеличивается производительность проекта практически без усилий.

Проявим немного сообразительности и автоматизируем процесс

То, что мы уже сделали, само по себе невероятно круто и очень полезно. Но, кое где можно сделать еще лучше, и тем самым облегчить и улучшить процесс сборки, как для себя, так и для Grunt.

  1. Запускать наши задачи по необходимости автоматически;
  2. Запускать только те задачи, которые нужны в данный момент.

Например:

  1. Объединять и минифицировать код JavaScript, когда он изменился;
  2. Оптимизировать изображения, если добавилось новое, или обновилось уже добавленное в проект.

Добиться этого очень легко, надо лишь отслеживать изменения в файлах проекта. Мы можем попросить Grunt приглядывать за файлами, и, если произошли изменения, запускать определённые задачи. Отслеживание производится при помощи плагина grunt-contrib-watch.

Я позволю вам установить его самостоятельно. Установка этого плагина ничем не отличается от предыдущих. Настроим его, указав в свойстве watch конкретные файлы (или папки, или и то и другое), за которыми нужно следить. Под отслеживанием файлов я подразумеваю наблюдение за их изменением, удалением и добавлением. Затем мы указываем, какие задачи необходимо запустить, если такое изменение произошло.

Проще говоря, сейчас мы бы хотели, чтобы при наличии изменений в папке /js/ запускались процессы по объединению и минификации файлов. Или, другими словами, когда это случится, нам нужно, что бы Grunt запустил тип задач, связанных с JavaScript. Но, если что-нибудь произойдёт в другом месте, нам, наоборот, не нужно запускать эти задачи, потому как они будут бесполезны. Итак:

watch: {
    scripts: {
        files: ['js/*.js'],
        tasks: ['concat', 'uglify'],
        options: {
            spawn: false,
        },
    }
}

Пока все довольно просто, да? Единственная, немного странная опция — это spawn. И знаете, что? Я понятия не имею, что она обозначает. Из документации я лишь понял, что, по хорошему, её лучше не менять из значения по умолчанию. Ну, мы разрабатываем в реальном мире. Просто не трогайте эту настройку, пока всё работает, а если что-то пошло не так, принимайтесь за чтение мануала.

Примечание: Грустно, когда что-то так просто выглядит в учебнике, но у вас по какой-то загадочной причине не работает, правда? Если вы не можете заставить Grunt работать после каких-то изменений, то, скорее всего, причина в синтаксической ошибке в файле Gruntfile.js. В терминале это выглядит примерно так:

Ошибка при запуске Grunt

Обычно, Grunt неплохо объясняет, что именно пошло не так, так что не забывайте проверять сообщения об ошибках. В моем случае произошла ошибка синтаксиса, меня подвела пропущенная запятая. Нужно её добавить, и всё снова заработает.

Заставим Grunt работать с нашим препроцессором

Последний пункт нашего списка в начале статьи — использование Sass. И вновь, Grunt отлично подходит для этой задачи. Но, спросите вы, как же так? Разве Sass работает не на Ruby? Да, это действительно так. Правда, есть версия Sass, работающая на Node, но, она не добавляет в проект дополнительные зависимости, да и не такая свежая по сравнению с версией на Ruby. Так что мы будем использовать официальный плагин grunt-contrib-sass, который просто считает, что Sass уже установлен на вашей машине. Если это не так, изучите инструкцию по установке Saas из командной строки.

Действительно крутая фишка Sass в том, что он самостоятельно производит объединение и минификацию файлов. Так что в нашем маленьком проекте достаточно просто скомпилировать наш основной файл global.scss:

sass: {
    dist: {
        options: {
            style: 'compressed'
        },
        files: {
            'css/build/global.css': 'css/global.scss'
        }
    }
}

И, конечно, нам бы не хотелось запускать эту задачу вручную. У нас ведь уже есть плагин для отслеживания изменений, так что давайте его используем! В конфигурации watch добавим ещё одну подзадачу:

css: {
    files: ['css/*.scss'],
    tasks: ['sass'],
    options: {
        spawn: false,
    }
}

Готово. И теперь, всякий раз, когда мы вносим изменения в Sass файлы, исходящий CSS файл будет автоматически обновляться.

Давайте пойдём немного дальше, это определённо того стоит, и добавим поддержку LiveReload. С LiveReload вам больше не придётся переключаться в окно браузера и обновлять страницу. Страница будет обновляться автоматически, а в случае CSS, новые стили будут внедряться в страницу также, без перезагрузки. Особенно полезно для тех сайтов, отображение которых зависит от различного состояния страниц.

Это очень легко устроить, потому как LiveReload уже включён в плагин watch. Всё, что нам надо сделать:

  1. Установить плагин для браузера;
  2. Добавить пару строк в настройки watch: watch: { options: { livereload: true, }, scripts: { /* и т.д. */

  3. Перезапустить браузер и щёлкнуть на иконку LiveReload, чтобы включить его;

  4. Отредактировать файл Sass и увидеть, как изменения появляются на странице без перезагрузки.

Страница обновляется на лету

Загляденье.

Предпочитаете видео?

Если вы лучше воспринимаете информацию в формате видеоуроков, то, специально для вас я подготовил небольшой скринкаст, отлично дополняющий эту статью. Он опубликован на CSS-Tricks: First Moments with Grunt

Получаем level-up

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

Какие-нибудь заумные приверженцы DevOps могут смотреть свысока на нашу простую конфигурацию. Но я бы посоветовал им умерить пыл. Даже то, что мы сделали уже сейчас чрезвычайно значимый шаг. И не забывайте, что это всё бесплатно, с открытыми исходниками, и это поразительно.

Вы можете получить настоящий level-up, используя следующие полезные задачи Grunt:

А также вы можете прокачаться ещё больше, просто поняв принцип работы самого Grunt:

Делимся знаниями

Я думаю, в завершении этой темы было бы неплохо организовать обмен знаниями между заинтересованными сторонами. Если вы установили Grunt в первый раз (или хорошо помните, как это делали), будьте особенно внимательны к неприятным мелочам, которые вы испытали и превозмогли. Это — те мелочи, которыми следует поделиться тут, в комментариях. Так мы сделаем из этой статьи полезный ресурс, помогающий преодолеть эти неприятные моменты без смущения. Мы все, вместе, занимаемся этой штукой!


Примечания

1. Может быть, кто-нибудь когда-нибудь сделает красивый UI под Grunt для вашей операционной системы. Но я до конца не уверен, что этот день наступит. Конфигурация плагинов — это важный атрибут использования Grunt. Каждый плагин немного отличается от остальных, в зависимости от того, что он делает. Это означает уникальный интерфейс для каждого отдельного плагина, и его воплощение — довольно рискованное занятие.

Возможно, неплохим компромиссом станет плагин Grunt DevTools для Chrome.

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

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Chris Coyier
Антон Хлыновский
Переводчик:
Антон Хлыновский
GitHub:
subzey
Twitter:
@subzey

Комментарии (37 комментариев, если быть точным)

Автар пользователя
iamstarkov

Жалко, что этой статьи не было несколько месяцев назад

Автар пользователя
ghost

У вас опечатка в статье. После выполнения команды grunt-contrib-concat в package.json будет добавлена зависимость именно для grunt-contrib-concat, а не для grunt-contrib-uglify

Автар пользователя
prBigBrother

Я, конечно же, понимаю, это все гибко и работает с помощью пару строк.

Но: в разработке обычно использую CodeKit. Он выполняет все требуемые пункты статьи, описанные выше (Единственного чего нет, это оптимизации изображения, но раньше я не обращал внимание на необходимость данного).

Процесс добавлении проекта в CodeKit состоит из пункта перенести в папку в окно программы. Конечно же, желательно ознакомиться с настройками программы при первом использовании и настроить под себя. В дальнейшем, вряд ли появится нужда изменять настройки, так как можно один раз настроить так, как тебе удобно.

Процесс c Grunt'ом требует куда более затрат по времени, со всеми нуждами прописывать команды, создавать тот же package.json.

То есть, мне для того что бы компилировать Less в CSS (c проверкой на ошибки), минифицировать JS (с проверкой на ошибки), и паковать это все нормально, плюс все плюшечки типа компилирования на лету и лайв релоуда, достаточно добавить папку с проектом в CodeKit.

Надеюсь был полезным ;)

Автар пользователя
prBigBrother

П.С. понимаю, что Codekit бесплатен в отличии Grunt'а, понимаю что много могу не знать о Grunt'е. Оперирую только на теми фактами, что раскрыли в статье.

Автар пользователя
iamstarkov

@prBigBrother, каждый волен выбирать то, что ему удобно.

из описанного вами про CodeKit я всё ещё продолжаю видеть у Grunt плюсы, так как: - грант кроссплатформен - грант-воркфлоу легко поделиться, лишь предложив людям выполнить grunt test для прогонки тестов, а не описывать как настроить кодкит-окружение - больше двух тысяч тасков на данный момент и появляется всё больше, а также можно всегда написать свой


что Codekit бесплатен в отличии Grunt'а

вы точно ничего не путаете?

Автар пользователя
iamstarkov

@EugeneAbrosimov, спасибо вам! исправил.

Проблема была в том, что ошибка существовала в оригинале на момент начала перевод.

В следующий раз, можете не стесняться и сразу присылать пулл-реквесты с исправлением таких неточностей.

Автар пользователя
prBigBrother

@matmuchrapna вы меня почти убедили. Не подумайте, что я упираюсь в единственное решение в виде CodeKit, просто не нашел аргументов в статье, почему Grunt мне действительно заменит его.

что Codekit бесплатен в отличии Grunt'а вы точно ничего не путаете?

Конечно же, я заметил опечатку изначально, не хотел плодить комментарии с исправлением.

Может у вас будет возможность раскрыть возможности Grunt'а чуть больше?

Опять же, останавливает меня только постоянная необходимости все настраивать с нуля на каждый проект. Может есть возможность обойти?

Опишу спектр своих задач: я разработчик кастомных тем под WP, у нас есть свое готовое тема-ядро. То есть, особенных задач, кроме как из LESS в CSS, из script.js в script.min.js + Autor Reload, в принципе и нет.

Автар пользователя
iamstarkov

Конечно же, я заметил опечатку изначально, не хотел плодить комментарии с исправлением.

можно было отредактировать свой комментарий на гитхабе


Может у вас будет возможность раскрыть возможности Grunt'а чуть больше?

я не смогу «продать» вам грант не зная ваших потребностей.


Опять же, останавливает меня только постоянная необходимости все настраивать с нуля на каждый проект. Может есть возможность обойти?

Мне кажется, что грант-таски обеспечивают достаточную степень абстракции над проектами и позволяют реиспользовать себя. Если же у вас совсем похожие проекты, то на первых порах вы вполне себе можете копировать из проекта в проект файлы package.json (зависимости) и Gruntfile.js (таски для ваших проектов) а затем даже написать свой скаффолдер, например yeoman-генератор

Автар пользователя
askd

Тоже недавно открыла для себя grunt. Сейчас не представляю, как можно было разрабатывать без него. По поводу экспириенса по установке и настройке... Оказалось проще, чем я думала, когда бралась за это.

Автар пользователя
raqystyle

@prBigBrother а насколько гибкий в настройке CodeKit? насколько легко переконфигурировать его согласно требованиям, изминениям в команде, деплойментам и прочим? Возможно, если вы работаете один (фрилансер, например) то его вполне хватает. Но если вы работаете в гибкой команде где люди могут приходит и уходить каждые пол-года, а то и чаще, то лучше Grunt'a я пока ничего не встречал.

Автар пользователя
toydestroyer

Друзья, правильно понимаю, что в grunt-contrib-watch уже полностью включен LiveReload и по сути лицензия не нужна? (Я покупал GUI в AppStore).

Видимо, Grunt достаточно занятная штука, особенно порадовала оптимизация изображения. Но у меня вновь вопрос: почти все эти задачи решает Sprockets (почти все проекты делаю в Middleman), соотвенно Grunt всего лишь альтернатива?

Автар пользователя
prBigBrother

@raqystyle речь шла больше не о гибкости CodeKit и о безусловной альтернативе Grunt'у. Я говорил что с основными задачами он справляется.

Но сейчас, я понимаю что можно куда более автоматизировать благодаря Grunt'у то, о чем мне и в голову не приходило бы автоматизировать ранее, тем более то что недоступно CodeKit'у

Автар пользователя
egamzin

Кто-то может поделиться опытом использования Grunt в больших проектах?

Проект на .Net с огромным кол-вом уникальных страниц, на каждой подключается по 5-50 js-ов. Планируется собирать для каждой страницы свой js-файл из всех скриптов, которые используются на ней. Задача усложняется наличием большого количества зависимостей. Например, нужно подключить какой-то модуль, но для него нужны некоторые библиотеки или jquery-плагины. И отслеживать это в ручную не представляется возможным.

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

Где можно почитать о best practice? Поиск выдает в основном совсем простые туториалы для новичков.

Автар пользователя
iamstarkov

@egamzin я не встречал на просторах интернета статью с best practice, но думаю она есть.

Попробую поделиться своим опытом: когда я начинал свой пока, что самый большой проект Хампи, то для достижения грант-просветления я осознал две вещи и начал использовать обе в полную силу:

1) для гранта огромное количество готовых плагинов, поэтому я отсмотрел все плагины по интересующим кейвордам и попробовал выбранные (повторяю с некоторой периодичностью) 2) осознал, что Gruntfile.js это обычный js-файл и внутри него можно творить, что угодно и использовать это в своих целях

Автар пользователя
ghost

@egamzin мы обычно используем для этих целей require.js. Если посмотреть доки по оптимизации, то можно найти примеры билда проекта в несколько "модулей". Но если у вас весь проект после билда не будет весить много, то не будет никакого смысла его разбивать на части.

Если используете какие то популярные библиотеки (jquery, например), то в конфиге require.js можно прописать его CDN, что позволит в некоторых случаях сократить время загрузки скриптов.

Автар пользователя
ivanzolotov

Если конфигурировать imagemin способом, описанным в статье, то при повторном запуске grunt возьмёт все графические файлы из ./img и всех её поддиректорий. Да, в том числе и из ./img/build, а при размещении оптимизированного файла аккуратно воссоздаст структуру папок в пункте назначения, то есть в ./img/build снова создаст build и положит оптимизированный файл туда. При третьем запуске grunt структура будет выглядеть уже следующим образом: ./img/build/build/build. Чтобы этого избежать нужно каким-то образом исключить ./img/build из источника, то есть внести корректировку вот в эту строку:

src: ['*_/_.{png,jpg,gif}']

Автар пользователя
jslby

@egamzin, используйте require.js

Автар пользователя
jslby

Набросал за несколько часов небольшой скелет. Если кому то интересно, то вот линк: https://github.com/jslby/fewatcher

Полностью функционирует, жду предложения и замечания.

Автар пользователя
ivanzolotov

А я правильно понимаю, что LiveReload заработает только с сервером? Ну, и вообще, раскрытия темы сервера статье не достаёт.

Автар пользователя
ivanzolotov

Насчёт SASS под Mac OS X. Для тех, у кого Ruby через Homebrew потребуется после установки самого SASS командой gem install sass выполнить:

brew unlink ruby; brew link ruby

Автар пользователя
iamstarkov

@jslby отписался в ишью репозитории

Автар пользователя
A

А я правильно понимаю, что LiveReload заработает только с сервером? Ну, и вообще, раскрытия темы сервера статье не достаёт.

grunt-contrib-watch сам запускает livereload-server. Пользователю достаточно всего лишь подключить его в своем html-файле:

<script src="//localhost:35729/livereload.js"></script>

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

Автар пользователя
zjoin

Если настроить concat по статье и напечатать 'grunt'

Warning: Task “default” not found. Use –force to continue.

Автар пользователя
iamstarkov

Если у тебя есть строчка: grunt.registerTask('default', ['concat']);, то всё должно работать. Покажи свой грантфайл

Автар пользователя
zjoin

http://jsbin.com/UYoDaxUt/1/edit

Непорядок здесь grunt-contrib-imagemin

Автар пользователя
iamstarkov

во-первых, это уже другая ошибка. во-вторых, у тебя не так, как в статье: grunt.registerTask('default', ['concat']); в-третьих, default-таск падает из-за ошибки в таске imagemin. тут уже веселее.

Подозреваю, что таск просто не находит ни одного файла внутри вложенных папок (**/*…) папки images/. А также проблема может быть здесь http://stackoverflow.com/q/20118325/1057730

Автар пользователя
ivanzolotov

А что насчёт бесконечного вложения папок build? Есть идеи, как это побороть?

Автар пользователя
iamstarkov

Конечно.

Достаточно добавить папку build в исключения

js imagemin: { dynamic: { files: [{ expand: true, cwd: 'images/', src: ['**/*.{png,jpg,gif}', '!build/'], dest: 'images/build/' }] } }

И всё будет хорошо, если только imagemin умеет перезаписывать файлы, если не умеет, то нам придёт на помощь grunt-contrib-clean:

js clean: { build: { src: ['images/build/'] } }

И итоговый код для default-таска будет таким:

js grunt.registerTask('default', ['concat', 'uglify', 'clean', 'imagemin']);

Автар пользователя
P3trovichUA

Только что сравнил imagemin с прогой которой я пользуюсь. Пока еще он проигрывает в сжатии.

Автар пользователя
P3trovichUA

Опробовал grunt. Отличная вещь. Prepros — на свалку.

Автар пользователя
transGLUKator

Спасибо, давно хотел начать пользоваться grunt'ом.

Автар пользователя
iamstarkov

попробуйте приглядеться к gulp

Автар пользователя
pavlyukpetr

подскажите в чем проблема: imagemin проваливается с ошибкой write EOF in file ...

Автар пользователя
pavlyukpetr

и ошибка при использовании contrib-sass. Пишет, что я должен установить руби и sass (You need to have Ruby and Sass installed and in your PATH for this task to work). Но они у меня стоят. Я могу через консоль посмотреть их версии. Как это решить?

Автар пользователя
KorbenMakar

Это, наверное, самая лучшая статья о настройках Grunt!!! До этого читал другие блоги - напряжно... Здесь же все доходчиво, ясно и понятно. Супер, спасибо.

Автар пользователя
Sigmanor

Занятно, но gulp Наше все :D

Автар пользователя
wwwork

сейчас уже есть github.com/sass/node-sass#options