Spec-Zone.ru › Grunt

Настройка задач

Это руководство объясняет, как настроить задачи для вашего проекта, используя Gruntfile. Если вы не знаете, что такое Gruntfile, пожалуйста, прочтите руководство Начало работы и ознакомьтесь с примером Sample Gruntfile.

Настройка Grunt

Настройка задач задаётся в вашем Gruntfile через метод grunt.initConfig. Эта настройка в основном будет находиться под свойствами с названиями задач, но может содержать любые произвольные данные. Все свойства, которые не конфликтуют со свойствами, необходимыми вашим задачам, будут игнорироваться.

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

grunt.initConfig({
  concat: {
    // concat task configuration goes here.
  },
  uglify: {
    // uglify task configuration goes here.
  },
  // Arbitrary non-task-specific properties.
  my_property: 'whatever',
  my_src_files: ['foo/*.js', 'bar/*.js'],
});

Конфигурация задач и целевые задачи

Когда задача выполняется, Grunt ищет её конфигурацию под свойством с таким же именем. Многозадачные задачи могут иметь несколько конфигураций, определённых с помощью произвольно именованных «целей». В примере ниже задача concat имеет цели foo и bar, а задача uglify имеет только цель bar.

grunt.initConfig({
  concat: {
    foo: {
      // concat task "foo" target options and files go here.
    },
    bar: {
      // concat task "bar" target options and files go here.
    },
  },
  uglify: {
    bar: {
      // uglify task "bar" target options and files go here.
    },
  },
});

Указание и задачи и цели, например, grunt concat:foo или grunt concat:bar, обработает только конфигурацию указанной цели, а выполнение grunt concat переберёт все цели, обрабатывая каждую по очереди. Обратите внимание, что если задача была переименована с помощью grunt.task.renameTask, Grunt будет искать свойство с новым именем задачи в объекте конфигурации.

Параметры

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

Объект options необязателен и может быть опущен, если он не требуется.

grunt.initConfig({
  concat: {
    options: {
      // Task-level options may go here, overriding task defaults.
    },
    foo: {
      options: {
        // "foo" target options may go here, overriding task-level options.
      },
    },
    bar: {
      // No options specified; this target will use task-level options.
    },
  },
});

Файлы

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

Все форматы файлов поддерживают src и dest, но форматы Компактный и Массив файлов поддерживают несколько дополнительных свойств:

  • filter Либо действительное имя метода fs.Stats, либо функция, которая получает сопоставленный src путь к файлу и возвращает true или false. См. примеры
  • nonull Если установлено значение true, операция будет включать несопоставленные шаблоны. В сочетании со флагом Grunt --verbose, этот параметр может помочь отладить проблемы с путями к файлам.
  • dot Разрешить шаблонам сопоставлять имена файлов, начинающиеся с точки, даже если шаблон явно не содержит точку в этом месте.
  • matchBase Если установлено значение, шаблоны без слэшей будут сопоставляться с базовым именем пути, если он содержит слэши. Например, a?b будет сопоставляться с путем /xyz/123/acb, но не с /xyz/acb/123.
  • expand Обработать динамическое сопоставление файлов src-dest, см. "Динамическое создание объекта files" для получения дополнительной информации.
  • Другие свойства будут переданы в базовые библиотеки в качестве соответствующих параметров. См. документацию по node-glob и minimatch для получения дополнительных параметров.

Разница между параметрами Grunt и параметров задач

Большинство задач выполняют операции с файлами, поэтому Grunt предоставляет встроенную инфраструктуру для получения файлов, которые должна обработать задача. Преимущество заключается в том, что авторам задач не нужно реализовывать эту логику заново. Чтобы позволить пользователю указать эти файлы, Grunt предоставляет такие параметры, как nonull и filter.

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

Для лучшего понимания этой разницы рассмотрим пример, использующий grunt-contrib-jshint:

grunt.initConfig({
  jshint: {
    ignore_warning: {
      options: {
        '-W015': true,
      },
      src: 'js/**',
      filter: 'isFile'
    }
  }
});

