Ember Octane — это новая редакция фреймворка Ember.js, а также лучший способ для команд создавать амбициозные веб-приложения.


20 декабря вышла новая версия Ember 3.15. И это Octane! Любопытно, что это значит для веб-разработки? Этот пост поможет вам сориентироваться.


Мы с гуглотранслейтом усердно старались над переводом (особенно гуглотранслейт). Добро пожаловать под кат!


Описание технических деталей (стратегии обновления, устаревшие функции, новые функции Ember Data) см. в блоге Ember 3.15 Release (англ.).


Что такое Ember Octane?


Ember всегда фокусировался на создании лучшей среды, которую люди с разными уровнями квалификации могут использовать вместе для создания веб-приложений. Octane обновляет компоненты и систему реактивности Ember, чтобы сделать их более современными и простыми в использовании. Теперь использовать Ember станет намного веселее!


Начиная с версии 3.15, разработчики Ember рекомендуют Octane для новых приложений и дополнений. Если вы создадите новое приложение, используя ember new с версией 3.15 или более поздней, вы получите новое приложение Octane.


Octane это fun


Центральным элементом улучшений Octane являются два больших изменения в ядре Ember: новая модель компонентов и новая система реактивности.


Для существующих приложений на Ember оба изменения полностью совместимы с существующим кодом. Обновление приложения Ember 3.14 до Ember 3.15 является совместимым изменением, как и предполагает номер версии.

Glimmer компоненты


Первое большое улучшение в Ember Octane — это компоненты Glimmer. Начиная с Ember 1.0 в Ember была однокомпонентная система, основанная на синтаксисе JavaScript, который был доступен в то время.


До: классические Ember компоненты


Когда вы смотрите на классические компоненты, первое, что бросается в глаза это то, что вы конфигурируете «root-элемент», используя синтаксис JavaScript.


import Component from '@ember/component';

export default Component.extend({
  tagName: 'p',
  classNames: ["tooltip"],
  classNameBindings: ["isEnabled:enabled", "isActive:active"],
})

После: компоненты Glimmer


Компоненты Glimmer, с другой стороны, позволяют обрабатывать корневой элемент как любой другой элемент. Это существенно упрощает модель компонентов, исключая особые случаи, связанные с наличием второго API только для работы с корневым элементом компонента.


код с hbs шаблоном компонента
Это также означает, что вы можете создать компонент без корневого элемента, и это будет работать.


код с hbs шаблоном компонента без корневого элемента


Использование модификаторов(modifiers) для повторного использования поведения DOM


Второе значительное улучшение в модели компонентов Ember — это модификаторы элементов — функция, которая позволяет создавать поведение DOM многократного использования, которое не связано с каким-либо конкретным компонентом.


До: Mixins


В классическом Ember, если вы хотите определить часть поведения DOM, которую вы можете повторно использовать в своем приложении, вы должны определить компонентный миксин, в котором реализованы соответствующие хуки жизненного цикла.


Например, у нас есть сторонняя библиотека, которая предоставляет функции activateTabs и deactivateTabs, каждая из которых принимает элемент. В классическом Ember вы можете написать миксин так:


import Mixin from '@ember/object/mixin';

export default Mixin.create({
  didInsertElement() {
    this._super();
    activateTabs(this.element);
  }

  willDestroyElement() {
    this._super();
    deactivateTabs(this.element);
  }
})

И тогда вы будете использовать его в таком компоненте:


import Component from '@ember/component';

export default Component.extend(Tabs, {
  // ...
});

Недостатки использования миксины для композиции пользовательского интерфейса хорошо описаны во всей экосистеме JavaScript (Mixins Considered Harmful, Hooks are coming to Vue.js version 3.0, Declined mixin proposal for svelte, Ember RFC: Deprecate Mixins). Самая большая проблема — конфликты имен. Любой метод в миксине может конфликтовать с методом в любом другом миксине, без хорошего способа разрешения конфликтов.


В контексте Ember есть еще одна проблема с использованием миксинов компонентов Ember для многократного использования поведения DOM. Если вы хотите использовать миксин Tabs для элемента, вам нужно превратить этот элемент в компонент с классом JavaScript, что довольно неудобно.


Хотя мы рекомендуем избегать миксинов, вы можете использовать их в Ember 3.15. Аддоны также могут по-прежнему предоставлять вам миксины.

