Использование Grunt¶
Grunt - это инструмент JavaScript по запуску задач, который автоматизирует минимизацию скриптов, компиляцию TypeScript, работу с инструментарием, отвечающим за качество кода, CSS препроцессоры, и многие другие вещи, которые поддерживают разработку на клиентской стороне. Grunt полностью поддерживается Visual Studio, а шаблоны ASP.NET используют Gulp по умолчанию (см. Использование Gulp).
Sections:
В этом примере используется шаблон Empty ASP.NET Core, чтобы вы увидели, как автоматизировать процесс сборки с нуля.
В законченном примере будет очищена целевая директория развертывания, будут скомбинированы JavaScript файлы, будет проверено качество кода, будет сжат контекст JavaScript файлов, и приложение будет развернуто. Мы станем использовать следующие пакеты:
- grunt: Пакет Grunt для запуска задач.
- grunt-contrib-clean: Плагин, который удаляет файлы или директории.
- grunt-contrib-jshint: Плагин, который просматривает качество JavaScript кода.
- grunt-contrib-concat: Плагин, который объединяет файлы в один.
- grunt-contrib-uglify: Плагин, который минимизирует JavaScript.
- grunt-contrib-watch: Плагин, с помощью которого можно просмотреть активность файлов.
Подготовка приложения¶
Для начала настройте новое empty веб приложение и добавьте файлы примера TypeScript. TypeScript автоматически компилируются в JavaScript с помощью настроек по умолчанию Visual Studio, и это будет наш стартовый материал для работы с Grunt.
- В Visual Studio создайте новое
ASP.NET Web Application
. - В диалоговом окне New ASP.NET Project выберите шаблон ASP.NET Core Empty и нажмите кнопку OK.
- В Solution Explorer просмотрите структуру проекта. Папка
\src
включает в себя пустыеwwwroot
иDependencies
.

- Добавьте новую папку
TypeScript
в директорию проекта. - Перед добавлением файлов давайте убедимся, что в Visual Studio есть опция ‘compile on save’ для TypeScript файлов. Tools > Options > Text Editor > Typescript > Project

- Кликните правой клавишей мышки по директории
TypeScript
и выберите из контекстного меню Add > New Item. Выберите элемент JavaScript file и назовите файл Tastes.ts (расширение именно *.ts). Скопируйте в файл строку TypeScript (после сохранения появится новый файл Tastes.js с исходником JavaScript).
enum Tastes { Sweet, Sour, Salty, Bitter }
- Добавьте в директорию TypeScript второй файл и назовите его
Food.ts
. Скопируйте в файл код снизу.
class Food {
constructor(name: string, calories: number) {
this._name = name;
this._calories = calories;
}
private _name: string;
get Name() {
return this._name;
}
private _calories: number;
get Calories() {
return this._calories;
}
private _taste: Tastes;
get Taste(): Tastes { return this._taste }
set Taste(value: Tastes) {
this._taste = value;
}
}
Настройка NPM¶
Далее, настройте NPM, чтобы скачать grunt и задачи grunt.
- В Solution Explorer кликните правой клавишей мышки по проекту и выберите из контекстного меню Add > New Item. Выберите элемент NPM configuration file, оставьте имя по умолчанию,
package.json
, и нажмите кнопку Add. - В файле package.json внутри объектных фигурных скобок
devDependencies
введите “grunt”. Выберитеgrunt
из списка Intellisense и нажмите клавишу Enter. Visual Studio выделит кавычками имя пакета grunt и добавьте двоеточие. Справа от двоеточия выберите последнюю стабильную версию пакета вверху списка Intellisense (нажмитеCtrl-Space
, если Intellisense не появился).