Эта конфигурация использует параметры Grunt src и filter для указания файлов для обработки. Она также использует параметр задачи grunt-contrib-jshint -W015 для игнорирования определённого предупреждения (которое имеет код W015).

Компактный формат

Этот формат позволяет указать одно сопоставление файла src-dest (исходный-конечный) на цель. Он чаще всего используется для задач только для чтения, например, grunt-contrib-jshint, где требуется одно свойство src, и ключ dest не имеет значения. Этот формат также поддерживает дополнительные свойства для каждого сопоставления src-dest.

grunt.initConfig({
  jshint: {
    foo: {
      src: ['src/aa.js', 'src/aaa.js']
    },
  },
  concat: {
    bar: {
      src: ['src/bb.js', 'src/bbb.js'],
      dest: 'dest/b.js',
    },
  },
});

Формат объекта файлов

Этот формат поддерживает несколько сопоставлений src-dest на цель, где имя свойства является файлом назначения, а его значение — файлом или файлами источника. В этом формате можно указать любое количество сопоставлений src-dest, но дополнительные свойства для каждого сопоставления указывать нельзя.

grunt.initConfig({
  concat: {
    foo: {
      files: {
        'dest/a.js': ['src/aa.js', 'src/aaa.js'],
        'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'],
      },
    },
    bar: {
      files: {
        'dest/b.js': ['src/bb.js', 'src/bbb.js'],
        'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'],
      },
    },
  },
});

Формат массива файлов

Этот формат поддерживает несколько сопоставлений src-dest на цель, а также позволяет указывать дополнительные свойства для каждого сопоставления.

grunt.initConfig({
  concat: {
    foo: {
      files: [
        {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'},
        {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'},
      ],
    },
    bar: {
      files: [
        {src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true},
        {src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'},
      ],
    },
  },
});

Старые форматы

Формат файлов dest-as-target — это пережиток времён, когда многозадачных задач и целей ещё не было, где путь к файлу назначения фактически являлся именем цели. К сожалению, так как имена целей являются путями к файлам, запуск grunt task:target может быть неудобным. Также вы не можете указать параметры на уровне цели или дополнительные свойства для каждого сопоставления src-dest.

Считается, что этот формат устарел, и следует избегать его при возможности.

grunt.initConfig({
  concat: {
    'dest/a.js': ['src/aa.js', 'src/aaa.js'],
    'dest/b.js': ['src/bb.js', 'src/bbb.js'],
  },
});

Пользовательская функция фильтрации

Свойство filter может помочь вам более точно нацеливаться на файлы. Просто используйте действительное имя метода fs.Stats. Следующее действие очистит только если шаблон соответствует реальному файлу:

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: 'isFile',
    },
  },
});

Или создайте собственную функцию filter и верните значение true или false, чтобы определить, нужно ли сопоставлять файл. Например, следующее действие будет очищать только те папки, которые пустые:

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: function(filepath) {
        return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0);
      },
    },
  },
});

Ещё один пример — который использует функции globbing и expand: true — позволяет вам избежать перезаписи файлов, которые уже существуют в назначении:

grunt.initConfig({
  copy: {
    templates: {
      files: [{
        expand: true,
        cwd: ['templates/css/'],     // Parent folder of original CSS templates
        src: '**/*.css',             // Collects all `*.css` files within the parent folder (and its subfolders)
        dest: 'src/css/',            // Stores the collected `*.css` files in your `src/css/` folder
        filter: function (dest) {    // `dest`, in this instance, is the filepath of each matched `src`
          var cwd = this.cwd,        // Configures variables (these are documented for your convenience only)
              src = dest.replace(new RegExp('^' + cwd), '');
              dest = grunt.task.current.data.files[0].dest;
          return (!grunt.file.exists(dest + src));    // Copies `src` files ONLY if their destinations are unoccupied
        }
      }]
    }
  }
});

Помните, что указанный выше метод не учитывает свойство rename при проверке существования назначения.

Шаблоны globbing

Часто неудобно указывать все пути к исходным файлам индивидуально, поэтому Grunt поддерживает расширение имён файлов (также известное как globbing) с помощью встроенных библиотек node-glob и minimatch.