После: Модификаторы элемента


Ember Octane предоставляет новый способ повторного использования поведения DOM: модификаторы элементов. Самый простой способ написать модификатор элемента — написать функцию, которая берет элемент и что-то с ним делает. Функция может дополнительно возвращать функцию-деструктор, которая должна запускаться, когда Ember разрушает элемент.


Вот как выглядит наш миксин Tabs когда переопределяется как модификатор.


import { modifier } from 'ember-modifier';

export default modifier(element => {
  activateTabs(element);

  return () => deactivateTabs(element);
});

Согласитесь, просто!


Вы можете использовать модификатор для любого элемента, используя синтаксис модификатора элемента.


DOM элемент с модификатором tabs


Модификаторы элементов работают с любым элементом, что означает, что вам не нужно создавать целый компонент просто для создания многократно используемого поведения DOM.


Этот способ написания модификаторов предполагает, что когда изменяются аргументы модификатора, можно запустить деструктор и запустить модификатор с нуля. Если вам нужно более детальное управление, пакет ember-modifier также предоставляет более продвинутый API.


Реактивность заимствованная из Glimmer


Отличительной чертой современного внешнего интерфейса является его «модель реактивности». Модель реактивности говорит вам, как определять и манипулировать данными в вашей программе, чтобы выходной DOM корректно обновлялся при внесении изменений.


Ember Octane раскрывает значительно более простую модель реактивности, называемую «отслеживаемыми (tracked) свойства».


Модель реактивности с отслеживаемыми свойствами совместима с классической моделью реактивности. Это связано с тем, что оба API реализованы в рамках модели внутренней реактивности Ember, основанной на Ссылках и Валидаторах .

До: вычисляемые свойства (computed properties) и их ограничения


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


Вот пример вычисляемых полей из руководств Ember 3.14:


import EmberObject, { computed } from '@ember/object';

const Person = EmberObject.extend({
  firstName: null,
  lastName: null,
  age: null,
  country: null,

  fullName: computed('firstName', 'lastName', function() {
    return `${this.firstName} ${this.lastName}`;
  }),

  description: computed('fullName', 'age', 'country', function() {
    return `${this.fullName}; Age: ${this.age}; Country: ${this.country}`;
  })
});

let captainAmerica = Person.create({
  firstName: 'Steve',
  lastName: 'Rogers',
  age: 80,
  country: 'USA'
});

captainAmerica.description; // "Steve Rogers; Age: 80; Country: USA"
captainAmerica.set('firstName', 'Steven');
captainAmerica.description; // "Steven Rogers; Age: 80; Country: USA"

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


После: Отслеживаемые свойство (tracked properties)


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


class Person {
  @tracked firstName;
  @tracked lastName;
  @tracked age;
  @tracked country;

  constructor({ firstName, lastName, age, country }) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.country = country;
  }

  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }),

  get description() {
    return `${this.fullName}; Age: ${this.age}; Country: ${this.country}`;
  })
}

let captainAmerica = new Person({
  firstName: 'Steve',
  lastName: 'Rogers',
  age: 80,
  country: 'USA'
});

captainAmerica.description; // "Steve Rogers; Age: 80; Country: USA"
captainAmerica.firstName = "Steven";
captainAmerica.description; // "Steven Rogers; Age: 80; Country: USA"

Вы начинаете с обычного класса JavaScript и аннотируете любые поля, которые могут повлиять на DOM, с помощью @tracked. Вам не нужно аннотировать геттеры или функции, так что вы можете разбить ваш код так, как хотите.


Особенность модели реактивности отслеживаемых свойств заключается в том, что если вы удалите аннотацию @tracked, код будет работать точно так же. Единственное, что изменяется, когда вы добавляете @tracked это то, что если свойство изменяется, любая часть DOM, которая использовала это свойство как часть своих вычислений, будет корректно обновляться.

Внимание к документации


Octane — это больше, чем просто новые функции. Кроме того, мы уделили много внимания обновлению документации, чтобы показать пользователям, как создавать приложения в стиле Octane.


Туториал — это первый способ, которым люди учатся создавать приложения Ember. Ember 3.15 полностью обновил туториал по Super Rentals, переписав его в стиле Octane. Структура уроков также уточнена и обновлена.


