Мы продолжаем нашу колонку по теме 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.
Ваше отношение к Bower и Gulp?

Проголосовало 140 человек. Воздержалось 36 человек.

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

Комментарии (30)


  1. mtt
    14.10.2015 10:35

    Зачем нужно сохранять сгенерированные css в виде файлов? System.Web.Optimization прекрасно отдает их на лету, в проекте нужны только исходники на less/sass


    1. leschenko
      14.10.2015 10:53
      +2

      Скорее всего для того, чтобы не тратить процессорное время на их генерацию.


      1. mtt
        14.10.2015 11:16

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


        1. masterL
          14.10.2015 14:03

          Возникает проблема с shared-hosting, где приложение выключается при простое и соответственно часто стартует.


          1. mtt
            14.10.2015 14:23

            Так в чем проблема то? Преобразование, минификация и объединение быстро и прозрачно, делается автоматом и отлично кэшируется.


            1. masterL
              14.10.2015 15:09

              Проблема в перегенерации файлов при старте приложения — это занимает время, из-за чего увеличивается время старта приложения.


              1. mtt
                15.10.2015 10:35

                Еще раз, никаких файлов как таковых не генерируется. Закэшированный результат преобразования отдается из памяти сразу в выходной поток


                1. leschenko
                  15.10.2015 10:59

                  Вот здесь уже ответили почему нельзя в ASP.NET 5 Core.
                  Для полноценного ASP.NET при условии shared-хостинга расход памяти для кешей файлов (тогда, когда можно без этого обойтись) тоже не очень хорошее решение.
                  К тому же нет нуджы добавлять сгенерированный контект непосредственно в проект. В проекте у вас исключительно исходники. Все то, что создается при сборке и деплое — дело другое.


                  1. mtt
                    15.10.2015 12:06

                    нельзя в ASP.NET 5 Core


                    т.е. очередной хороший компонет .net выброшен, ради привлечения разработчиков на Linux и Mac

                    ASP.NET при условии shared-хостинга расход памяти для кешей файлов


                    Хостинг уже переместился в облака, где память доступна гигабайтами. Кэш сжатых css и javascript занимает десятки килобайт. Так что аргумент расхода памяти тоже несущественен.


                    1. leschenko
                      15.10.2015 14:19

                      1. Вы путаете причину и следствие. Не ради Linux делали, ASP.NET 5 Core, а благорадя глубогому рефакторингу стало возможно его запускать на Linux. Да, кучу легаси удалили. Да, не все еще реализовали. Но еще не релиз.
                      2. Память гигабайтами стоит гигаденег. шаредхостинг есть и в облаках.


                1. masterL
                  15.10.2015 13:24

                  Закэшированный результат ведь не сохраняется между перезапусками приложения? И при запуске его нужно генерировать снова? — Именно это время на генерацию я и имел в виду.


    1. Taritsyn
      14.10.2015 11:08
      +1

      Потому что System.Web.Optimization не совместим с ASP.NET 5 Core.


    1. XaocCPS
      14.10.2015 11:15

      CDN


      1. mtt
        14.10.2015 11:31

        Т.е. нужно разрабатывать фронтэнд на less/sass, потом с помощью Gulp генерировать css, потом переносить из проекта во внешний CDN, и потом на все это смотреть в браузере? Если уж идет речь о CDN, то не проще ли разработчику прямо в студии получать скомпилированный css?


        1. Taritsyn
          14.10.2015 11:58
          +1

          Главной причиной добавления поддержки Gulp в шаблоны проектов новой версии ASP.NET является ее кроссплатформенность. Предполагается, что часть разработчиков будет писать ASP.NET 5 Core приложения на компьютерах, на которых установлены Linux и Mac OS. Как правило, эти разработчики уже знакомы с Node.js, Grunt, Gulp и Bower.

          Если эти инструменты кажутся вам неудобными, то вы можете использовать вместо них VS-расширения, разработанные Мэдсом Кристенсеном: Bundler & Minifier, Web Compiler и Web Analyzer.


          1. mtt
            14.10.2015 13:24
            +1

            Таким образом весь этот стэк технологий Node.js, Grunt, Gulp и Bower насильно встраивается в asp.net только ради того чтобы повысить привлекательность .net для alternative-windows аудитории. И при этом для pro-windows разработчиков закрываются целые направления .net, вроде webforms, несмотря на огромное количество наработок, опыта, сторонних компонентов и проектов в поддержке.


            1. justmara
              14.10.2015 21:23
              +3

              Как .net-разработчик, я только всячески приветствую как можно скорейшее закапывание WebForms в землю. Эта «технология» изначально была создана только для упрощения процесса перетаскивания всех этих VisualBasic/Delphi разрабов в веб. И изначально убога, ущербна и изобилует такими кошмарными костылями, что туда ей и дорога.
              Я могу понять вой тех «несчастных», которые сделали ставку на то, чтоб доить разрабов, которые упёрлись в потолок, возникший на пересечении ограничений aps.net из коробки и собственных возможностей… Но что поделаешь. Если не успели поймать ветер mbc, то всё дальнейшее развитие вам тоже будет болезненно.


              1. mtt
                14.10.2015 21:40
                -1

                Что такое ветер mbc? И что такого убогого и ущербного в webforms? Говнокод можно плодить везде, на любой технологии. Посмотреть сейчас на код во вьюхах на более-менее крупных проектах, так от этого винегреда из html, c#, javascript, css и серверных тэгов кажется что это не развитие, а шаг назад на 15 лет в классический asp. Webforms дает более-менее формальное разделение между программированием и версткой, удачно разделяя бизнес логику и визуальное представление.


                1. justmara
                  14.10.2015 23:06
                  +2

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

                  И что такого убогого и ущербного в webforms

                  Ну, начнём со ViewState и всего с ним связанного. А с ним связано всё.
                  Продолжим костылями типа UpdatePanel, мракобесной цепочки HttpModule/HttpFilter/HttpHandler. А на закуску DataBinding в контексте событийной модели — вот там самные прекрасные танцы.
                  Webforms дает более-менее формальное разделение между программированием и версткой, удачно разделяя бизнес логику и визуальное представление

                  Агада. Прям учит, как надо разделять их. Контролы, на события которых можно подписываться прям в шаблоне, там же рядом прописывая Css-свойства и вставляя туда же биндинги на DataSource…
                  Возможно, вас память обманывает, скрывая плохое. Но изначально в ASP.NET не было даже precompiled web application и не было code behind. Т.е. весь код, шаблон и css были в одном файле, разделённые самым прекрасным блоком на свете:
                  <script runat="server" >
                  

                  Т.е. то, что вы сейчас называете WebForms — это результат тринадцати лет непрерывных попыток костылями и подпорками продержать всё это мракобесие на плаву.
                  Учитывая, что первый MVC вышел в 2009м году и уже тогда был просто божественным откровением (т.е. ещё шесть лет назад всем было понятно, насколько WebForms несостоятелен) — то ныть сейчас про накопленный багаж "наработок, опыта, сторонних компонентов" довольно самокритично.


                  1. mtt
                    15.10.2015 11:13

                    Ну, начнём со ViewState и всего с ним связанного. А с ним связано всё.


                    Если вы не умеете использовать ViewState — то не используйте. Можете вообще отключить его, если вас напрягает скрытое поле. В mvc вы как то обходитесь без сохранения состояния страницы, и там тоже можете. Просто в webforms это дополнительная фича, для тех кто понимает зачем она нужна.

                    DataBinding в контексте событийной модели — вот там самные прекрасные танцы


                    DataBinding в webforms прекрасен. Вы управляете биндингом из C# — из языка программирования, а не языка верстки. Вы можете использовать всю объектную модель и алгоритмическую мощь языка. Вы можете абстрагироваться на любое количество уровней в вашей архитектуры. Обрабатывая события вы можете писать сколь угодно сложные алгоритмы обработки данных. Архитектура mvc разрешает вам только одно действие — швырнуть модель во вью. Если вам нужны хотя бы минимальная обработка данных из модели перед отображением, ваша вьюха разрастается до адовой помойки серверного кода вперемешку с html, javascript, css и хорошо если не sql

                    Но изначально в ASP.NET не было даже precompiled web application и не было code behind. Т.е. весь код, шаблон и css были в одном файле, разделённые самым прекрасным блоком на свете:


                    Это ложь. Прекрасным блоком script runat=«server» пользовались только переученные пхпшники. Начиная с самой tech preview в шаблоне была только разметка, а в code behind — логика работы на c#.

                    MVC вышел в 2009м году и уже тогда был просто божественным откровением (т.е. ещё шесть лет назад всем было понятно, насколько WebForms несостоятелен


                    «Божественное» откровение архитектуры MVC это только для тех, кто не умел раньше разделять данные, представление и бизнес логику. Паттерн MVC не имеет никакого отношения к asp.net и вэбу вообще. Даже консольные прихожения в командной строке вы можете написать с помощью этого архитектурного решения. Если выбирать между кастомным разделением уровней приложения и mvc, то для любого проекта сложнее гестбука на вашей homepage лучше выбрать свою собственную архитектуру, адаптированную для вашего проекта. Если выбирать между mvc и отсутствием разделения данных, представлений и логики, то уж лучше используйте mvc, чем вообще ничего.


            1. Taritsyn
              14.10.2015 21:56

              Я бы не сказал, что технологии на базе Node.js встраиваются в ASP.NET. Наличие этих технологий в шаблонах проектов и инструментарии Visual Studio не означает, что они часть ASP.NET. В проектах, написанных на ASP.NET 5 Core вы можете использовать вместо них другие технологии: VS-расширения Мэдса Кристенсена или Smidge.

              Но нужно понимать, что все современные фронтенд-технологии созданы на базе Node.js (за исключением: Sass, YUI Compressor и Closure Compiler). Никакие .NET-адаптации этих технологий не могут полностью реализовать их функционал – это я говорю вам как автор Bundle Transformer.


    1. kaatula
      14.10.2015 17:57

      Я тоже так думал, был фанатом Cassette, а потом родных бандлов
      Однако со статичными файлами всё действительно работает как-то повеселее. И в дейплойменте, и в хостинге, и при отладке.


    1. marshinov
      14.10.2015 23:18

      Совсем не прекрасно, особенно под нагрузкой, особенно если хотите статику на cookieless-домене с nginx. И совсем плохо с точки зрения независимой работы front и back-команд


    1. GraDea
      15.10.2015 15:34

      Есть SPA проекты, которые просто дергают некое общее rest api. В таком случае проект — просто набор статических файлов.


  1. x512
    14.10.2015 11:46

    1)По последнему видео от разработчиков www.youtube.com/watch?v=wWfpAY4c3dg&list=PL0M0zPgJ3HSftTAAHttA3JQU4vOjXFquF&index=0 примерно после 36 минуты говорится, что большинство рутинных операций для сборки frontend будут доступно без gulp. Можете прокомментировать?
    2)Тут хотелось бы еще услышать про компиляцию TypeScript. Как её лучше делать — через gulp, .tsproject или будут встроенные средства в VS. Есть ли примеры на эту тему?


    1. masterL
      14.10.2015 13:57

      Вероятно, имеется в виду использование WebEssentials.


      1. x512
        14.10.2015 14:04

        Я так понял, что они реализуют часть функционала WebEssentials внутри VS


        1. Taritsyn
          14.10.2015 21:23

          Большая часть функционала Web Essentials перенесена в отдельные расширения: Bundler & Minifier, Web Compiler и Web Analyzer. Рекомендую вам прочитать статью Мэдса Кристенсена «Bundling, minification and client-side compilation».


    1. AndrewMayorov
      14.10.2015 22:55

      TypeScript уже включен в студию, начиная с 2013 Update 2.


      1. x512
        14.10.2015 23:46

        Включен, но настройка его компиляции достаточно ограничена. Неясно, как группировать файлы для компиляции в единый JS и использовать AMD лоадеры с получившимися файлами. Мой вопрос — использовать gulp или более совершенные инструменты будут в VS из коробки.