Примечание
NPM использует семантическое версирование для организации зависимостей. Семантическое версирование, также известное как SemVer, определяет пакеты с помощью схемы <major>.<minor>.<patch>. Intellisense упрощает семантическое версирование, показывая только несколько подходящих вариантов. Самый верхний элемент в списке Intellisense (0.4.5 в примере выше) считается последней стабильной версией пакета. Символ ^ соответствует самым последним главным версиям, а знак ~ соответствует самым последним второстепенным версиям. См. NPM semver.
- Добавьте несколько зависимостей в пакеты grunt-contrib* для clean, jshint, concat, uglify и watch, как показано в примере ниже. Версии не обязательно должны соответствовать версиям в примере.
"devDependencies": {
"grunt": "0.4.5",
"grunt-contrib-clean": "0.6.0",
"grunt-contrib-jshint": "0.11.0",
"grunt-contrib-concat": "0.5.1",
"grunt-contrib-uglify": "0.8.0",
"grunt-contrib-watch": "0.6.1"
}
- Сохраните файл
package.json
.
Будут скачаны пакеты для каждого элемента devDependencies наряду с любыми файлами, которые требуются для каждого пакета. Вы можете найти файлы пакетов в директории node_modules
, нажав на кнопку Show All Files в Solution Explorer.

Примечание
При необходимости вы можете вручную восстановить зависимости в Solution Explorer, если кликните правой клавишей мышки по Dependencies\NPM
и выберите опцию Restore Packages.

Настройка Grunt¶
Grunt использует Gruntfile.js
, который определяет, загружает и регистрирует задачи, которые могут запускаться автоматически или вручную, основываясь на событиях Visual Studio.
- Кликните правой клавишей мышки по проекту и выберите Add > New Item. Выберите опцию Grunt Configuration file, оставьте имя по умолчанию,
Gruntfile.js
, и нажмите на кнопку Add.
Начальный код включает в себя определение модуля и метод grunt.initConfig()
. initConfig()
настраивает опции для каждого пакета, а в остальной части модуля загружаются и регистрируются задачи.
module.exports = function (grunt) {
grunt.initConfig({
});
};
- Внутри метода
initConfig()
добавьте опции для задачиclean
, как показано в Gruntfile.js ниже. Задача clean принимает массив строк директории. Эта задача удаляет файлы из wwwroot/lib, а также убирает всю директорию /temp.
module.exports = function (grunt) {
grunt.initConfig({
clean: ["wwwroot/lib/*", "temp/"],
});
};
- Дальше идет вызов
grunt.loadNpmTasks()
. Тогда задачу можно запустить из Visual Studio.
grunt.loadNpmTasks("grunt-contrib-clean");
- Сохраните Gruntfile.js. Файл должен выглядеть примерно так.

- Кликните правой клавишей по Gruntfile.js и выберите из контекстного меню Task Runner Explorer. Откроется окно Task Runner Explorer.

- Убедитесь, что
clean
показана под Tasks в Task Runner Explorer.

- Кликните правой клавишей мышки по задаче clean и выберите из контекстного меню Run. В командном окне отобразится процесс выполнения задачи.

Примечание
Больше не осталось файлов и директорий, которые нужно очистить. Кроме того, вы можете вручную создать их в Solution Explorer, а затем запустить задачу clean для тестирования.
- В методе initConfig() добавьте запись для
concat
.
В массиве свойств src
перечисляются файлы, которые нужно скомбинировать, чтобы их можно было объединить. Свойство dest
присваивает скомбинированным файлам путь.
concat: {
all: {
src: ['TypeScript/Tastes.js', 'TypeScript/Food.js'],
dest: 'temp/combined.js'
}
},
Примечание
Свойство all
- это имя цели. Цели используются в нескольких Grunt задачах, чтобы можно было использовать несколько сред. Вы можете просмотреть встроенные цели с помощью Intellisense или присвоить собственные.
- Добавьте задачу
jshint
.
Задача jshint запускается для каждого JavaScript файла, найденного в директории temp.
jshint: {
files: ['temp/*.js'],
options: {
'-W069': false,
}
},
Примечание
Опция “-W069” - это ошибка, которая создается jshint, если JavaScript при присвоении свойства использует квадратные скобки вместо точечной нотации, например, Tastes["Sweet"]
вместо Tastes.Sweet
. Опция возвращает предупреждение, чтобы позволить процессу продолжить работу.
- Добавьте задачу
uglify
.
Задача минимизирует файл combined.js, найденный в директории temp, и создает результирующий файл в wwwroot/lib, следуя стандартному соглашению по именованию <file name>.min.js.
uglify: {
all: {
src: ['temp/combined.js'],
dest: 'wwwroot/lib/combined.min.js'
}
},
- После вызова grunt.loadNpmTasks(), который загружает grunt-contrib-clean, включите этот же вызов для jshint, concat и uglify.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
- Сохраните
Gruntfile.js
. Файл должен выглядеть приблизительно так.

