Octane is here


Ember 3.15 is Octane! Curious about what Octane means for web development? This blog post will help you find your way.

For a record of technical details (upgrade strategy, deprecation, new Ember Data features), please refer to Ember 3.15 release blog post.

What is Ember octane?

Ember Octane is the best way for teams to build ambitious web applications.

Ember has always focused on building the best framework that people of different skill levels can use together to build web applications. Octane updated Ember’s components and reaction system to make it more modern, easier to use, and more interesting.

Ember project recommended Octane

Starting from Ember 3.15, the Ember project recommends Octane for new applications and plugins.If you create a new application using ember new With version 3.15 or higher, you will get a new Octane app.

Octane is more interesting

The first task of the Ember Octane version is to make it simpler and more pleasure Build the Ember application.

At the core of Octane’s ergonomic improvements are two major changes to the core of Ember: a new component model and a new reaction system.

For existing Ember users, the new component model and the new reaction system are completely optional and can be fully interoperable with existing code. As the version number implies, upgrading Ember 3.14 applications to Ember 3.15 is a compatible change.

Low light component

The first major improvement of Ember Octane is Glimmer Components. Ember has had a single component system based on the JavaScript syntax available at the time since Ember 1.0.

Before: classic components

When you look at classic components, the first thing you think of is to configure the “root element” using JavaScript microgrammar.

import Component from '@ember/component';

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

After: low light component

In contrast, the Glimmer component allows you to treat the root element like any other element. This greatly simplifies the component model and eliminates the special situation that arises from using the second API only to process the root element of the component.

<p class="tooltip {{if @isEnabled 'enabled'}} {{if @isActive 'active'}}">
  {{yield}}
</p>

This also means that you can create a component with no root element at all, and that kind of thing is fine.

<p>{{yield}}</p>
<hr>

Reusable DOM behavior with modifiers

The second major improvement of the Ember component model is element modifiers, which allow you to build reusable DOM behaviors that are not connected to any specific components.

Before: mixed

In Classic Ember, if you want to define a DOM behavior that can be reused throughout the application, you will define a component mixin that implements appropriate lifecycle hooks.

For example, suppose we have a public third-party library activateTabs with deactivateTabs Function, both take one element. In Classic Ember, you can write a mixin like this:

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

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

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

Then you would use it in a component like this:

import Component from '@ember/component';

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

A good description of the disadvantages of using mixin for UI composition Pass through This JavaScript ecosystemThe most obvious problem is naming conflicts. Any method on a mixin may conflict with any other method on a mixin, and there is no good way to resolve the conflict.

In the context of Ember, there is another problem with mixing Ember components for reusable DOM behavior.If you want to use Tabs The mixin is on an element, and you need to turn this element into a component with a JavaScript class, which is awkward.

Although we recommend that you avoid using mixins, you can still use them in Ember 3.15. The plug-in may still provide a mixin for you to use.

After: element modifier

Ember Octane provides a new way to reuse DOM behavior: element modifiers. The easiest way to write element modifiers is to write a function that accepts the element and processes it. This function can optionally return a destructor, which should be run when Ember tears down the element.

This is ours Tabs When reimplemented as a modifier, the mixin looks like.

import { modifier } from 'ember-modifier';

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

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

It’s really straightforward!

You can use modifiers on any element using element modifier syntax.

<div {{tabs}}></div>

Element modifiers apply to any element, which means you don’t need to create an entire component to create reusable DOM behaviors.

This way of writing modifiers assumes that when the parameters of the modifier change, you can run the destructor and run the modifier from the beginning. If you need finer control, ember-modifier The package also provides a more advanced API.

Low light response

The hallmark of a modern front-end framework is its “reactive model.” The reactive model tells you how to define and manipulate the data in the program so that the output DOM will be updated correctly when you make changes.

Ember Octane published a very simple reaction model called “tracking attributes”.

The tracking attribute reaction model is compatible and interoperable with the classic reaction model.This is because these two APIs are implemented according to Ember’s internal reaction model, based on reference with Validator.

Before: Calculating properties and limitations

In Classic Ember, you can change the reactive properties by using set, And any calculation must be described as a calculated attribute. The calculated attribute must fully enumerate all dependencies.