Хотя это не исчерпывающее руководство по шаблонам globbing, помните, что в пути к файлу:

  • * соответствует любому числу символов, но не /
  • ? соответствует одному символу, но не /
  • ** соответствует любому числу символов, включая /, если это единственный элемент в части пути
  • {} позволяет использовать перечисление выражений «или» через запятую
  • ! в начале шаблона инвертирует соответствие

Всё, что большинство людей должны знать, это то, что foo/*.js соответствует всем файлам, заканчивающимся на .js в подкаталоге foo/, но foo/**/*.js соответствует всем файлам, заканчивающимся на .js в подкаталоге foo/ и всех его подкаталогах.

Кроме того, для упрощения в противном случае сложных шаблонов globbing Grunt позволяет указывать массивы путей к файлам или шаблонов globbing. Шаблоны обрабатываются в порядке следования, при этом сопоставления с префиксом ! исключают соответствующие файлы из результата. Результат сводится к уникальным элементам.

Например:

// You can specify single files:
{src: 'foo/this.js', dest: ...}
// Or arrays of files:
{src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...}
// Or you can generalize with a glob pattern:
{src: 'foo/th*.js', dest: ...}

// This single node-glob pattern:
{src: 'foo/{a,b}*.js', dest: ...}
// Could also be written like this:
{src: ['foo/a*.js', 'foo/b*.js'], dest: ...}

// All .js files, in foo/, in alpha order:
{src: ['foo/*.js'], dest: ...}
// Here, bar.js is first, followed by the remaining files, in alpha order:
{src: ['foo/bar.js', 'foo/*.js'], dest: ...}

// All files except for bar.js, in alpha order:
{src: ['foo/*.js', '!foo/bar.js'], dest: ...}
// All files in alpha order, but with bar.js at the end.
{src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...}