- Обратите внимание, что список задач Task Runner Explorer включает в себя
clean
,concat
,jshint
иuglify
. Запустите каждую задачу по порядку и просмотрите результат в Solution Explorer. Все задачи должны пройти без ошибок.

Задача concat создает новый файл combined.js и размещает его в директорию temp. Задача jshint просто запускается, но не создает результат. Задача uglify создает новый файл combined.min.js и размещает его в wwwroot/lib. По завершению решение должно выглядеть так:

Примечание
Зайдите на https://www.npmjs.com/ и введите имя пакета в поле поиска. Например, вы можете поискать пакет grunt-contrib-clean, чтобы получить ссылку на документацию, которая объясняет все его параметры.
Теперь все вместе¶
Используйте метод Grunt registerTask()
, чтобы запустить серию задач в конкретной последовательности. Например, чтобы запустить представленные выше задачи в последовательности clean -> concat -> jshint -> uglify, добавьте в модуль данный код. Код должен быть добавлен на том же уровне, что и вызовы loadNpmTasks(), вне initConfig.
grunt.registerTask("all", ['clean', 'concat', 'jshint', 'uglify']);
Новая задача представлена в Task Runner Explorer под Alias Tasks. Вы можете кликнуть правой клавишей мышки и запустить ее, как и любую другую задачу. Задача all
запустит по порядку clean
, concat
, jshint
и uglify
.

Просмотр изменений¶
Задача watch
следит за файлами и директориями. watch запускает задачи автоматически, если изменение найдено. Добавьте данный код в initConfig, чтобы просмотреть изменения в файлах *.js директории TypeScript. Если JavaScript файл меняется, watch
запустит задачу all
.
watch: {
files: ["TypeScript/*.js"],
tasks: ["all"]
}
Добавьте вызов loadNpmTasks()
, чтобы просмотреть задачу watch
в Task Runner Explorer.
grunt.loadNpmTasks('grunt-contrib-watch');
Кликните правой клавишей мышки по задаче watch в Task Runner Explorer и выберите из контекстного меню Run. В командном окне вы увидите сообщение “Waiting…”. Откройте один из файлов TypeScript, добавьте пробел, а затем сохраните файл. Это запустит задачу watch и по порядку другие задачи.

Связывание с событиями Visual Studio¶
Вместо того чтобы постоянно вручную запускать задачи, вы можете связать задачи с событиями Before Build, After Build, Clean и Project Open.
Давайте привяжем watch
, чтобы она запускалась каждый раз, когда открывается Visual Studio. В Task Runner Explorer кликните правой клавишей мышки по watch и выберите из контекстного меню Bindings > Project Open.

Перезагрузите проект. После этого задача watch начнет выполняться автоматически.
Резюме¶
Grunt - это мощный инструмент загрузки задач, который можно использовать для автоматизации большинства клиентских задач. Grunt использует NPM, чтобы получить пакеты для интеграции с Visual Studio. Visual Studio Task Runner Explorer определяет изменения в конфигурационных файлах и предлагает удобный интерфейс для запуска, просмотра и связывания задач с событиями Visual Studio.