This is an example of a calculated attribute in the Ember 3.14 guide:

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', 'Christopher');
captainAmerica.description; // "Christopher Rogers; Age: 80; Country: USA"

This design makes it more difficult to decompose a calculated attribute into smaller functions, because a calculated attribute still needs to enumerate all the attributes it uses, no matter where they are used. In practice, this means that in Classic Ember, you decompose calculated attributes into more calculated attributes, which is effective but somewhat limited.

After: tracked attributes

Octane’s reactive model, tracking properties, has a lighter footprint.

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 = "Christopher";
captainAmerica.description; // "Christopher Rogers; Age: 80; Country: USA"

You start with a normal JavaScript class and use the following command to annotate any fields that may affect the DOM @tracked. You do not need to annotate getters or functions, so you can break down the code as needed.

One neat thing about the tracking attribute reactivity model is that if you delete @tracked Note, the code works exactly the same.If you add, the only thing that will change @tracked Yes, if you change the property, any part of the DOM that uses the property as part of its calculation will be updated correctly.

Focus on documentation

Octane is more than just a new feature. It also focuses on refreshing documents to show users how to build applications in Octane.

Fully updated tutorial and component guide

This tutorial is the first way people learn how to build Ember applications. Ember 3.15 is fully refreshed Super Lease Tutorial So it is written in Octane style.

The structure of the tutorial has also been clarified and updated.

before


Rear

Tutorial after Octane

The guide has also undergone major updates, improving components and eliminating messy organization (such as the separation between templates and components). The new guide no longer emphasizes the less important controllers in Octane. The classic object model part is now included in the part about migrating to Octane, rather than as a first-class part.

before

Octane's previous guide

Rear

Guide after octane

The Ember checker is a very important part of the way Ember developers build Ember applications.

We have maintained a reliable five-star rating in the Chrome Web Store for many years, and we are very proud of that.

Embers inspector

For Octane, the Ember checker has been updated to support Octane features in a first-class way, including tracking properties and Glimmer components.

The updated checker eliminates duplicate concepts and outdated language (such as “view tree”). It also has many visual improvements, including new component tooltips that better reflect Octane idioms. It also updated component tooltips and fixed long-term issues with physical widgets.

Ember Inspector view tree

getting Started

Whether you are a new Ember developer returning to Ember years later, or an existing Ember developer, the fastest and easiest way to learn how to build an application the Octane way is to run Updated tutorial.

After completing this tutorial, you can build something really interesting. The Ember plugin ecosystem is an important part of Ember, so you need to use plugins to speed up the process of building projects.

Ember watcher Is the directory of the Ember plugin ecosystem. Each plug-in will receive a quality score based on a manual review of formal standards, such as whether there is a meaningful readme file, whether the plug-in has an automatic build, and whether the plug-in is maintained by multiple people. This week, it will also indicate whether the plug-in is Octane Ready.

Due to the details of the Octane compatibility story, most plugins should be Octane Ready without any changes. Ember Observer will help the community proactively identify and fix Octane issues in the maintenance package.

In-depth understanding of seamless interoperability

In addition to eliminating computational properties, Glimmer’s reactive model does not include special Ember agents or observers. The Octane reactive model is more powerful than the classic model, but easier to use.

If it is difficult to use objects implemented using the classic reaction model from objects implemented using the Octane model, then the Octane reaction model will not be very useful for existing Ember users. For this reason, we strive to ensure that existing Ember applications can freely use classic objects in classes built with tracking attributes.

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', 'Christopher');
contact.description; // "Christopher Rogers; Age: 80; Country: USA"

Since the two systems are interoperable, the library can adopt the Octane reactive system without major changes to its API.

This work also allows the existing Ember code base to adopt the Octane pattern on a module-by-module basis.

Thank you for viewing Octane!

Octane is a project that the Ember community is happy to share with new and old developers. Octane is a modern and efficient way to build web applications, making our work interesting and stable.

Without the efforts of the community and every member, it is impossible to achieve a complete and comprehensive update of Ember’s API and help content. Ember core teamThank you for being a member of our community, contributing to this project, and continuing to help Ember become a great choice for building on the web.

Leave a Reply

Your email address will not be published. Required fields are marked *