Liveблог веб-разработки на Aurelia
Это вторая часть из серии о процессе разработки веб-приложения Aurelia, которая написана так, как это происходит. Целью части 2 является создание простого прототипа приложения с использованием выбранных технологий из части 1. Я займусь настройкой среды разработки, созданием интерфейсного проекта, созданием серверного проекта для API и, наконец, соединю их вместе. Когда я закончу, все должно работать в Azure.
Настройка
Сначала мне нужно убедиться, что у меня установлены все инструменты. Node.js версии 6 только что был выпущен в рамках плана LTS, поэтому я заменяю свой 4.x на 6.9.1, а также обновляю npm, запустив npm install npm -g в командной строке. как администратор. Это дает мне версию npm 3.10.9. Затем с помощью npm я устанавливаю последнюю версию Aurelia CLI, которая сейчас находится в версии 0.21.0. На всякий случай также обновляю Git. Вероятно, потребуется еще несколько установок, если вы не устанавливали ничего из этого раньше, но я думаю, вы легко найдете руководства, чтобы все настроить.
Visual Studio Code - это редактор, которым я буду чаще всего пользоваться. Одной из причин выбора облегченного редактора кода вместо полнофункциональной IDE Visual Studio является недавно выпущенный Плагин Aurelia для VS Code. Я также сделаю несколько заметок для сравнения двух редакторов. Я не очень опытный пользователь VS Code и обычно предпочитаю больше графических интерфейсов, но с Aurelia большую часть тяжелой работы будет выполнять CLI, поэтому ключевыми функциями редактора являются выделение кода, форматирование и intellisense. С серверным C # я, вероятно, по-прежнему буду полагаться на полную IDE.
Создание проекта Aurelia
До сих пор я всегда начинал новый проект Aurelia, копируя официальное приложение-скелет. С помощью интерфейса командной строки я просто запускаю au new и следую инструкциям:
Используя custom-option (3), я создаю проект с транспилированием TypeScript (2), препроцессором Sass CSS (3), включенными модульными тестами и Visual Studio Code в качестве редактора (1). После подтверждения настройки CLI установит все зависимости проекта. Это займет около трех минут. После завершения установки я получаю одно предупреждение о том, что типизация angular-protractor устарела:
Я пока не особо об этом беспокоюсь. Предупреждающее сообщение указывает на некоторые проблемы с типизацией для Protractor (структура сквозного тестирования для приложений Javascript, изначально построенная для AngularJS, но может использоваться с Aurelia). Наверное, позже напишу отдельную часть, посвященную тестированию.
Прежде чем вносить какие-либо изменения в проект, я создаю новый репозиторий проекта на GitHub. На этом этапе я понимаю, что это должен был быть самый первый шаг перед созданием проекта. Итак, чтобы получить репозиторий внутри проекта, я клонирую репозиторий в Github во временную папку и перемещаю папку .git в корень моего проекта (подсказка от stackoverflow). VS Code быстро понимает, что есть репозиторий, и показывает все файлы как изменения. Всего несколько щелчков мышью, и мой первоначальный проект завершен.
Запуск приложения в среде разработки действительно прост благодаря встроенному веб-серверу. Вы просто вызываете au run в командной строке и указываете браузеру правильный URL-адрес, по умолчанию localhost: 9000. Чтобы приложение автоматически перезагружалось при внесении изменений в исходные файлы, добавьте флаг --watch после команды.
Обновлять
На данный момент проходит несколько недель, а у вас нет возможности продолжить писать / развивать проект. Первое, что нужно сделать, вернувшись, - это проверить наличие обновлений для фреймворка и других зависимостей. Особенно это актуально на ранних этапах разработки. Для проектов Aurelia есть инструмент под названием Monterey, который я иногда использую, чтобы проверить, для каких пакетов проекта доступны обновления. Однако в этом случае я решил воссоздать проект с нуля после обновления Aurelia CLI до версии 0.22.0. Есть небольшие отличия в содержании проекта при создании в более новой версии (посмотрите различия).
Пока я занимаюсь этим, я также обновляю остальные пакеты. Сюда входят aurelia-tools (1.0.0), gulp-typescript (3.1.2) и gulp-tslint (6.1.3). После обновления, если вы попытаетесь запустить проект, появится следующее предупреждение:
Это из-за некоторых изменений в интерфейсе gulp-typescript. Исправление так же просто, как и предполагает предупреждающее сообщение, просто небольшое изменение в задаче сборки в aurelia_project / tasks / transpile.ts.
Макет
Далее я попытаюсь заставить работать sass и bootstrap. Sass уже включен в проект благодаря cli, но в нем еще нет стилей. Я хочу иметь возможность использовать переменные начальной загрузки для настройки работы начальной загрузки, поэтому я npm install bootstrap-sass --save-dev. Затем я создаю основную таблицу стилей в src / styles / app.scss. На данный момент он импортирует только все стили начальной загрузки из пакета bootstrap-sass.
Существует несколько различных подходов к включению таблицы стилей в приложение. Старый способ заключался в добавлении тега ссылка в раздел заголовок страницы. Однако по умолчанию Aurelia Cli не выводит обработанные файлы css. Они являются частью исходного кода приложения и будут включены в комплекты. Поэтому вместо прямого связывания css необходимо импортировать через загрузчик модуля. Первая попытка - добавить импорт в код машинописного текста в app.ts:
import 'styles/app.css!';
Это приводит к ошибке в процессе сборки, в результате чего наблюдатель останавливается (что немного раздражает, потому что мне нужно будет перезапускать наблюдатель каждый раз, когда у меня будет опечатка при импорте). Ошибка, похоже, в том, что ! в конце не имеет никакого эффекта, и загрузчик модуля все еще пытается загрузить файл app.css.js, ожидая модуля javascript. После быстрого поиска в Google я заметил раздел Styling your Application в документации Cli, в котором советуется использовать в шаблоне require-element:
<require from=”./styles.css”></require>
Это работает, как ожидалось, и теперь я могу использовать классы начальной загрузки в моем шаблоне html. Все стили, включая весь бутстрап, теперь включены в мой комплект приложения. Приятно отметить, что это добавляет около 154 КБ к размеру пакета, поэтому в некоторых сценариях стоит рассмотреть разделение таблицы стилей на отдельный пакет (с возможностью отдельного кэширования).
Включение загрузочного javascript - это целая история. Bootstrap попадает в категорию устаревших библиотек при использовании с Aurelia Cli и зависит от jQuery. Вдобавок к этому нам нужно будет заняться определениями типов (bootstrap.d.ts in DefinitionsTyped, похоже, не хватает версии 0.0.2) и как-то справиться с тем фактом, что вместо этого мы используем порт bootstrap-sass. пакета начальной загрузки по умолчанию. Оценивая преимущества JS-компонентов против всего этого, я думаю, что пока смогу жить без них. В любом случае большую часть функциональности с Aurelia действительно просто реализовать.
Содержание
У меня пока нет четкого плана относительно цели приложения. Есть несколько идей, но на данный момент я концентрируюсь на том, чтобы все разные части работали вместе. Тем не менее мне понадобится какой-то контент для демонстрации основных функций, таких как вызовы Api. Для этого я воспользуюсь концепцией заметок (например, стикеров или стикеров). Я начну с очень простого компонента Note, в котором есть некоторый контент и ничего больше. Чтобы сделать вещи немного интереснее, я буду использовать contenteditable, чтобы пользователи могли редактировать контент. Вы можете увидеть модель представления в note.ts и шаблон в note.html.
Объезд
Есть библиотеки, которые я мог бы использовать, чтобы сделать редактор контента более удобным для пользователей. Мне очень нравится простота редактора Medium, поэтому после еще одного быстрого поиска в Google я решаю попробовать Medium.js. Прежде всего, загрузите пакет как зависимость для разработки, запустив npm install moment.js --save-dev. Затем я добавляю зависимость для Aurelia Cli в комплекте с другими библиотеками, добавляя строку в массив зависимостей vendor-bundle в aurelia_project / aurelia.json. После неудачных попыток использования библиотеки я понимаю, что ее, вероятно, необходимо включить как устаревшую библиотеку (например, Bootstrap выше), поэтому я добавляю следующие несколько строк на основе примеров документации cli:
{ "name": "medium.js", "path": "../node_modules/medium.js", "main": "medium", "exports": "Medium", "resources": [ "medium.css" ] },
Кажется, это работает, и я могу импортировать библиотеку, добавив import * as Medium из medium.js вверху файла note.ts. В библиотеках, поддерживающих модули, импорт обычно осуществляется в форме import {Object, AnotherObject} из библиотеки, но для устаревших библиотек обычно требуется предыдущий формат. С TypeScript требуется еще один шаг, чтобы библиотека работала с типизированным исходным кодом: определения типов. В большинстве распространенных библиотек определение типа типа доступно либо в официальном дистрибутиве, либо в качестве вклада сообщества (обычно в реестре ОпределенноTyped), но Medium.js, похоже, не имеет ничего доступного. Вы всегда можете написать определение типа самостоятельно, но в качестве обходного пути можно использовать фиктивное определение для предотвращения ошибок компиляции. Проект содержит папку custom_typings для определений настраиваемых типов, в которую можно добавить следующее содержимое в файл с именем medium.d.ts.
declare module ‘medium.js’; declare class Medium { constructor(options?: any); }
Если честно, я не сразу понял это с первого раза. Первая строка - это определение фиктивного модуля, а объявление класса Medium позволяет использовать Medium в качестве класса, как работает исходный модуль, если вы включаете библиотеку как файл javascript, а не с загрузчиком модуля. .
Так все хорошо? Когда я снова создаю объект Medium.js в своей заметке, меня это не впечатляет. Кажется, он ничего не делает, кроме простой установки contenteditable = ”true”, по крайней мере, в Chrome. Возможно, я просто не использую его правильно, но беглый взгляд на репозиторий Medium.js на Github многое объясняет. Практически никакой активности нет, а последний релиз датирован декабрем 2015 года. Официально звучащее название, вероятно, вселило мои надежды. Эта библиотека, вероятно, не стоит усилий, поэтому я возвращаю все свои изменения и возвращаюсь к стандартному contenteditable.
Создать API
Серверное приложение с постоянным хранилищем требуется (ну, не совсем, но мы будем упрощать) для обмена заметками между пользователями и их сохранения. Здесь я стараюсь протестировать возможности использования инструментов Visual Studio / ASP.Net Core / Azure / GitHub, всех технологий, которые должны поддерживаться из коробки. Моя цель состоит в том, чтобы приложение ASP.Net Core работало в Azure, код был передан на GitHub и автоматически развернут из выбранной ветки, а база данных SQL для Api могла подключаться без какой-либо конфигурации в исходном коде.
Процесс создания нового приложения прост. Я создаю новый проект и решение для него, выбираю шаблон ASP.Net Core Web API, ставлю галочки Создать новый репозиторий Git и Хост в облаке, выбираю и / или создаю необходимые службы Azure (в моем случае я выбираю свою подписку, создаю новую группу ресурсов, план службы приложений, службу приложений, сервер sql и базу данных sql) и нажимаю Создать. Затем я открываю окно GitHub, вхожу в свою учетную запись GitHub и публикую свой репозиторий Git. Я вижу первые два коммита, сделанные VS. Пока что все работает достаточно хорошо, хотя Visual Studio один раз дает сбой при просмотре запросов на вытягивание в окне GitHub.
Затем я перехожу на портал Azure, где вижу все вновь созданные ресурсы в выбранной мной группе ресурсов:
Я выбрал продукты уровня Free для всех услуг, поэтому мне не нужно беспокоиться о ценах. Есть некоторые ограничения, но мне не о чем беспокоиться в небольшом и простом прототипе. Интересный момент - автоматическое развертывание. Я разрешаю порталу Azure использовать мою учетную запись GitHub и выбираю репозиторий и ветку (master в настоящее время единственной доступной ветвью). Также есть возможность настроить автоматическое тестирование производительности, поэтому, хотя я действительно не знаю, как это работает, я просто иду и настраиваю это тоже.
Развертывание не запускается автоматически после настройки, поэтому я пытаюсь внести небольшое изменение в репозиторий. Обычно я, вероятно, фиксирую ветку, а затем объединяю ее с master, возможно, из запроса на вытягивание, но теперь я просто иду вперед и фиксирую в master. Кажется, это запускает некоторые действия в Azure, а через некоторое время - целый ряд действий (более 1000 запросов), поэтому я предполагаю, что тесты производительности выполняются. Я перехожу к URL-адресу, а там мой API работает!
Чтобы в какой-то мере контролировать длину этой части 2, я оставляю вопросы, связанные с базой данных, на потом. Теперь мне нужно развернуть Client и заставить его загружать заметки из Api.
Принести!
Я слишком долго избегал выборки. Незадолго до того, как перейти к Aurelia, я прочитал сообщение в блоге от вдохновителя Chrome Джейка Арчибальда, которое до сих пор является одним из лучших объяснений fetch и его преимуществ с очень практичным подходом. Но несмотря на это и на настойчивые рекомендации Аурелии использовать fetch over xhr, это единственная часть, где я оставался на безопасном расстоянии от передового края. Спустя год я все еще не использовал fetch, кроме нескольких быстрых тестов. Я думаю, что пора это изменить, поэтому я использую эту возможность, чтобы освоиться с новым способом извлечения ресурсов из Api.
Хорошее место для начала - Документация Aurelia для HTTP-сервисов. Сначала мне нужно установить aurelia-fetch-client через npm и включить пакет в комплект поставщика. Затем я добавляю класс, который внедряет HttpClient из модуля aurelia-fetch-client. Но после добавления класса приложение не компилируется. Оказывается, TypeScript не имеет Fetch Api в библиотеке определения типов по умолчанию. К счастью, есть простое решение: typing install ds ~ whatwg-fetch --global --save.
«Подожди, что… wg?» Да, синтаксис немного неудобен, но в основном это говорит инструменту набора текста
- определения типов установки из источника ds (вышеупомянутая библиотека DefinentyTyped)
- для спецификации стандартов whatwg Fetch Api
- как глобальная библиотека (глобально доступна как window.fetch ())
- и сохраните детали в typings.json (чтобы легко отслеживать установки и обновления).
Все это работает нормально, но ошибка компиляции все равно остается:
Похоже, что определения для URLSearchParams и ReadableStream все еще отсутствуют. В Google я быстро нахожу решение последнего из проблемы с TypeScript: typings install ds ~ whatwg-streams --global --save. Для URLSearchParams текущее решение в приложении скелета Aurelia кажется отдельным файлом определения типа в репозитории aurelia-fetch-client, который я могу установить с помощью ввода install github: aurelia / fetch-client / doc / url. d.ts --save --global. И с этим у меня, наконец, снова компилируется мой проект, и я могу зафиксировать изменения.
Далее идет фактический код для выборки ресурсов. Чтобы отделить вызовы Api от остальной части приложения, я создаю класс NotesApi, который внедряет HttpClient из библиотеки aurelia-fetch-client. Затем я начинаю писать метод для получения всех заметок из Api. Я очень впечатлен тем, как свободно IntelliSense работает с TypeScript в VS Code, и в равной степени доволен документацией по пакетам Aurelia.
Код для получения ресурса - это простой вызов fetch () для правильной конечной точки в URL-адресе Api и вызов response.json для преобразования данных ответа из строки json в объект javascript ( массив строк в данном случае). Я использую конфигурацию среды в aurelia_project / environment / dev.ts, чтобы установить базовый URL для всех запросов. Чтобы разрешить запрос из другого домена (или порта), мне нужно настроить CORS в серверном приложении.
Наконец, я добавляю привязку данных к компоненту узла и добавляю загрузку и отображение узлов на главной странице. Теперь у меня все заработало, но только локально. Мне все еще нужно развернуть приложение Aurelia в Azure.
Обратите внимание: если вы хотите поддерживать IE (или другие браузеры, не поддерживающие выборку), вам нужно будет использовать polyfill. Это должно быть просто: добавление библиотеки в проект и добавление import ‘fetch’; к основному модулю, но с прототипом я буду придерживаться браузеров, которые его поддерживают.
Развертывать
Последний шаг для запуска и запуска всей системы - это развертывание клиентского приложения в Azure. Простым решением было бы просто запустить au build --env prod и вручную развернуть результат в Azure. Но вместо того, чтобы делать то, что я уже знаю, я попытаюсь построить непрерывное развертывание, как в случае с серверным приложением. Сложность заключается в том, что клиенту требуется запустить au build после извлечения ветки из репозитория git. Для этого мне нужно будет добавить несколько пользовательских сценариев развертывания для Azure, а для этого мне понадобится Azure CLI (или, по крайней мере, это значительно облегчит работу).
Сначала я устанавливаю cli, запустив npm i -g azure-cli (обратите внимание, что вам потребуются права администратора для установки глобальных модулей). Затем я запускаю azure config mode asm, чтобы изменить режим на управление службами (по умолчанию - диспетчер ресурсов). Чтобы создать сценарий развертывания для Kudu, я запускаю azure site deploymentscript --node, который создает файлы .deploy и deploy.cmd для развертывания на основе узлов. После создания веб-приложения Azure и настройки автоматического развертывания из GitHub Azure получит последний код из репозитория, выполнит npm install как указано в deploy.cmd и развернет результат на веб сервер. Единственная оставшаяся проблема - как запустить au build.
Чтобы настроить развертывание в Azure, Kudu предоставит вам максимальный контроль над происходящим. Я новичок в Куду, но сценарий не выглядит слишком сложным для понимания. Чтобы помочь в изучении, я использую консоль Kudu, доступ к которой можно получить с помощью дополнительных инструментов на портале Azure.
В сервисах Kudu я выбираю Debug Console ›CMD в верхнем меню и перехожу в папку site / repository. Там я могу протестировать команды, которые будут запускаться при извлечении новой версии из репозитория.
Чтобы заставить скрипт развертывания работать, требуется довольно много времени. Вот несколько полезных руководств: Начало работы с веб-приложениями Node.js от Microsoft (хотя мое приложение не совсем приложение Node.js, но оно использует узел для развертывания), Kudu wiki и немного устаревшее, но полезное Вики-страница о развертывании Azure, на которую я случайно наткнулся при поиске в Google.
Мне нужно внести несколько изменений в сценарий развертывания. Во-первых, мне нужно изменить порядок команд в части развертывания, чтобы сначала запустить npm install, затем запустить au build и в качестве последнего шага запустить kuduSync для скопируйте файлы в wwwroot. Для сценария сборки я добавляю сценарий build-aurelia в package.json, поэтому мне не нужно искать команду aurelia-client. Среда выбирается путем добавления параметра настройки приложения AURELIA_ENVIRONMENT для веб-приложения на портале Azure. Значение будет доступно в сценарии с тем же именем, поэтому я могу добавить - --env% AURELIA_ENVIRONMENT% в вызов build-aurelia (первое двойное тире необходимо для передачи аргументов. к сценарию ). Я буду использовать stage в качестве среды, поэтому мне также нужно добавить appUrl в конфигурацию среды в aurelia_project / environment / stage.ts. На самом деле я бы предпочел, чтобы URL-адрес был прямо в настройках приложения в Azure, но я могу вернуться к этому позже.
На этом развертывание выполнено, и любые изменения, которые я вношу и отправляю в основную ветку GitHub, автоматически развертываются в Azure.
Что дальше?
Теперь у меня есть работающее приложение Aurelia, поддерживаемое Api, работающим в Azure, с настроенным непрерывным развертыванием. В следующих частях я могу перейти к более конкретным темам, связанным с Aurelia, таким как привязка данных, пользовательские компоненты и шаблоны.