Пишем ХабраКвест на ASP.NET Core и Angular2

Каждый раз с выходом нового фреймворка, хочется попробовать его в деле и написать на нем какое-то приложение. В прошлый раз отлично зашел формат квеста. По этому предлагаю посмотреть что поменялось за почти полтора года и написать еще один квест— и фреймворки посмотрим, и поиграть можно.
Результат:
 — сорсы на гитхабе для тех, кому интересно посмотреть на исходники
 — линк на квест для тех, кому интересно что получилось или потратить свое время на еще один логический квест.
b7f32549705e424db4e7f2f9d67cccb5.png
Под катом описан полный процесс от создания проекта до его развертывания.

Предварительные требования


Для работы с ASP.NET Core и Angular2 подойдет почти любая IDE или текстовый редактор. Конечно для полноценной отладки ASP.NET нужна Visual Studio, но с выходом новой Core версии для разработки она не обязательна, можно работать с кодом в Sublime\Atom\… и запускать приложение (предварительно установив SDK) из командной строки, с помощью:
dotnet run

Исходный код, инсталлятор, документацию для интерфейса командой строки .NET и SDK можно найти на:
dotnet.github.io
При чем все это теперь доступно не только лишь на Windows, но и на Max, Linux, а так же Docker.

Наверное, многие испытают когнитивный диссонанс, увидев

sudo apt-get install dotnet-dev-1.0.0-preview2-003121

Создаем проект


Для создания нового ASP.NET core приложения есть несколько путей:
1) С помощью Visual Studio
2) Из консоли — dotnet new
3) Используя сторонние генераторы.

Не будем углубляться во все проблемы создания и конфигурирования проекта, тем более что нам нужно не пустое приложение, а уже с подключенным Angular2 и, желательно настроенными билд скриптами.
Для этого идеально подходит ASP.NET Core JavaScript Services github.com/aspnet/JavaScriptServices, который позволяет создавать приложения для ASP.NET Core с JavaScript фреймворком на выбор: Angular 2, React, и Knockout.
Для этого нам потребуется: ASP.NET Core, Node.js и генератор yeoman с шаблоном aspnet-spa. Последний можно установить с помощью:

npm install -g yo generator-aspnetcore-spa

Теперь создание нового проекта сводится к
cd <папка_для_проекта>
yo aspnetcore-spa

59f9242d4f0c4a34bd2aa4f55ddb0422

Выбираем Angular2 шаблон, название проекта и генератор сам создаст всю структуру, зависимости и т.д. (это может занять несколько минут).
Сначала может показаться, что этот генератор использует слишком много библиотек, особенно, если вы не любитель последних или же мало работали с фронт-ендом. Но лично мое мнение — что это один из наиболее сбалансированных шаблонов. Особенно хочется выделить следующие свойства:

TypeScript


Конечно же разрабатывать приложения на Angular2 можно и на простом JavaScript, TypeScript дает нам возможности типизации, автодополнения, более привычный (для большинства) синтаксис для ООП. А также команда Angular2 активно использует TypeScript и похоже на то, что TypeScript будет (или уже есть) не официальным языком по умолчанию для Angular2.

Webpack


Похоже, что webpack быстро становится фаворитом в битве инструментов для фронт-енда. Особенно важно заметить его возможности при постоянном изменении кода. Фактически разработчику можно забыть о том, чтобы постоянно пересобирать проект и обновлять страницу с помощью Горячей Подмены Модулей (Hot module replacement — HMR). После того как попробовали писать фронт-енд на одном мониторе, в то время как на втором он на глазах меняется уже не хочется возвращаться назад, на инструменты без возможности горячей подмены.

Другие бонусы


Серверный пре-рендер, ленивая загрузка, удобная работа с Development и Production билдами.
Больше можно узнать в блоге одного из разработчиков JavaScriptServices:
blog.stevensanderson.com/2016/05/02/angular2-react-knockout-apps-on-aspnet-core
или же увидеть реальный пример в одном из последних публичных стенд-апов команды ASP.NET:

Собираем проект


Как уже говорилось раньше, чтобы собрать и запустить проект, можно воспользоваться консольной командой:
dotnet run

Как результат, сайт будет собран и запущен локально:
872d38b97f8345319ab5c96a64add017

Или же, сделать тоже самое из Visual Studio.
Если после билда у вас будет уведомление, что не все модули npm установлены,
6564f5b5ee574d7eb18ea78c2ef7b695
скорее всего это проблема с тем, что один из модулей не поддерживается в Windows, но по скольку зависимость не обязательная, приложение должно работать нормально.

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

Приступаем к работе


Рассмотрим главные отличия, в сравнении с предыдущими версиями фреймворков.

Структура проекта


Похоже, структура проекта JavaScriptServices webpack-ориентирована. То есть это npm + webpack, соответственно отсутствуют gulp и bower. На сколько я понимаю bower просто решили не добавлять в стартовый проект, так как нет много зависимостей от JavaScript библиотек, со всем справляется npm. А все функции gulp (или grunt) теперь выполняет webpack.