// Templates may be used in filepaths or glob patterns:
{src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'}
// But they may also reference file lists defined elsewhere in the config:
{src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}

Для получения дополнительной информации о синтаксисе шаблонов glob, см. документацию по node-glob и minimatch.

Динамическое создание объекта files

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

expand Установите значение true, чтобы включить следующие свойства:

  • cwd Все src совпадения относительны к (но не включают) этому пути.
  • src Шаблон(ы) для сопоставления, относительно cwd.
  • dest Префикс пути назначения.
  • ext Замените любой существующий расширение на это значение в сгенерированных dest путях.
  • extDot Указывает, где расположена точка, обозначающая расширение. Может принимать значения 'first' (расширение начинается после первой точки в имени файла) или 'last' (расширение начинается после последней точки), и по умолчанию установлено в 'first' [Добавлен в 0.4.3]
  • flatten Удалите все части пути из сгенерированных dest путей.
  • rename Встраивает пользовательскую функцию, которая возвращает строку, содержащую новое место назначения и имя файла. Эта функция вызывается для каждого сопоставленного src файла (после переименования расширения и выравнивания).

В следующем примере задача uglify увидит тот же список сопоставлений src-dest для целей static_mappings и dynamic_mappings, так как Grunt автоматически расширит объект dynamic_mappings files в 4 отдельных статических сопоставлениях src-dest — предполагая, что найдено 4 файла — при запуске задачи.

Любое сочетание статических и динамических сопоставлений файлов src-dest может быть указано.

grunt.initConfig({
  uglify: {
    static_mappings: {
      // Because these src-dest file mappings are manually specified, every
      // time a new file is added or removed, the Gruntfile has to be updated.
      files: [
        {src: 'lib/a.js', dest: 'build/a.min.js'},
        {src: 'lib/b.js', dest: 'build/b.min.js'},
        {src: 'lib/subdir/c.js', dest: 'build/subdir/c.min.js'},
        {src: 'lib/subdir/d.js', dest: 'build/subdir/d.min.js'},
      ],
    },
    dynamic_mappings: {
      // Grunt will search for "**/*.js" under "lib/" when the "uglify" task
      // runs and build the appropriate src-dest file mappings then, so you
      // don't need to update the Gruntfile when files are added or removed.
      files: [
        {
          expand: true,     // Enable dynamic expansion.
          cwd: 'lib/',      // Src matches are relative to this path.
          src: ['**/*.js'], // Actual pattern(s) to match.
          dest: 'build/',   // Destination path prefix.
          ext: '.min.js',   // Dest filepaths will have this extension.
          extDot: 'first'   // Extensions in filenames begin after the first dot
        },
      ],
    },
  },
});

Свойство переименования

Свойство rename уникально, поскольку единственно допустимым значением для него является JavaScript-функция. Хотя функция возвращает строку, вы не можете просто использовать строку в качестве значения для rename (это приведёт к ошибке: Property 'rename' of object # is not a function). В следующем примере задача copy создаст резервную копию README.md.

grunt.initConfig({
  copy: {
    backup: {
      files: [{
        expand: true,
        src: ['docs/README.md'],    // The README.md file has been specified for backup
        rename: function () {       // The value for rename must be a function
          return 'docs/BACKUP.txt'; // The function must return a string with the complete destination
        }
      }]
    }
  }
});

При вызове функции dest и соответствующий src путь передаются в функцию и могут быть использованы для возврата выходной строки. В приведенном ниже примере файлы копируются из папки dev в папку dist, а затем переименовываются для удаления слова «beta».

grunt.initConfig({
  copy: {
    production: {
      files: [{
        expand: true,
        cwd: 'dev/',
        src: ['*'],
        dest: 'dist/',
        rename: function (dest, src) {          // The `dest` and `src` values can be passed into the function
          return dest + src.replace('beta',''); // The `src` is being renamed; the `dest` remains the same
        }
      }]
    }
  }
});

Если несколько соответствующих src путей переименовываются в одинаковый конечный пункт назначения (то есть, если два разных файла переименовываются в один и тот же файл), каждый вывод добавляется в массив источников для него.

Шаблоны

Шаблоны, заданные с использованием разделителей <% %>, будут автоматически расширяться, когда задачи будут читать их из конфигурации. Шаблоны расширяются рекурсивно, пока не останется ни одного.

Весь объект конфигурации является контекстом, в котором разрешаются свойства. Кроме того, grunt и его методы доступны внутри шаблонов, например, <%= grunt.template.today('yyyy-mm-dd') %>.

  • <%= prop.subprop %> Расширяется до значения prop.subprop в конфигурации, независимо от типа. Такие шаблоны могут быть использованы для ссылки не только на строковые значения, но и на массивы или другие объекты.
  • <% %> Выполняет произвольный встроенный JavaScript-код. Это полезно для управления потоком или циклов.

Учитывая пример конфигурации задачи concat ниже, запуск grunt concat:sample сгенерирует файл с именем build/abcde.js, объединив баннер /* abcde */ со всеми файлами, соответствующими foo/*.js + bar/*.js + baz/*.js.

grunt.initConfig({
  concat: {
    sample: {
      options: {
        banner: '/* <%= baz %> */\n',   // '/* abcde */\n'
      },
      src: ['<%= qux %>', 'baz/*.js'],  // [['foo/*.js', 'bar/*.js'], 'baz/*.js']
      dest: 'build/<%= baz %>.js',      // 'build/abcde.js'
    },
  },
  // Arbitrary properties used in task configuration templates.
  foo: 'c',
  bar: 'b<%= foo %>d', // 'bcd'
  baz: 'a<%= bar %>e', // 'abcde'
  qux: ['foo/*.js', 'bar/*.js'],
});

Импорт внешних данных

В следующем файле Gruntfile метаданные проекта импортируются в конфигурацию Grunt из файла package.json, а задача плагина grunt-contrib-uglify uglify настроена на минимизацию исходного файла и динамическое создание комментария баннера с помощью этих метаданных.

Grunt имеет методы grunt.file.readJSON и grunt.file.readYAML для импорта данных в формате JSON и YAML.

grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    dist: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'dist/<%= pkg.name %>.min.js'
    }
  }
});

© GruntJS Team
Licensed under the MIT License.
https://gruntjs.com/configuring-tasks

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API