Мы продолжаем нашу колонку по теме ASP.NET5 публикацией от Вячеслава Бобика — .NET-разработчика из компании Radario. В этой статье Вячеслав интересно рассказывает о применении с ASP.NET5 популярных инструментов автоматизации Gulp и Bower c интеграцией в Visual Studio. Предыдущие статьи из колонки всегда можно прочитать по ссылке #aspnetcolumn — Владимир Юнев
В наши дни client-side разработка становиться не менее сложной, чем разработка server-side. Современному frontend разработчику приходится решать множество рутинных задач, таких как: препроцессинг Lass/Scss/Stylus, написание вендорских префисксов, поспроцессинг css, склеивать стили в один файл и многое другое.
Так же, если в команде больше одного frontend разработчика, не плохо бы использовать линтеры для валидации js файлов еще до того как они попадут в продакшн. Если выполнять все эти задачи вручную, то на это уйдет львиная доля рабочего времени, а на решение бизнес задач ничего не останется.
Поэтому у frontend разработчиков есть довольно мощные инстументы, которые берут на себя выполнение множетсва рутинных задач, такие как: gulp и bower, а в новом ASP.NET5 они поставляются из коробки. Давайте рассмотри на примере ASP.NET5 приложения, как мы можем использовать gulp и bower.
Gulp
Gulp — это утилита для автоматизации сборки проекта и улучшения рабочего процесса. Основная единица выполняющая нашу задачу так и называется — task. Давайте создадим пустой ASP.NET5 проект.
В корень проекта добавим NPM Configuration file и назовем его package.json
Чтобы использовать gulp в нашем проекте, его необходимо установить. Для этого в файле package.json, в “devDependencies” пишем "gulp": "3.9.0". Все задачи для gulp описываются в специальном для него файле — Gulp configuration file, добавим его.
После добавления файла, он по умолчанию содержит переменную gulp, и задачу с именем default. Если мы напишем внутри задачи console.log ("Hello Gulp"); и выполним её (для этого правой кнопкой мыши необходимо щелкнуть по gulp.js и кликнуть по Task Runner Explorer, дале дважды кликнем по задаче default).
у нас появится следующее окно, в котором мы и увидим результат работы нашей задачи
После небольшого hello-world, давайте напишем что-то более полезное, например процессинг из less в css.
Сначала необходимо подключить gulp-less плагин, для этого открываем снова package.json и в "devDependencies" необходимо добавить "gulp-less": "3.0.3".
Создадим простой main.less файл с таким содержимым:
@base: #f938ab;
.main {
color: @base
}
В итоге, наш проект должен выглядеть как-то так:
Теперь в gulp.js добавим инициализацию gulp-less плагина, а так же задачу по процессингу из less в css.
var gulp = require('gulp'),
less = require('gulp-less');
gulp.task('less', function () {
gulp.src('./Content/less/**/*.less')
.pipe(less())
.pipe(gulp.dest('./wwwroot/' + 'css'));
});
gulp.task('default', function () {
console.log("Hello Gulp"); });
Что делает gulp очень изящным инструментом — это технология потоковой передачи данных для организации процесса сборки. Поскольку все данные передаются напрямую в буфер, пропадает необходимость в создании временных файлов. Вся работа внутри задачи происходит в виде конвеера(pipe). В задаче ‘less’ мы на вход подаем наши less файлы, процессим их, и сохраняем в директорию wwwroot/css. В новом ASP.NET5 директория wwwroot является домашней директорий для проекта, поэтому все статические файлы следует сохранять в неё. После выполнения задачи наш проект будет выглядеть так:
Файл core.css будет содержать в себе:
body {
color: #f938ab;
}
Мы рассмотрели примеры простые примеры уровня hello-world, но в реальных проектах обычно все несколько сложнее, и уже простым выполнением задач не отделаешься. Что если перед запуском одной задачи нам необходимо выполнить каик-то подготовительные действия? Для этого gulp позволяет нам использовать dependent task, когда выполнение одной задачи зависит от другой.
Давайте создадим простую задачу, которая пишет в лог:
gulp.task('dependent', function () {
console.log('hello from dependent gulp task')
}); и модифицируем нашу задачу по препроцессингу less вот таким образом:
gulp.task('less', ['dependent'], function () {
gulp.src('./Content/less/**/*.less')
.pipe(less())
.pipe(gulp.dest('./wwwroot/css'));
});
Запустим задачу less, и если все получилось, то мы увидим следующее:
Как мы видим, довольно легко и удобно gulp избавляет нас от рутинных задач.
Bower
В мире server-side разработки если мы хотим включить в проект какую-либо стороннюю библиотеку, то первое, что приходить на ум это установить её с помощью пакетного менеджера например: nuget, gem или easyinstall. Идея управлять зависимостями в проекте с помощью “пакетов” очень удобна и стара как наш мир, однако для client-side только в 2012 году, усилиями двух разработчиков из Twitter, было положено начало для bower. Bower — это менеджер пакетов для вэба, который довольно быстро стал стандартом дэ фактом в управлении зависимостями для front-end разработки.
ASP.NET5 не стал исключением, и предпочтительным способом в установке front-end библиотек(jquery, bootstrap, и т.д), как раз является bower. Давайте посмотрим на него в действии.
За описание всех client-side зависимостей в проекте отвечает Bower Configuration File, добавим его в проект.
Теперь, давайте добавим в наш проект jquery. Для этого откроем bower.json и в "dependencies" добавим "jquery": "2.1.4", visual studio, с помощью автокомплита, покажет нам последнюю стабильную версию пакета.
Обратите внимание на то, что версия пакета одна, а bower предложил нам три варианта. Все дело в том, что на версионирования пакетов bower использует semantic versioning. Тильда “~” означает, что bower загрузит версию 2.1.4 и любые патчи к ней. Например если мы решим обновить наши пакеты через bower update и следующая версия jquery 2.1.5, то bower обновит её. В случае если же следующая версия jquery 2.2.0 или 3.0 bower проигнорирует обновление. Символ “^” говорит bower загружать любые версии библиотеки в пределах >=2.1.4 < 2.0.0.
Естественно, если это необходимо, мы можем указать версию ниже, но для примера воспользуемся самой последней. Сохраняем файл(Ctrl + S), и visual studio автомагически скачает нам пакет с jquery, и положет его в wwroot/lib. Дерево нашего проекта теперь выглядит как-то так:
Как мы видим пакет содержит не только нужный нам jquery.js, а еще много всего. На мой взгляд это небольшой минус bower пакетов, который решается довольно просто: мы можем написать не сложную gulp task для удаления всего лишнего из wwroot. Для использования jquery осталось вставить во вью(или лэйаут) ссылку вида.
<script src="~/lib/jquery/dist/jquery.js"></script>. Если путь кажется длинным и не очень красивым, то опять же, это все можно решить с помощью gulp.
Вот так, с помощью bower очень легко и просто управлять зависимостями, а самое главное на мой взгляд то, что они все описаны в одном месте. Помимо удобного обновления, это позволит минимизировать риск расхождения версий одной и той же библиотеки в рамках проекта.
Заключение
В этой статье мы узнали об основных инструментах client-side разработки в ASP.NET 5. Попробовали выполнение простых и зависимых задач на gulp, остановились на установке пакетов с помощью bower, который позволяет избежать “dependency hell” в проекте. Здорово что ребята из Microsoft встроили эти инструменты в ASP.NET 5, и нет нужды тратить время на настройку инфраструктуры вокруг проекта или на написание своих решений.
Авторам
Друзья, если вам интересно поддержать колонку своим собственным материалом, то прошу написать мне на vyunev@microsoft.com для того чтобы обсудить все детали. Мы разыскиваем авторов, которые могут интересно рассказать про ASP.NET и другие темы.
Об авторе
Бобик Вячеслав Борисович,
Разработчик .NET в Radario
Молодой .Net программист, с 3 годами опыта. Разработчик на ASP.NET MVC, автор приложений для Windows и Windows phone.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Комментарии (30)
x512
14.10.2015 11:461)По последнему видео от разработчиков www.youtube.com/watch?v=wWfpAY4c3dg&list=PL0M0zPgJ3HSftTAAHttA3JQU4vOjXFquF&index=0 примерно после 36 минуты говорится, что большинство рутинных операций для сборки frontend будут доступно без gulp. Можете прокомментировать?
2)Тут хотелось бы еще услышать про компиляцию TypeScript. Как её лучше делать — через gulp, .tsproject или будут встроенные средства в VS. Есть ли примеры на эту тему?masterL
14.10.2015 13:57Вероятно, имеется в виду использование WebEssentials.
x512
14.10.2015 14:04Я так понял, что они реализуют часть функционала WebEssentials внутри VS
Taritsyn
14.10.2015 21:23Большая часть функционала Web Essentials перенесена в отдельные расширения: Bundler & Minifier, Web Compiler и Web Analyzer. Рекомендую вам прочитать статью Мэдса Кристенсена «Bundling, minification and client-side compilation».
AndrewMayorov
14.10.2015 22:55TypeScript уже включен в студию, начиная с 2013 Update 2.
x512
14.10.2015 23:46Включен, но настройка его компиляции достаточно ограничена. Неясно, как группировать файлы для компиляции в единый JS и использовать AMD лоадеры с получившимися файлами. Мой вопрос — использовать gulp или более совершенные инструменты будут в VS из коробки.
mtt
Зачем нужно сохранять сгенерированные css в виде файлов? System.Web.Optimization прекрасно отдает их на лету, в проекте нужны только исходники на less/sass
leschenko
Скорее всего для того, чтобы не тратить процессорное время на их генерацию.
mtt
Оно тратится только один раз при старте приложения. И уж те доли миллисекунд которые тратятся, роли совершенно не играют.
masterL
Возникает проблема с shared-hosting, где приложение выключается при простое и соответственно часто стартует.
mtt
Так в чем проблема то? Преобразование, минификация и объединение быстро и прозрачно, делается автоматом и отлично кэшируется.
masterL
Проблема в перегенерации файлов при старте приложения — это занимает время, из-за чего увеличивается время старта приложения.
mtt
Еще раз, никаких файлов как таковых не генерируется. Закэшированный результат преобразования отдается из памяти сразу в выходной поток
leschenko
Вот здесь уже ответили почему нельзя в ASP.NET 5 Core.
Для полноценного ASP.NET при условии shared-хостинга расход памяти для кешей файлов (тогда, когда можно без этого обойтись) тоже не очень хорошее решение.
К тому же нет нуджы добавлять сгенерированный контект непосредственно в проект. В проекте у вас исключительно исходники. Все то, что создается при сборке и деплое — дело другое.
mtt
т.е. очередной хороший компонет .net выброшен, ради привлечения разработчиков на Linux и Mac
Хостинг уже переместился в облака, где память доступна гигабайтами. Кэш сжатых css и javascript занимает десятки килобайт. Так что аргумент расхода памяти тоже несущественен.
leschenko
1. Вы путаете причину и следствие. Не ради Linux делали, ASP.NET 5 Core, а благорадя глубогому рефакторингу стало возможно его запускать на Linux. Да, кучу легаси удалили. Да, не все еще реализовали. Но еще не релиз.
2. Память гигабайтами стоит гигаденег. шаредхостинг есть и в облаках.
masterL
Закэшированный результат ведь не сохраняется между перезапусками приложения? И при запуске его нужно генерировать снова? — Именно это время на генерацию я и имел в виду.
Taritsyn
Потому что System.Web.Optimization не совместим с ASP.NET 5 Core.
XaocCPS
CDN
mtt
Т.е. нужно разрабатывать фронтэнд на less/sass, потом с помощью Gulp генерировать css, потом переносить из проекта во внешний CDN, и потом на все это смотреть в браузере? Если уж идет речь о CDN, то не проще ли разработчику прямо в студии получать скомпилированный css?
Taritsyn
Главной причиной добавления поддержки Gulp в шаблоны проектов новой версии ASP.NET является ее кроссплатформенность. Предполагается, что часть разработчиков будет писать ASP.NET 5 Core приложения на компьютерах, на которых установлены Linux и Mac OS. Как правило, эти разработчики уже знакомы с Node.js, Grunt, Gulp и Bower.
Если эти инструменты кажутся вам неудобными, то вы можете использовать вместо них VS-расширения, разработанные Мэдсом Кристенсеном: Bundler & Minifier, Web Compiler и Web Analyzer.
mtt
Таким образом весь этот стэк технологий Node.js, Grunt, Gulp и Bower насильно встраивается в asp.net только ради того чтобы повысить привлекательность .net для alternative-windows аудитории. И при этом для pro-windows разработчиков закрываются целые направления .net, вроде webforms, несмотря на огромное количество наработок, опыта, сторонних компонентов и проектов в поддержке.
justmara
Как .net-разработчик, я только всячески приветствую как можно скорейшее закапывание WebForms в землю. Эта «технология» изначально была создана только для упрощения процесса перетаскивания всех этих VisualBasic/Delphi разрабов в веб. И изначально убога, ущербна и изобилует такими кошмарными костылями, что туда ей и дорога.
Я могу понять вой тех «несчастных», которые сделали ставку на то, чтоб доить разрабов, которые упёрлись в потолок, возникший на пересечении ограничений aps.net из коробки и собственных возможностей… Но что поделаешь. Если не успели поймать ветер mbc, то всё дальнейшее развитие вам тоже будет болезненно.
mtt
Что такое ветер mbc? И что такого убогого и ущербного в webforms? Говнокод можно плодить везде, на любой технологии. Посмотреть сейчас на код во вьюхах на более-менее крупных проектах, так от этого винегреда из html, c#, javascript, css и серверных тэгов кажется что это не развитие, а шаг назад на 15 лет в классический asp. Webforms дает более-менее формальное разделение между программированием и версткой, удачно разделяя бизнес логику и визуальное представление.
justmara
mbc это опечатка mvc. С телефона писал и когда заметил — уже исправить нельзя было.
Ну, начнём со ViewState и всего с ним связанного. А с ним связано всё.
Продолжим костылями типа UpdatePanel, мракобесной цепочки HttpModule/HttpFilter/HttpHandler. А на закуску DataBinding в контексте событийной модели — вот там самные прекрасные танцы.
Агада. Прям учит, как надо разделять их. Контролы, на события которых можно подписываться прям в шаблоне, там же рядом прописывая Css-свойства и вставляя туда же биндинги на DataSource…
Возможно, вас память обманывает, скрывая плохое. Но изначально в ASP.NET не было даже precompiled web application и не было code behind. Т.е. весь код, шаблон и css были в одном файле, разделённые самым прекрасным блоком на свете:
Т.е. то, что вы сейчас называете WebForms — это результат тринадцати лет непрерывных попыток костылями и подпорками продержать всё это мракобесие на плаву.
Учитывая, что первый MVC вышел в 2009м году и уже тогда был просто божественным откровением (т.е. ещё шесть лет назад всем было понятно, насколько WebForms несостоятелен) — то ныть сейчас про накопленный багаж "наработок, опыта, сторонних компонентов" довольно самокритично.
mtt
Если вы не умеете использовать ViewState — то не используйте. Можете вообще отключить его, если вас напрягает скрытое поле. В mvc вы как то обходитесь без сохранения состояния страницы, и там тоже можете. Просто в webforms это дополнительная фича, для тех кто понимает зачем она нужна.
DataBinding в webforms прекрасен. Вы управляете биндингом из C# — из языка программирования, а не языка верстки. Вы можете использовать всю объектную модель и алгоритмическую мощь языка. Вы можете абстрагироваться на любое количество уровней в вашей архитектуры. Обрабатывая события вы можете писать сколь угодно сложные алгоритмы обработки данных. Архитектура mvc разрешает вам только одно действие — швырнуть модель во вью. Если вам нужны хотя бы минимальная обработка данных из модели перед отображением, ваша вьюха разрастается до адовой помойки серверного кода вперемешку с html, javascript, css и хорошо если не sql
Taritsyn
Я бы не сказал, что технологии на базе Node.js встраиваются в ASP.NET. Наличие этих технологий в шаблонах проектов и инструментарии Visual Studio не означает, что они часть ASP.NET. В проектах, написанных на ASP.NET 5 Core вы можете использовать вместо них другие технологии: VS-расширения Мэдса Кристенсена или Smidge.
Но нужно понимать, что все современные фронтенд-технологии созданы на базе Node.js (за исключением: Sass, YUI Compressor и Closure Compiler). Никакие .NET-адаптации этих технологий не могут полностью реализовать их функционал – это я говорю вам как автор Bundle Transformer.
kaatula
Я тоже так думал, был фанатом Cassette, а потом родных бандлов
Однако со статичными файлами всё действительно работает как-то повеселее. И в дейплойменте, и в хостинге, и при отладке.
marshinov
Совсем не прекрасно, особенно под нагрузкой, особенно если хотите статику на cookieless-домене с nginx. И совсем плохо с точки зрения независимой работы front и back-команд
GraDea
Есть SPA проекты, которые просто дергают некое общее rest api. В таком случае проект — просто набор статических файлов.