Что касается файловой структуры, то по части серверных файлов все так же, как и раньше, а вот на front-end есть некоторые отличия. Например, в папке со статическими файлами wwwroot есть только папка dist, куда, фактически, компилируется весь JavaScript.
В сравнении с первой версией Angular бросается в глаза то, что нет никаких представлений и контроллеров — все в компонентах и для каждой html части компоненты есть TypeScript часть.

Особенности в процессе


Webpack конечно очень радует в плане горячей замены модулей, разработка front-end части из-за этого значительно приятнее.
Стоит так же заметить, что ошибки WebPack отлично показываются уже на уровне ASP.NET, очень удобная интеграция. Правда после ошибочного состояния (например, подтягивание не существующей компоненты) горячая замена у меня не заработала, возможно в таких случаях все же надо обновлять страницу вручную.

Так же очень удобно то, что дебажить в браузере можно TypeScript и все это уже встроено по умолчанию
aa86c885bfa241fd97cf0605727a8f8e

В первую очередь я переделал страницы с примерами на те, что нужны мне. Это оказалось очень просто, несмотря на то, что мои знания Angular2 и TypeScript близки к нулю. Вообще синтаксис нового Angular кажется очень читабельным, как минимум с первого взгляда. А возможность описывать интерфейсы, классы и типы в TypeScript делают его очень понятным.
Пример простой компоненты:
0d710746fe3d4107afe81cc8d08063c7
Думаю большинство разработчиков, которые видят TypeScript в первый раз сразу поймут что здесь происходит.

Entity Framework и база данных


Если вы знакомы с предыдущими версиями Entity Framework то с Entity Framework Core проблем возникнуть не должно. В крайнем случае — можно просмотреть документацию на docs.efproject.net/en/latest/intro.html

Сначала ставим nuget пакеты для самого EF, а также для инструментов для работы с базой (версия последнего пока не стабильна):

Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Tools –Pre

github.com/gbdrm/HabraQuest/commit/959f4cb6c253dad0cc5e6eb34756ee5cc9c920f9

Дальше, добавляем команды инструментов в project.json, для этого открываем его, находим настройки tools и добавляем

"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",

Возможно в вашем шаблоне инструменты уже будут добавлены. Тогда ничего менять не надо.

Добавляем классы модели нашего приложения и DbContext и регистрируем их в Startup.cs.
Ну и конечно ConnectionString в appsettings.json и так же добавляем код для конфигурации в Startup.cs.
github.com/gbdrm/HabraQuest/commit/7411eb4262bdef9f5fb810f6cf7d5a239221c0b5

Следующий шаг, типичная история с миграциями — добавляем начальную миграцию и просим базу обновиться.

Add-Migration Initial
Update-Database

Поскольку база еще не существует, после второй команды она должна быть создана. Это можно проверить, посмотрев, какие базы данных существуют если присоединиться к SQL-серверу с помощью Visual или SQL Management студии.
github.com/gbdrm/HabraQuest/commit/09b42dc0a8e45da1f461b38c2b41d79c4fc0b88a

Давайте добавим простой метод в Home контроллер и попробуем минимально использовать соединение с базой. Добавим метод создания нового игрока, который будем возвращать его токен.
github.com/gbdrm/HabraQuest/commit/e67a322184517aa929d1347f6fd638c6290bf9d3

Если теперь мы запустим приложение, можно протестировать этот метод, добавив /home/registernewplayer в конец адреса. В результате мы должны получить токен нашего игрока.
c4bd9333569143d19b5bb5a3115f3477

Первые шаги в Angular 2


По скольку мы уже создали примитивный back-end, то можем попробовать его использовать на клиенте. Попробуем сделать следующее:
когда новый пользователь заходит на страницу — проверить, есть ли у него cookie с токеном и, если нету, попросить его из сервера. Чтобы не создавать собственный велосипед, попробуем использовать существующую библиотеку для работы с cookie. Например, ng2-cookies.
Для этого нам надо установить ее и подключить в компоненте home.
github.com/gbdrm/HabraQuest/commit/8c7aadd9607a0c4d0a1039707b08b0c4b720112c

Сложно описать мои следующие несколько часов упорной борьбы со стереотипами JavaScript и первого Angular. Оказалось, что во второй версии фреймворка все абсолютно иначе. Могу лишь сказать, что закончилось это тем, что я решил пока не использовать сервисы (решил сначала лучше разобраться с rxjs observable, который активно используется в Angular 2), обновил пакеты до следующего релиз кандидата (четвертого), добавил новые формы (оказалось, что они были сильно переделаны и этот процесс еще не закончен) и решил максимально упросить код (большинство логики в одну компоненту). Для начала нужно сделать что-то рабочее, а потом будем думать о хороших практиках. Так же добавил несколько заглушек на серверную часть.
github.com/gbdrm/HabraQuest/commit/60c8239a89cae2357d0521973e091781027186ba