Руководство (guides) также подверглось значительному обновлению. Теперь мы вначале рассказываем о компонентах, устранив сбивающую с толку организацию (например, разделение между шаблонами и компонентами). Новое руководство снимает акцент с контроллеров, которые менее важны в Octane. Классическая объектная модель теперь включена в раздел о миграции на Octane.


Ember Inspector стал еще лучше


Инспектор Ember — очень важная часть того, как разработчики Ember создают приложения Ember.


Мы очень гордимся тем, что на протяжении многих лет мы поддерживаем пятизвездочный рейтинг в Интернет-магазине Chrome.


image


Для Octane инспектор Ember обновлен для поддержки первоклассных функций Octane, включая отслеживаемые свойства и компоненты Glimmer.


Обновленный инспектор устраняет дублирующиеся понятия и устаревший язык (например, «Дерево просмотра»). Он также имеет множество визуальных улучшений, включая новую всплывающую подсказку о компонентах, которая лучше отражает идиомы Octane. Также обновляется всплывающая подсказка для компонента, которая устраняет давнюю проблему небольшими компонентами.


image


Начиная работу


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


Экосистема аддонов Ember — это отличная часть Ember, поэтому вы захотите использовать аддоны, чтобы ускорить процесс создания вашего проекта.


Ember Observer — это каталог для экосистемы аддонов Ember. Каждый аддон получает оценку качества на основе анализа формальных критериев, таких как наличие значимого README, имеет ли аддон автоматическую сборку, и поддерживается ли аддон более чем одним человеком. Начиная с этой недели также будет указано, является ли аддон Octane Ready.


Большинство дополнений должны быть Octane Ready без каких-либо изменений. Ember Observer поможет сообществу заблаговременно выявлять и устранять проблемы Octane в поддерживаемых пакетах.

Немного подробнее о бесшовном взаимодействии (seamless interop)


В дополнение к исключению вычисленных свойств, модель реактивности Glimmer также не включает Ember Proxies или Observers. Модель реактивности Octane более мощная, чем классическая, но ее гораздо проще использовать.


Модель реактивности Octane не была бы полезна для существующих пользователей Ember, если бы было трудно использовать объекты, реализованные с использованием классической модели реактивности, из объектов, реализованных с использованием модели Octane. Поэтому мы усердно работали над тем, чтобы существующие приложения Ember могли свободно использовать классические объекты в классах, созданных с использованием отслеживаемых свойств.


class Contact {
  @tracked person;

  constructor(person) {
    this.person = person;
  }

  get description() {
    return this.person.description;
  }
}

import EmberObject, { computed } from '@ember/object';

const Person = EmberObject.extend({
  firstName: null,
  lastName: null,
  age: null,
  country: null,

  fullName: computed('firstName', 'lastName', function() {
    return `${this.firstName} ${this.lastName}`;
  }),

  description: computed('fullName', 'age', 'country', function() {
    return `${this.fullName}; Age: ${this.age}; Country: ${this.country}`;
  })
});

let captainAmerica = new Person({
  firstName: 'Steve',
  lastName: 'Rogers',
  age: 80,
  country: 'USA'
});

let contact = new Contact(captainAmerica);
contact.description; // "Steve Rogers; Age: 80; Country: USA"
captainAmerica.set('firstName', 'Steven');
contact.description; // "Steven Rogers; Age: 80; Country: USA"

Поскольку эти две системы совместимы, библиотеки могут использовать систему реактивности Octane без существенных изменений в API.


Это позволяет вам переписывать существующие приложения Ember с использованием Octane модуль за модулем.


Спасибо за ваш интерес к Ember Octane


Octane — проект, которым сообщество Ember рада поделиться с разработчиками, как новыми, так и опытными. Octane — это современный продуктивный способ создания веб-приложений, позволяющий получать удовольствие и стабильность в нашей работе.


Полное обновление API-интерфейсов Ember и документации не могло бы быть достигнуто без усилий сообщества и каждого члена core-команд Ember. Благодарим вас за то, что вы являетесь его частью, вносите свой вклад в этот проект и продолжаете помогать Ember быть отличным выбором для веб-разработки.


от переводчика:
На русском про Ember можно спрашивать в телеграмм канале ember_js

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


  1. Kaer_Morchen
    27.12.2019 15:55

    Спасибо за перевод.