Обновление 23.07.2016 : Несколько человек прокомментировали тот факт, что эта статья сравнивает Aurelia с Angular 1.x вместо Angular 2; это по замыслу. Хотя это правда, что Aurelia против Angular 2 будет более ровным сравнением, эта статья предназначена для людей и компаний, которые в настоящее время привержены Angular 1.x и ищут причины для перехода на более новую платформу, но не уверены в переходе на Угловой 2 и необходимо обосновать соотношение затрат и выгод меняющихся структур. Я хотел предоставить подробное сравнение, чтобы помочь тем пользователям и компаниям принять это решение.
Эта статья была рецензирована Vildan Softic . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!
В мире веб-разработки и JavaScript мы видели множество парадигм. Но осталась одна парадигма: одностраничное веб-приложение.
Один из самых популярных фреймворков за последние шесть лет был AngularJS . Выпущенный в 2010 году и поддержанный Google, он обещал быструю и простую разработку полнофункциональных клиентских приложений благодаря использованию декларативного двустороннего связывания данных. Получив большое количество поклонников, AngularJS быстро зарекомендовал себя как методология разработки веб-приложений, которую используют такие компании, как Amazon и Pluralsight.
Сегодня, в 2016 году, AngularJS начал показывать свой возраст. Новая платформа под названием Aurelia стала популярным выбором для многофункциональных клиентских приложений. Первоначально созданный Робом Айзенбергом из Durandal Inc., Aurelia нацелена на ту же проблемную область, что и AngularJS. Тем не менее, Aurelia использует современный подход для облегчения разработки и решения многих проблем, которые преследуют AngularJS.
В этой статье мы подробно рассмотрим AngularJS и Aurelia, а также сравним и сопоставим эти две среды. В целях этого сравнения мы исключим Angular 2 из нашего каркасного сравнения. Вместо этого мы сосредоточимся только на фреймворке AngularJS 1.x. Сегодня, используя точку зрения разработчика в 2016 году, мы возьмем сравнение методологий AngularJS, разработанных в 2010 г., и современных методологий, используемых Aurelia.
Краткое изложение
И AngularJS, и Aurelia — это клиентские JavaScript-фреймворки, предназначенные для создания одностраничных веб-приложений. И AngularJS, и Aurelia поддерживают интуитивное двустороннее связывание данных, маршрутизацию на стороне клиента и расширенные функции шаблонов. И AngularJS, и Aurelia поощряют расширение HTML с помощью пользовательских элементов. И AngularJS, и Aurelia поставляются с компонентами по умолчанию, объединяющими общие функциональные возможности. Как указывалось ранее, AngularJS и Aurelia ориентированы на одну и ту же проблемную область. Так где же сходство заканчивается?
Давайте кратко рассмотрим основные различия между AngularJS и Aurelia.
AngularJS | Aurelia |
---|---|
патентованный | Стандарты совместимый |
конфигурация | условность |
Сложный | просто |
Дорогие | эффективное |
Исправлена | гибкий |
монолитный | модульная |
Вау — подожди минутку. Вы могли бы сказать, эй — похоже, что вы немного сложили колоду там. Но я бы хотел больше вникнуть в эти претензии.
Собственный (AngularJS) и совместимый со стандартами (Aurelia)
Веб-стандарты развивались в течение шести лет с момента выпуска AngularJS. Хотя AngularJS изначально разрабатывался для соответствия стандартам того времени, он был вынужден создавать множество проприетарных решений для сценариев, в которых не было четко определенных правил. Среди них были стандарты языка JavaScript и шаблоны HTML.
Стандарты языка JavaScript
Язык и экосистема JavaScript постоянно движутся вперед; его стандарты, функции и синтаксис постоянно развиваются. В то время как AngularJS был разработан для использования возможностей веб-браузера в 2010 году, Aurelia была разработана на основе современных стандартов.
AngularJS предоставил нестандартную реализацию формата модуля JavaScript, которая была разработана для использования с инфраструктурой AngularJS. Aurelia, для сравнения, опирается на стандарт модуля ES2015. Кроме того, Aurelia использует преимущества новых языковых конструкций, таких как декораторы ES2016, для упрощения разработки и поддержки новых стандартов.
HTML шаблоны
И AngularJS, и Aurelia позволяют вам, как разработчику, расширять HTML новыми способами. Когда AngularJS был создан, стандарты для расширения HTML еще не созрели. Таким образом, AngularJS создал собственные решения для шаблонов и пользовательских элементов.
Сегодня спецификация веб-компонента определяет набор правил как для шаблонных, так и для пользовательских элементов. Aurelia активно придерживается этих стандартов, поддерживая Shadow DOM, элемент <template>
Конфигурация (AngularJS) против Конвенции (Аурелия)
Когда я впервые начал играть с Angular, я думал, что это круто. Изучение того, как настроить AngularJS с конкретными вызовами кода, не заняло много времени. Однако по мере того, как я чувствовал себя более комфортно с AngularJS и создавал больше приложений, вся конфигурация Angular стала мешать.
AngularJS требует от вас создания специфичного для Angular модуля. По сути, все, что ваше приложение будет использовать, должно быть явно зарегистрировано в фреймворке и настроено до запуска веб-приложения. Таким образом, необходимо подключить все контроллеры, службы и пользовательские директивы к модулю AngularJS, прежде чем их можно будет использовать. Кроме того, контроллеры AngularJS связаны с представлениями через код: представление должно объявить контроллер, который он намеревается использовать. Все это приводит к множеству шаблонов. Давайте посмотрим на пример, используя ES2015.
hello.js
// A Hello controller
export class Hello {
constructor (userService) {
this.userService = userService;
this.greeting = "Hello, " + this.userService.getUser() + "!";
}
};
пользовательский service.js
// A User Service
export class UserService {
getUser () {
return "Newman";
};
};
index.js
import {Hello} from 'hello';
import {UserService} from 'user-service';
// No matter how or where we declare our objects,
// we'll always have to use Angular's registration code
// to let AngularJS know about them.
angular.module('App', []);
.controller('HelloCtrl', Hello)
.service('UserService', UserService)
... and so on
hello.html
<div data-ng-controller="HelloCtrl as hello">
<h1>{{hello.greeting}}</h1>
...my view
</div>
Для сравнения, Aurelia не требует явной регистрации компонентов, прежде чем их можно будет использовать. Фреймворк знает, как найти представления и модели представления без их явной настройки с использованием соглашения по умолчанию. (Это соглашение может быть переопределено при необходимости через конфигурацию, но явная конфигурация не обязательна.) Наконец, модели представления Aurelia не связаны с представлениями кодом внутри представления.
hello.js
// A Hello controller
export class Hello {
constructor (userService) {
this.userService = userService;
this.greeting = "Hello, " + this.userService.getUser() + "!";
}
};
пользовательский service.js
// A User Service
export class UserService {
getUser () {
return "Newman";
};
};
index.js
// We don't need to explicitly register our objects with
// Aurelia - so really, we don't even need this.
hello.html
<template>
<h1>${greeting}</h1>
...my view
</template>
Это означает, что начать работу с Aurelia очень просто: разработчик может освоить меньше кода, специфичного для фреймворка. Соглашения Aurelia «из коробки» поддерживают быстрое развитие и уменьшают кривую обучения. Однако, после более подробного ознакомления с Aurelia, вы можете изменить ее условные обозначения, если хотите, а если нет, то просто не хватает кода, специфичного для фреймворка.
Комплекс (AngularJS) против Simple (Аурелия)
По моему опыту работы с AngularJS, хотя некоторые базовые концепции могут быть довольно простыми, расширенные концепции структурно и семантически сложны. Некоторые вещи (например, написание расширяемых компонентов и модулей) не так уж плохи, в то время как другие вещи (сложные директивы) могут быть почти загадочными. Aurelia стремится упростить выполнение своих передовых концепций, создав более плоскую кривую обучения.
Семантика
AngularJS использует сложную семантику. Разработчик должен знать их, чтобы действительно использовать фреймворк. Например, в AngularJS вы можете объявить service
factory
value
constant
Вы также можете объявить controller
directive
К сожалению, немногие из них используют одни и те же соглашения, особенно директивы AngularJS.
Директивы — это мощная конструкция в AngularJS, позволяющая приложениям расширять HTML с помощью пользовательских элементов, атрибутов и поведения. К сожалению, они также являются продвинутой концепцией, и у них может быть крутая кривая обучения.
Объяснение директив AngularJS выходит за рамки этой статьи, но поверьте мне в этой. Давайте просто посмотрим на образец директивы.
index.html
<body ng-controller="MainCtrl">
<h1>What's your favorite Javascript framework?</h1>
<choose-framework></choose-framework>
</body>
chooseFramework.html
<div>
<input id="framework-input" type="text" ng-model="framework" placeholder="Choose a framework" />
<button data-ng-click="choose()">Choose</button>
<p ng-if="chosen">You prefer {{chosenFramework}}!</p>
</div>
chooseFramework.js
app.directive('chooseFramework', function() {
return {
scope: {
framework: '',
chosen: false,
},
restrict: 'E',
replace: true,
templateUrl: 'chooseFramework.html',
link: function(scope, elem, attrs) {
// Assume we're using jQueryUI autocomplete.
$('#framework-input').autoComplete(['AngularJS', 'Aurelia', 'VanillaJS']);
},
controller: function ($scope) {
$scope.choose = function () {
// Log our preference somewhere.
alert('Your framework choice has been stored for posterity.');
$scope.chosenFramework = $scope.framework;
$scope.chosen = true;
}
}
};
});
Аурелия, напротив, упрощает всю эту семантику и уменьшает кривую обучения. Он полностью избавляется от этапа объявления, позволяя вам внедрить свой код как зависимость гораздо более простым способом. Кроме того, Aurelia использует четко определенные методы жизненного цикла вместо событий, поэтому соглашения о коде распределяются между моделями представления и пользовательскими элементами. Это делает написание и рассуждение о коде простым. Наконец, тайные объявления директив AngularJS заменяются пользовательскими элементами, которые работают так же, как и модели представления Aurelia.
Давайте взглянем:
index.html
<body>
<h1>What's your favorite Javascript framework?</h1>
<choose-framework></choose-framework>
</body>
chooseFramework.html
<div>
<input id="framework-input" type="text" value.bind="framework" placeholder="Choose a framework" />
<button click.delegate="choose()">Choose</button>
<p if.bind="chosen">You prefer ${chosenFramework}!</p>
</div>
chooseFramework.js
@customElement('choose-framework')
export class ChooseFramework {
constructor () {
this.framework = '';
this.chosen = false;
}
attached () {
// Assume we're using jQueryUI autocomplete.
$('#framework-input').autoComplete(['AngularJS', 'Aurelia', 'VanillaJS']);
}
choose () {
// Log our preference somewhere.
alert('Your framework choice has been stored for posterity.');
this.chosenFramework = this.framework;
this.chosen = false;
}
}
Interoperability
Из-за того, как работает обнаружение изменений, AngularJS не может обнаружить изменения объектов или свойств, которые сама инфраструктура не делает. По сути, если изменение происходит вне цикла дайджеста AngularJS, оно должно быть уведомлено, чтобы оно могло его забрать. На практике, хотя AngularJS предоставляет некоторые служебные оболочки для общих функций (таких как тайм-ауты, интервалы и обещания) из коробки, это означает, что любые сторонние библиотеки, которые вносят изменения, должны быть упакованы, чтобы уведомить AngularJS о том, что произошло изменение. Вы заканчиваете тем, что пишете много стандартного кода как это:
$scope.$apply(function () {
// some asynchronous activity that updates scope, such as a
// timeout or an interval
$scope.value = 'updated';
});
(После того, как вы поймете это, у вас все в порядке — но прежде чем вы поймете, что происходит, вы легко можете столкнуться с этой ловушкой, как я это сделал здесь . Однако, поняв, вы в конечном итоге будете много писать этот код.)
Aurelia не требует этих упаковщиков, что означает уменьшение площади и упрощение соглашений. Это также означает, что интеграция сторонних компонентов и библиотек намного проще.
Дорогой (AngularJS) против Эффективного (Аурелия)
Если вы использовали AngularJS каким-либо существенным образом, у вас могут возникнуть проблемы с производительностью, особенно при использовании ng-repeat
Производительность AngularJS сдерживается его методом обнаружения изменений: грязная проверка.
Обнаружение изменений Angular основывалось на «цикле переваривания». По сути, AngularJS будет определять временной интервал, а в конце каждого интервала он «переваривает» все изменения, произошедшие с момента последнего дайджеста. Это происходило несколько раз в секунду. Хотя этот подход работал, у него было три основных недостатка. Во-первых, каждое свойство будет проверяться каждый раз, даже если никаких изменений не произошло; во-вторых, требуется постоянная загрузка процессора; и наконец, основанный на времени цикл дайджеста начнет сбиваться, когда многие свойства нуждаются в обнаружении изменений.
Кроме того, когда AngularJS отвечает на событие изменения, он немедленно обновляет DOM для этого изменения. Множество различных изменений в одном цикле дайджеста вызовут много перерисовок браузера, создадут узкое место и снизят производительность.
Для сравнения, обнаружение изменений Aurelia наблюдает за фактическим изменением, а не сканирует изменения через заданный интервал времени. Выбирая этот современный подход, Аурелия, по сути, обходит три проблемы, описанные выше. Аурелия может использовать грязную проверку, но это будет только как крайний запасной вариант. Во всех других случаях обнаружение изменений Aurelia не вызовет проблем с производительностью, которые преследуют AngularJS.
Наконец, вместо обновления DOM для каждого изменения Aurelia объединяет все обновления DOM с помощью микрозадач, что значительно сокращает количество перерисовок браузера, необходимых для полного обновления представления. Это повышает производительность как в веб-браузерах, так и на мобильных устройствах.
На практике все это делает Aurelia более быстрой и производительной, чем AngularJS. В среде веб-браузера это важно, но это еще более важно на мобильных устройствах, где производительность является первостепенной задачей. Однако это также означает, что как разработчик вы можете делать больше с вашим приложением, не сталкиваясь с блоками производительности.
Фиксированный (AngularJS) против Гибкого (Aurelia)
По моему опыту работы с AngularJS, его фиксированные соглашения работали хорошо, пока вы не столкнулись с условием, которого среда не ожидала. Мы рассмотрим два основных различия между реализацией AngularJS и Aurelia.
Объект window.angular
В AngularJS среда предполагает наличие доступного объекта window
window.angular
Подход Аурелии отбрасывает устаревшее соглашение о глобальных переменных. Вместо этого базовая библиотека инфраструктуры экспортирует объект Aurelia, который можно использовать в любом случае.
Присоединение переменной к window
AngularJS и Aurelia — это веб-фреймворки, так что вы, вероятно, запустите их в веб-браузере, верно?
По моему опыту, это не обязательно так. Модульные тесты и сквозное тестирование в AngularJS требуют инфраструктуры тестирования, такой как Karma, а также специальной библиотеки-макета AngularJS; это может сделать тесты тяжелыми и громоздкими для настройки. ( Я сам столкнулся с этой проблемой. ) Для сравнения, поскольку Aurelia является модульной и не требует наличия window
document
В качестве бонуса, изоморфный JavaScript становится возможным в Aurelia, в то время как реализация AngularJS по умолчанию никогда не допустит этого. Это также означает, что мы можем создавать вложенные приложения Aurelia — что требует творческого программирования в AngularJS.
Конфигурация приложения
При создании веб-приложения в AngularJS инфраструктура и все поставщики должны быть настроены до того, как AngularJS загрузит приложение. Конфигурация после загрузки AngularJS не поддерживается из-за особенностей архитектуры фреймворка. Таким образом, после запуска веб-приложения ваша конфигурация исправлена и не может быть изменена.
Аурелия, для сравнения, позволяет динамическую настройку во время выполнения. У него есть соглашение для настройки приложения при начальной загрузке, но конфигурация не является статической. Это позволяет вашей конфигурации быть гибкой, приспосабливаясь к потребностям вашего приложения.
Одним из практических примеров этого является конфигурация службы $http
Обе платформы позволяют разработчику создавать «перехватчики» — промежуточное программное обеспечение, которое может преобразовывать входящий или исходящий вызов AJAX. Однако AngularJS требует, чтобы эти перехватчики были определены до запуска приложения, то есть они не могут быть удалены во время выполнения. (Это на самом деле сценарий реального мира, с которым столкнулись люди .)
Монолитный (AngularJS) против Модульного (Aurelia)
Вы, как разработчик, когда-либо использовали фреймворк, который работает только с самим собой? По моему опыту с монолитными каркасами, развитие в рамках каркаса было бы быстрым. Но когда вам когда-нибудь понадобится вырваться из формы или отвергнуть ее мнение, вам придется бороться с рамками.
AngularJS изначально был построен как монолитный каркас. Все его компоненты, такие как клиентская маршрутизация, шаблоны и система привязки, были объединены в один большой пакет. Это означало не только то, что всегда требовался весь пакет (даже для простого приложения), но монолитная архитектура AngularJS затрудняла удаление компонентов и их замену при необходимости. (Как пример, это было очевидно с компонентом маршрутизатора Angular.) Хотя в более поздних выпусках AngularJS это несколько смягчалось за счет модульности определенных функций и сервисов, сама базовая структура оставалась тесно связанной единичным пакетом.
Аурелия, в сравнении, использует более современный подход. Несмотря на то, что это полноценный фреймворк, Aurelia состоит из набора библиотек, которые работают вместе с использованием четко определенных интерфейсов, поэтому он полностью модульный. Это означает, что веб-приложение должно включать только необходимые ему зависимости. Кроме того, это означает, что, пока реализации придерживаются определенного интерфейса, отдельные компоненты могут быть изменены или заменены с минимальными усилиями.
В качестве примера, давайте возьмем встроенную зависимость от AngularJS. В моем проекте у меня есть несколько модулей AngularJS, которые экспортируют сервисы с одинаковыми именами, но я обнаружил, что встроенный инжектор использует единое пространство имен для всех модулей, что означает, что регистрация сервисов с одинаковыми именами приводит к конфликту с неожиданным поведением . Мне бы хотелось, чтобы модули AngularJS работали как отдельные DI-контейнеры, чтобы избежать любых коллизий инжектора, поэтому я пишу компонент внедрения зависимостей, который решает проблему. К сожалению, поскольку сервисный уровень AngularJS является основным компонентом AngularJS, я не могу избавиться от него или изменить его без изменения ядра AngularJS. Пока я не перестрою фреймворк или не изменим код приложения, я застрял.
В Aurelia, хотя внедрение зависимостей является ключевым компонентом, используемым и в рамках фреймворка, потому что это модульный компонент, я могу заменить его своей собственной реализацией — до тех пор, пока я придерживаюсь интерфейса внедрения зависимостей Aurelia. Если я обнаружу проблему с собственным инжектором, я могу поменять собственную реализацию внедрения зависимостей без необходимости перестраивать каркас, касаться любого кода приложения или беспокоиться о зависимых компонентах. По опыту, возможность менять компоненты фреймворка — это действительно хорошая возможность.
Вердикт
Пришло время сделать шаг назад и подвести итог. Мы рассмотрели AngularJS против Aurelia в следующих областях:
AngularJS | Aurelia |
---|---|
патентованный | Стандарты совместимый |
конфигурация | условность |
Сложный | просто |
Дорогие | эффективное |
Исправлена | гибкий |
монолитный | модульная |
… и на основании этих сравнений я могу прийти только к одному логическому выводу:
AngularJS | Aurelia |
---|---|
Старый и Разоренный | Новая Жара |
В этом сравнении может показаться, что я использую AngularJS. И если честно, я вроде как. Но это не значит, что AngularJS — плохая структура. Мне было очень весело изучать и использовать его, и я смог создать из него несколько замечательных вещей. (На самом деле, я бы ни за что не смог рассказать о AngularJS в таких деталях, не использовав его так много.) Однако у AngularJS есть некоторые проблемы, которые просто не стареют в течение шести лет. Суть заключается в следующем: если взять AngularJS и Aurelia в сравнении яблок с яблоками в 2016 году, Aurelia просто свежее и сочнее, чем AngularJS.
Дело в том, что если вы думаете о выборе AngularJS в качестве более современного фреймворка, такого как Aurelia, может быть целесообразно сделать шаг назад и переоценить. Aurelia не сложна в освоении, имеет активное сообщество и должна быть знакома разработчикам AngularJS. Но поистине замечательной особенностью Aurelia является то, что, хотя она и обеспечивает разумные значения по умолчанию, она не будет навязывать свое мнение в горло — и, по моему опыту, это означает, что вы можете зависеть от Aurelia, вместо того, чтобы зависеть от вас. Преимущества использования современного фреймворка с подходом, ориентированным на разработчика, безусловно, окупаются.
Если вы заинтересованы в том, чтобы лучше узнать Аурелию, ознакомьтесь с некоторыми из следующих ресурсов Аурелии.