Из интересных особенностей — то ли студия то ли решарпер умеют подтягивать правильные импорты для TypeScript, так же в большинстве случаев работает штатная навигация по методах. Из-за такого рода особенностей писать код для клиентской части становиться значительно приятней, нету больше чувства, что вы пишете какой-то скрипт, который может упасть где угодно. Вместо этого основные элементы синтаксиса проверяются автоматически и есть уверенность, что все не поломается где-то посредине. А даже если и поломается, то выполнится еще одна проверка на уровне webpack и в результате на странице будет показа ошибка, даже без перезапуска.
35f4a360bfd74ad0b0561bffbd00bcee

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

Весь следующий код не представляет особой важности. В основному это реализация заглушенных моментов. Если вам все же интересно просмотреть — исходники доступны на github.com/gbdrm/HabraQuest

Развертывание


По скольку бек-енд написан на .Net то деплоить наше приложение будем на Azure. Кстати за последние год-полтора тут тоже изменений хоть отбавляй, с первого раза не разберешься что и куда. Для нашего приложения нам достаточно будет создать самый базовый сайт с базой (Web App + SQL).
С деплойментом, как всегда, не очень гладко. Во-первых, он не проходит без ошибок. Сам сайт работает, но в итоге Visual Studio показывает ошибки в каких-то внешних модулях TypeScript. Пока так и не разобрался что это. Во-вторых, бывает, что при открытии сайта вылетает ошибка «TaskCanceledException: A task was canceled». С этим тоже пока не до конца ясно, но похоже проблема где-то на уровне хостинга. И кроме этого, немного поигрался с миграциями.

Хотя, в общем, я этим шагом остался доволен. Очень детальный и понятный лог, все можно сконфигурировать (база, миграции). Первый раз, правда, нужно подождать некоторое время (несколько минут) пока все билдится, копируется. Да и вообще, похоже, что процесс довольно сложный, на сколько я понял сначала все копируется локально, а потом уже перебрасывается на Azure, но это уже детали.

Результат, выводы


Все получилось так, как и планировалось. Новыми фреймворками лично я доволен, с радостью бы на них перешел. Конечно есть еще не очень стабильные моменты, Angular 2 еще и совсем не выпущен официально. Но выглядит все уже довольно интересно и, главное, работает.
Очень радует развитие инструментов, подходов в разработке которые позволяют делать меньше рутинных задач, типа обновления станицы, контролирования структуры базы данных.
Так же, очень много блогов, вопросов, документации в сети, так что с решением типичных задач уже должно быть все просто.

Все результаты можно найти на:
github.com/gbdrm/HabraQuest
habraquest.azurewebsites.net

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

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

  • 28 июля 2016 в 15:44 (комментарий был изменён)

    0

    Простите, но… Первый нах!
    http://habraquest.azurewebsites.net/results
    • 28 июля 2016 в 15:47

      +1

      Быстро вы справились. Учтем :)
    • 28 июля 2016 в 16:12

      0

      Жаль, что «Поехали!» != «поехали»
    • 28 июля 2016 в 16:24

      0

      Ну и вопросики у вас. На 6 остановился, дальше не пошло :)
      • 28 июля 2016 в 16:29

        0

        Я чет тоже не могу врубится в шестой вопрос :(
        • 28 июля 2016 в 16:32 (комментарий был изменён)

          0

          https://habrahabr.ru/post/306292/#comment_9721146
      • 28 июля 2016 в 16:31

        0

        подсказка 1
        Номер задания является его частью!
        подсказка 2
        из (номер задание + текст задания) убрать то, что написано убрать
        • 28 июля 2016 в 16:38

          0

          не подскажете что в 11 вопросе есть последняя аббревиатура. А то слишком много ассоциаций. Например Молдавский лей (MDL)
          • 28 июля 2016 в 16:39

            0

            вы уже сами все сказали :)
            • 28 июля 2016 в 16:43

              0

              блин. Слишком просто получилось думал накрученее будет. Вспомнил школьный курс химии.
      • 28 июля 2016 в 16:31 (комментарий был изменён)

        0

        ответил ниже
      • 28 июля 2016 в 16:33

        0

        5 минут бился. Вспомнил про 4 вопрос и прошел дальше.
    • 28 июля 2016 в 16:24

      0

      Чёрт, я думал, я теперь буду всегда верхний в списке. А оно по алфавиту. Хнык.
  • 28 июля 2016 в 16:17

    0

    У вас в исходниках проекта (клиент) есть бутлоадер для браузера и для сервера. Последний использует angular-universal.


    В самом проекте этот код работает? Или это пока просто заглушка?


    Информации по angular-universal очень мало, и для меня такая информация была бы более интересной, чем все пункты в опросе.

    • 28 июля 2016 в 16:44

      0

      Если честно — то не успел разобраться. Как только пойму, отвечу :)

© Habrahabr.ru