Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Road to Ember 2.0 RFC #15

Merged
merged 2 commits into from
Jun 7, 2015
Merged

The Road to Ember 2.0 RFC #15

merged 2 commits into from
Jun 7, 2015

Conversation

tomdale
Copy link
Member

@tomdale tomdale commented Nov 3, 2014

  • Start Date: 2014-12-03
  • RFC PR: (leave this empty)
  • Ember Issue: (leave this empty)

The Road to Ember 2.0

Intro

Today, we're announcing our plan for Ember 2.0. While the major version bump gives us the opportunity to simplify the framework in ways that require breaking changes, we are designing Ember 2.0 with migration in mind.

This is not a big-bang rewrite; we will continue development on the master branch, and roll out changes incrementally on the 1.x release train. The 2.0.0 release will simply remove features that have been deprecated between now and then. Our goal is that you can move your Ember app to 2.0 incrementally, one sprint at a time.

This RFC captures the results of the last two core team face-to-face meetings, where we discussed community feedback about the future of the project. While it explains the high-level goals and tries to paint a picture of how all the pieces fit together, this document will be updated over time with links to individual RFCs that contain additional implementation detail.

We plan to flesh out these more-detailed RFCs in the next few weeks, as the discussion here progresses, before finalizing this plan.

We are announcing Ember 2.0 through our community RFC process in advance of a release, both so our proposals can be vetted by the community and so the community can understand the goals and contribute their own ideas back.

Motivation

Stability without Stagnation

Ember is all about identifying common patterns that emerge from the web development community and rolling them into a complete front-end stack. This makes it easy to get started on new projects and jump into existing ones, knowing that you will get a best-of-breed set of tools that the community will continue to support and improve for years to come.

In the greater JavaScript community, getting the latest and greatest often means rewriting parts of your apps once a year, as the community abandons existing solutions in search of improvements. Progress is important, but so is ending the constant cycle of writing and rewriting that plagues so many applications.

The Ember community works hard to introduce new ideas with an eye towards migration. We call this "stability without stagnation", and it's one of the cornerstones of the Ember philosophy.

Below, we introduce some of the major new features coming in Ember 2.0. Each section includes a transition plan, with details on how we expect existing apps to migrate to the new API.

When breaking changes are absolutely necessary, we try to make those changes ones you can apply without too much thought. We call these "mechanical" refactors. Typically, they'll involve a change to syntax without changing semantics. These are significantly easier to adopt than those that require fundamental changes to your application architecture.

To further aid in these transitions, we are planning to add a new tab to the Ember Inspector that will list all deprecations in your application, as well as a list of the locations in the source code where the deprecated code was triggered. This should serve as a convenient "punch list" for your transitional work.

Every member of the core team works on up-to-date Ember applications, and we feel the tension between stability and progress acutely. We want to deliver cutting-edge products, but need to keep shipping, and many companies that have adopted Ember for their products tell us the same thing.

Big Bets

In 2014, we made big bets in two areas, and they've paid off.

The first bet was on open standards: JavaScript modules, promises and Web Components. We started the year off with globals-based apps, callbacks and "views", and incrementally (and compatibly) built towards standards-based solutions as those standards solidified.

The second bet was that the community was as tired as we were of hand-rolling their own build scripts for each project. We've invested heavily in Ember CLI, giving us a single tool that unifies the community and provides a venue for disseminating great ideas.

In Ember 2.0, Ember CLI and ES6 modules will become first-class parts of the Ember experience. We will update the website, guides, documentation, etc. to teach new users how to build Ember apps with the CLI tools and using JavaScript's new module syntax.

While globals-based apps will continue to work in 2.0, we may introduce new features that rely on either Ember CLI or ES6 modules. You should begin moving your app to Ember CLI as soon as possible.

All of the apps maintained by the Ember core team have been migrated to Ember CLI, and we believe that most teams should be able to make the transition incrementally.

Learning from the Community

We're well aware that we don't have a monopoly on good ideas, and we're always analyzing competing frameworks and libraries to discover great ideas that we can incorporate.

For example, AngularJS taught us the importance of making early on-ramp easy, how cool directives/components could be, and how dependency injection improves testing.

We've been analyzing and discussing React's approach to data flow and rendering for some time now, and in particular how they make use of a "virtual DOM" to improve performance.

Ember's view layer is one of the oldest parts of Ember, and was designed for a world where IE7 and IE8 were dominant. We've spent the better part of 2014 rethinking the view layer to be more DOM-aware, and the new codebase (codenamed "HTMLBars") borrows what we think are the best ideas from React. We cover the specifics below.

React's "virtual DOM" abstraction also allowed them to simplify the programming model of component-based applications. We really like these ideas, and the new HTMLBars engine, landing in the next Ember release, lays the groundwork for adopting the simplified data-flow model.

In Ember 2.0, we will be adopting a "virtual DOM" and data flow model that embraces the best ideas from React and simplifies communication between components.

Interestingly, we found that well-written Ember applications are already written with this clear and direct data flow. This change will mostly make the best patterns more explicit and easier for developers to find when starting out.

A Steady Flow of Improvement

Ember 1.0 shipped over a year ago and we have continued to improve the framework while maintaining backwards-compatibility. We are proud of the fact that Ember apps tend to track released versions.

You might expect us to do Ember 2.0 work on a separate "2.0" branch, accumulating features until we ship. We aren't going to do that.

Instead, we plan to do the vast majority of new work on master (behind feature flags), and land new features in 1.x as they become stable.

The 2.0.0 release will simply remove the cruft that naturally builds up when maintaining compatibility with old releases.

If we add features that change Ember idioms, we will add clear deprecation warnings with steps to refactor to new patterns.

Our goal is that, as much as possible, people will be able to boot up their app on the last 1.x version, update to the latest set of idioms by following the deprecation prompts, and have things working on 2.0.

Because going from the last version of Ember 1.x to Ember 2.0 will be just another six-week release, there simply won't be much time for us to make it an incredibly painful upgrade. ;)

Simplifying Ember Concepts

Ember evolved organically from a view-layer-only framework in 2011 into the route-driven, complete front-end stack it is today. Along the way, we've accumulated several concepts that are no longer widely used in idiomatic Ember apps.

These vestigial concepts make file sizes larger, code more complex, and make Ember harder to learn.

Ember 2.0 is about simplification. This lets us reduce file sizes, reduce code complexity, and generally make Ember apps easier to pick up and maintain.

The high-level set of improvements that we have planned are:

  • More intuitive attribute bindings
  • New HTML syntax for components
  • Block parameters for components
  • More consistent template scope
  • One-way data binding by default, with opt-in to mutable, two-way bindings
  • More explicit communication between components, which means less implicit communication via two-way bindings
  • Routes drive components, instead of controller + template
  • Improved actions that are invoked inside components as simple callbacks

In some sections, we provide estimates for when a feature will land. These are our best-guesses, but because of the rapid-release train model of Ember, we may be off by a version or two.

However, all features that are slated for "before 2.0" will land before we cut over to a major new version.

More Intuitive Attribute Bindings

Today's templating engine is the oldest part of Ember.js. Under the hood, it generates a string of HTML and then inserts it into the page.

One unfortunate consequence of this architecture is that it is not possible to intuitively bind values to HTML attributes.

You would expect to be able type something like:

<a href="{{url}}">Click here</a>

But instead, in today's Ember, you have to learn about and use the bind-attr helper:

<a {{bind-attr href=url}}>Click here</a>

The new HTMLBars template engine makes bind-attr a thing of the past, allowing you to type what you mean. It also makes it possible to express many attribute-related concepts simply:

<a class="{{active}} app-link" href="{{url}}.html">Click here</a>

Transition Plan

The HTMLBars templating engine is being developed on master, and parts of it have already landed in Ember 1.8. Doing the work this way means that the new engine continues to support the old syntax: your existing templates will continue to work.

The improved attribute syntax has not yet landed, but we expect it to land before Ember 1.10.

We do not plan to remove support for existing templating syntax (or no-longer-necessary helpers like bind-attr) in Ember 2.0.

More Intuitive Components

In today's Ember, components are represented in your templates as Handlebars "block helpers".

The most important problem with this approach is that Handlebars-style components do not work well with attribute bindings or the action helper. In short, a helper that is meant to be used inside an HTML tag cannot be used inside a call to a component.

Beginning in Ember 1.11, we will support an HTML-based syntax for components. The new syntax can be used to invoke existing components, and new components can be called using the old syntax.

<my-video src={{movie.url}}></my-video>

<!-- equivalent to -->

{{my-video src=movie.url}}

Transition Plan

The improved component syntax will (we hope) land in Ember 1.11. You can transition existing uses of {{component-name}} to the new syntax at that time. You will likely benefit by eliminating uses of computed properties that can now be more tersely expressed using the interpolation syntax.

We have no plans to remove support for the old component syntax in Ember 2.0.

Block Parameters

In today's templates, there are two special forms of built-in Handlebars helpers: #each post in posts and #with post as p. These allow the template inside the helper to retain the parent context, but get a piece of helper-provided information as a named value (such as post in the previous examples).

{{#with contact.person as p}}
  {{!-- this block of code is still in the parent's scope, but
        the #with helper provided a `p` name with a
        helper-provided value --}}
  <p>{{p.firstName}} {{p.lastName}}</p>

  {{!-- `title` here refers to the outer scope's title --}}
  <p>{{title}}</p>
{{/with}}

Today, this capability is hardcoded into the two special forms, but it can be useful for other kinds of components. For example, you may have a calendar component (ui-calendar) that displays a specified month.

The ui-calendar component may want to allow users to supply a custom template for each day in the month, but each repetition of the template will need information about the day it represents (its day of the week, date number, etc.) in order to render it.

With the new "block parameters" feature, any component will have access to the same capability as #each or #with:

<ui-calendar month={{currentMonth}} as |day|>
  <p class="title">{{day.title}}</p>
  <p class="date">{{day.date}}</p>
</ui-calendar>

In this case, the ui-calendar component iterates over all of days in currentMonth, rendering each instance of the template with information about which date it should represent.

We also think that this feature will be useful to allow container components (like tabs or forms) to supply special-case component definitions as block params. We are still working on the details, but believe that an approach along these lines could make these kinds of components simpler and more flexible.

Transition Plan

Block parameters will hopefully land in 1.12, and at that point the two special forms for {{each}} and {{with}} will be deprecated. You should refactor your templates to use the new block parameters syntax once it lands, as it is a purely mechanical refactor.

We have no plans to remove support for the {{each}} and {{with}} special forms in Ember 2.0.

More Consistent Handlebars Scope

In today's Ember, the each and with helpers come in two flavors: a "context-switching" flavor and a "named-parameter" flavor.

{{#each post in posts}}
  {{!-- the context in here is the same as the outside context,
        and `post` references the current iteration --}}
{{/each}}

{{#each posts}}
  {{!-- the context in here has shifted to the individual post.
        the outer context is no longer accessible --}}
{{/each}}

This has proven to be one of the more confusing parts of the Ember templating system. It is also not clear to beginners which to use, and when they choose the context-shifting form, they lose access to values in the outer context that may be important.

Because the helper itself offers no clue about the context-shifting behavior, it is easy (even for more experienced Ember developers) to get confused when skimming a template about which object a value refers to.

In Ember 1.10, we will deprecate the context-shifting forms of #each and #with in favor of the named-parameter forms.

Transition Plan

To transition your code to the new syntax, you can change templates that look like this:

{{#each people}}
  <p>{{firstName}} {{lastName}}</p>
  <p>{{address}}</p>
{{/each}}

with:

{{#each people as |person|}}
  <p>{{person.firstName}} {{person.lastName}}</p>
  <p>{{person.address}}</p>
{{/each}}

We plan to deprecate support for the context-shifting helpers in Ember 1.10 and remove support in Ember 2.0. This change should be entirely
mechanical.

One-Way Bindings by Default

After a few years of having written Ember applications, we have observed that most of the data bindings in the templating engine do not actually require two-way bindings.

When we designed the original templating layer, we figured that making all data bindings two-way wasn't very harmful: if you don't set a two-way binding, it's a de facto one-way binding!

We have since realized (with some help from our friends at React), that components want to be able to hand out data to their children without having to be on guard for wayward mutations.

Additionally, communication between components is often most naturally expressed as events or callbacks. This is possible in Ember, but the dominance of two-way data bindings often leads people down a path of using two-way bindings as a communication channel. Experienced Ember developers don't (usually) make this mistake, but it's an easy one to make.

When you use the new component syntax, the {{}} interpolation syntax defaults to creating one-way bindings in the components.

<my-video src={{url}}></my-video>

In this example, the component's src property will be updated whenever url changes, but it will not be allowed to mutate it.

If a template wishes to allow the component to mutate a property, it can explicitly create a two-way binding using the mut helper:

<my-video paused={{mut isPaused}}></my-video>

This can help ease the transition to a more event-based style of programming.

It also eliminates the boilerplate associated with an event-based style when working with form controls. Instead of copying state out of a model, listening for callbacks, and updating the model, the input helper can be given an explicit mutable binding.

<input value={{mut firstName}}>
<input value={{mut lastName}}>

This is similar to the approach taken by React.Link, but we think that the use-case of form helpers is sufficiently common to make it ergonomic.

Transition Plan

The new one-way default is triggered by the use of new component syntax. This means that component invocations in existing templates will continue to work without changes.

When transitioning to the new HTML-based syntax, you will likely want to evaluate whether bindings are actually being mutated, and avoid using mut for values that the component never changes. This will make it easier for future readers of your template to get an understanding of what properties might be changed downstream.

To preserve the same semantics during a refactor to the new HTML-based syntax, you can simply mark all bindings as mut.

{{!-- these are semantically equivalent --}}

{{my-video src=movie.url paused=controller.isPaused}}

<my-video src={{mut movie.url}} paused={{mut controller.isPaused}}>
</my-video>

While the above example preserves the same mutability semantics, it should be clear that the video player component should never change the url of the movie model.

To make sure you get an exception should this ever happen, simply remove the mut:

<my-video src={{movie.url}} paused={{mut controller.isPaused}}>
</my-video>

We have no plans to remove the old-style component syntax in Ember 2.0, so the semantics of existing component invocations will not change.

Separated Component Parameters

In today's Ember, parameters passed to components as attributes become properties of the component itself, putting them in the same place as other internal state.

This can be somewhat confusing, because it may not be obvious to the reader of a component's JavaScript or template which values are internal, and which are passed in as part of the public API.

To remind themselves, many Ember users write their components like this:

export default Component.extend({
  /* Public API */

  src: null,
  paused: null,
  title: null,

  /* Internal */
  scrubber: null
})

It can also be unclear how to react to a change in the external properties. It is possible to use observers for this purpose in Ember, but observers feel low-level and do not coordinate very well with the rendering process.

To reduce confusion, we plan to move external attributes into a new attrs hash.

If you invoke a component like this:

<my-video src={{movie.url}}></my-video>

then the my-video component accesses the passed-in src attribute as this.attrs.src.

We also plan to provide lifecycle callbacks (modelled after React's lifecycle callbacks) for changes to attrs that will integrate with the rendering lifecycle. We plan to supplement the API with callbacks for changes in individual properties as well.

Transition Plan

In Ember 1.10, we will begin installing provided attributes in the component's attrs hash. If a provided attribute is accessed directly on the component, a deprecation warning will be issued.

In applications, you should update your component JavaScript and templates to access provided attributes via the component's attrs property.

In Ember 2.0, we will stop setting attributes as properties on the component itself.

We will also provide a transitional mixin that Ember addons can use that will make provided attributes available as attrs.*. This will allow add-ons to move to the new location, while maintaining support for older versions of Ember. We expect people to upgrade to Ember 1.10 relatively quickly, and do not expect addons to need to maintain support for Ember 1.9 indefinitely.

Routeable Components

Many people have noticed that controllers in Ember look a lot like components, but with an arbitrary division of responsibilities. We agree!

In current versions of Ember, when a route is entered, it builds a controller, associates a model with it, and hands it off to an (old-style) view for rendering. The view itself is invisible; you just write a template with the correct name.

We plan to transition to: when a route is entered, it renders a component, passing along the model as an attr. This eliminates a vestigial use of old-style views, and associates the top-level template with a regular component.

Transition Plan

Initially, we will continue to support routing to a controller+template, so nothing will break. Going forward, routes will route to a component instead.

In order to do that refactoring, several things will change:

  • Instead of referring to model properties directly (or on this), you will refer to them as model.propName.
  • Similarly, computed properties that move to your component will need to depend on model.propName if they are migrated from an ObjectController.
  • In both cases, the short version is that you can no longer rely on the proxying behavior of ObjectController or ArrayController, but you can remedy the situation by prefixing model. to the property name.
  • Unlike controllers, top-level components do not persist across navigation. Persistent state should be stored in route objects and passed as initial properties to routable components.
  • In addition to the asynchronous model hook in routes, routes will also be able to define a attrs hook, which can return additional asynchronous data that should be provided to the component.
  • Routeable Components should be placed in a "pod" naming convention. For example, the component for the blog-post route would be app/blog-post/component.js.

We plan to land support for routeable components in Ember 1.12, and deprecate routeable controllers at the same time. We plan to remove support for routeable controllers in Ember 2.0. This will allow you to move your codebases over to routeable components piecemeal before making the jump to 2.0.

We will also provide an optional plugin for Ember 2.0 apps that restores existing behavior. This plugin will be included in the Ember automated test suite to ensure that we do not introduce accidental regressions in future releases on the 2.x series.

We realize that this is the change has the largest transitional cost of all the planned features, and we plan to dedicate time to the precise details in the full RFC on this topic.

Improving Actions

Today's components can communicate with their parent component through actions. In particular, the sendAction method allows a child component to invoke a named action on the parent (inside of the actions hash).

Part of the reason for this API was a limitation in the original Handlebars syntax:

{{!-- we can't get too fancy with the value of key-press --}}
{{input key-press="valueChanged"}}

In this example, when the input component calls this.sendAction('key-press'), it invokes the valueChanged action on its parent component.

With the new HTML syntax for components, we have more flexibility:

<input key-press={{action "valueChanged"}}>

This will package up the parent's valueChanged action (in the actions hash) as a callback function that is available to the child component as this.attrs['key-press'].

export default Ember.Component.extend({
  keypress: function(event) {
    this.attrs['key-press'](event.target.value);
  }
});

The benefit of this approach is twofold:

  • Actions are no longer treated specially in the component API. They are simply properties packaged up to be called by the child component.
  • It is possible to pass an alternative function as the key-press, reducing the child component's knowledge of what the callback is doing. This has testing and abstraction benefits.

Transition Plan

We will continue to support the sendAction API for the forseeable future in today's Handlebars syntax.

When calling an existing component with new HTMLBars syntax, you do not need to change your existing actions hash. You should change syntax that looks like this:

{{video-player playing="playingBegins"}}

To this:

<video-player playing={{action "playingBegins"}}>

The video-player component's internal use of sendAction will work with both calling styles.

New components should use this.attrs.playing(), but existing components that want to continue supporting legacy callers should continue to use sendAction for now. The sendAction API will seamlessly support both calling styles, and will be supported for the forseeable future.

// instead of
this.sendAction('progress', value);

// new code can use
this.attrs.progress(value);

Onward

Version 2.0 marks the transformation of Ember from simply an MVC framework to a complete front-end stack. Between Ember's best-in-class router, revamped components with virtual DOM, easy-to-use build tools, and a growing ecosystem that makes taking advantage of additional libraries a breeze, there's no better way to get started and stay productive developing web apps today.

Hopefully, this plan demonstrates that staying on the cutting-edge can be done without rewriting your app. There are a huge number of Ember apps in production today, and we're looking forward to a time in the very near future where they can start to take advantage these new features.

Expect to see many more RFCs covering these features in depth soon (including a roadmap for Ember Data 1.0). We look forward to hearing your feedback!

@Robdel12
Copy link

Robdel12 commented Nov 3, 2014

This is amazing.

In Ember 2.0, Ember CLI and ES6 modules will become first-class parts
of the Ember experience. We will update the website, guides, documentation,
etc. to teach new users how to build Ember apps with the CLI tools and
using JavaScript's new module syntax.

I'd love to help. Any specifics on how to?

@fivetanley
Copy link
Member

A side note about migrating: please start opening use case issues here: https://github.com/fivetanley/ember-cli-migrator

@igorT and I are building a command line tool to help you migrate as we have the time. It's currently not usable from the command line (you might be able to use a custom node script), but we're interested in the following use cases:

  • Detecting third party dependencies like moment, jQuery UI, etc and doing the import statements for you.
  • migrating tests over

and probably some other stuff I'm forgetting.

I'm hoping to get something usable out the door by Black Friday (November 28th, 2014, the day after thanksgiving). I'd love to here the use cases of people trying to migrate on that repository (please don't respond to this comment here)

@Pradeek
Copy link

Pradeek commented Nov 3, 2014

Many people have noticed that controllers in Ember look a lot like
components, but with an arbitrary division of responsibilities. We
agree!

I've never understood the real pull of writing everything as a component. Going by what web components are defined like, I would imagine components are reusable generic standalone templates+logic. Generally a web app involves using multiple such components in some combination to get the business logic required. What advantage does changing "everything" into a component actually provide? Is it just a matter of "cleanliness" or is there some other benefit? Most routes I imagine are not going to be reusable, so can you guys explain the rationale on this a bit more?

@James1x0
Copy link

James1x0 commented Nov 3, 2014

@Pradeek I have to agree with you. Components are reusable and drop-in. Routes just aren't reusable in nature. I would like the rationale for this change as well.

@jacefarm
Copy link
Contributor

jacefarm commented Nov 3, 2014

👍

@nybblr
Copy link

nybblr commented Nov 3, 2014

Great thoughts, really excited to see where Ember is headed.

My only concern is the CLI: while CLIs n' such are nice to begin with, most of the time they get in the way if you need to customize it to another build tool. For example, when Famo.us first came out, it was entirely based around their CLI, which made any real world use a royal pain.

Will Ember 2.0 remain easy to pull in to a custom build system, etc. without the CLI?

@wycats
Copy link
Member

wycats commented Nov 3, 2014

@Pradeek In today's controllers, there are usually several things going on:

  1. A few properties that are meant to persist across navigations and may be attached to query parameters
  2. Computed properties that convert those properties into something suitable for display
  3. Handling events produced by the top-level template, and manipulating those properties

Looking at a lot of apps (including our own) and listening to people ask us questions about the role of the controller, it is clear that the last two responsibilities above have equivalents on components. Letting you think of the top-level context as a component doesn't harm the architecture at all, but removes an unnecessary component.

As for the second bullet, we agree that there is a need for a place to store a small number of properties that persist across navigations, similar to the "session" concept in server-side frameworks, but that requirements has grown into a vestigial top-level role in the system that we think makes it ambiguous where to put common functionality.

In short, the extra concept simply wasn't paying its way. After answering "what exactly should go in the component" hundreds of times to new developers at trainings, clients, attendees at hack nights and more, we realized that everyone would be better off by moving the responsibilities into objects with more clearly designed responsibilities.

Nothing is stopping you from breaking out functionality or logic that you don't think really belongs associated with the view layer into a separate object, and we definitely encourage experienced developers to decouple their code!

@taras
Copy link

taras commented Nov 3, 2014

@Pradeek @James1x0 the difference between current route controllers & future component is largely ergonomics.

Technically speaking both are very similar. Currently, when a user enters a route the router instantiates a controller and binds it to a template. An virtual view is created which handles events that are triggered in the DOM. So, we have a route + controller + template + view, but all of these have separate classes with properties that need to be wired together by the template.

With the new approach, you still have route but controller, template & view are unified into 1 component. This makes it a lot easier to keep track of all of the code that is related to one route. You can actually use a component for a route today, but it requires a bit of extra wiring and it's not as well organized as it will be in the future.

@wycats
Copy link
Member

wycats commented Nov 3, 2014

@nybblr we're going to focus on making the CLI the best possible experience, but there are two decent escape valves:

  • The Ember framework itself is decoupled from the file system; it looks for modules through an object called the "resolver". Ember 2.0 applications will need to use some JavaScript module system, but an AMD-based or CJS-based resolver will work without any changes to the framework itself.
  • The division of responsibilities between Ember CLI and other build systems is pretty clear: you can have your build system invoke Ember CLI commands as part of the build process. At @tildeio, our Ember app is a full Ember CLI app, but it's integrated with our Rails development server and request/response lifecycle so we can run the two together seamlessly.

I expect people to build integrations along both of these lines in the months ahead.

@lrdiv
Copy link

lrdiv commented Nov 3, 2014

👍 👍

@opsb
Copy link

opsb commented Nov 3, 2014

This looks very good! Couple of questions about actions:

  1. With routing directly to components, will events generated in components be able to bubble up through parent components?
  2. It looks like it will be possible to return a promise from actions, is this the plan?

@searls
Copy link

searls commented Nov 3, 2014

@nybblr a vain and jealous part of me (as maintainer of @linemanjs) is disappointed that moving forward, there will be an expected 1:1 coupling between "ember apps" and "the build tool for ember apps", but I think this is absolutely the right move.

We wrote Lineman because it gave us the opportunity to package a massive number of build configurations when all we set in stone were a handful of important conventions (e.g. javascript goes here, fonts go there). We intentionally only focused on things at the file-organization layer, because we wanted to stay out of any framework churn (and there's been plenty of it in the two years since), making it really easy to switch between projects.

What attracted me to Ember, and why I loved @wycats' Railsconf 2014 keynote, is that the same embrace of a handful of carefully-planned conventions provide a tremendous amount of productivity to people writing Ember apps. By just following those, you get default behavior "for free", and that lets developers focus on more important problems. In fact, it actively discourages developers from answering a myriad of meaningless questions about code organization and naming, which is sometimes just as important.

When I read @tomdale's 2.0 roadmap note, and as I've watched ember-cli pick up steam from the sidelines, I'm encouraged to believe that the project is now at a point of maturity, size, and understanding to establish conventions in both build tools and framework APIs that will play together really nicely.

Rails is the best analogy I can think of to all of this. When I install a gem targeting Ruby on Rails apps, I can expect it will work with default behavior, more-or-less without me telling it to do anything. We're already seeing the same sort of phenomenon emerge in the nascent ecosystems of ember-cli extensions, and in my opinion that's fantastic. None of this would be practical or advisable, by the way, without the careful shepherding of API changes that the team is demonstrating in this thread.

Integrating ember CLI as a first-class part of the Ember experience accomplishes things that no other front-end web framework can do. I'm really excited for Ember's future.

@Pradeek
Copy link

Pradeek commented Nov 3, 2014

@wycats I agree with the thoughts behind the computed properties and event handling, but calling it a "component" seems wrong to me because the term is largely associated with reusability which might be confusing in the long term. I had always considered the controller to mask the app business logic from the UI specific ones. Now it seems to me like that extra layer of separation would be lost.

@Pradeek
Copy link

Pradeek commented Nov 3, 2014

@wycats For example, calling both a drop down and my entire detail page as components does not seem very clear on what a component entails.

@bcardarella
Copy link
Contributor

Would it make sense for certain components to get mutable properties by default? For example, instead of <input value={{mut name}}> the Input component could be aware that the property being passed should be mutable internally, so you only have to do <input value={{name}}>. I can't think of many situations where you would want one-way bindings for inputs.

And there seemed to be lack of consistency in how properties are defined in HTMLBars. For examples I saw both <my-thing foo="{{bar}}"> and <my-thing foo={{bar}}>. Are the quotes around the property required?

@stopachka
Copy link

So excited right now! Go ember team :)

@thecodejack
Copy link

Routeable Components looks like a big change. For sometime i didn't see the use of it but now clearly removes the usage of controller from component which is really a welcome move.

@opsb
Copy link

opsb commented Nov 3, 2014

What will happen to the model hook now? If the router is going to assign attrs to components then there doesn't seem to be any reason to limit it to a single model. With query params and dynamic segments I can't see any reason why the model hook shouldn't return any number of attrs (perhaps just have an attrs hook instead of model?).

@juggy
Copy link

juggy commented Nov 3, 2014

Will the "bool:true:false" syntax for classes be there still for the attribute bindings? Will we be able to use it for other attributes like style?

It would be nice to be able to use the syntax within {{}} and {{mut }} as well.

I know @wycats does not like too much logic in the templates, so can you share your view there?

@wycats
Copy link
Member

wycats commented Nov 3, 2014

And there seemed to be lack of consistency in how properties are defined in HTMLBars. For examples I saw both <my-thing foo="{{bar}}"> and <my-thing foo={{bar}}>. Are the quotes around the property required?

This is actually intentional. The main point is that " means a string literal (with interpolation), while no " means passing a value directly. This is similar to today's distinction in Handlebars syntax.

There is a key difference in HTML between attributes, which are always strings, and properties, which aren't. Most developers don't have a clear mental model for this, which became obvious to me when we tried to roll out $.prop in jQuery, but the difference exists nonetheless.

React, Angular 2.0 and Ember all have to deal with this problem, and there are several different options:

  1. Ember 1.x: All properties become JavaScript properties on the component, with a whitelist of attributes (attributeBindings). That worked ok with the old component syntax {{my-video src=url isPlaying=val}}, but was already somewhat confusing for common attributes that we didn't whitelist in the framework. We also don't think this will work at all when we switch to HTML-based syntax (people will expect <my-video title={{val}}> to set the HTML attribute title)
  2. Angular 2.x original announcement: Attributes are always attributes, unless surrounded in [], so <my-video title="{{val}}"> works as expected, but <input checked="{{val}}"> will not work as expected (<input [checked]="{{val}}"> is required).
  3. React: All values are properties. If you want a string, quote the value. You are required to use the property form of attribute names (<label htmlFor=val> instead of <label for=val>, <div className=val> instead of <div class=val>, multi-word attributes like maxlength must use the camelcased form).
  4. Ember 2.0: Same as React (all values are properties, and quoting creates a string), except that we map the attribute naming in HTML to properties and we handle any quirks in the mapping between props and attributes. In the vast majority of cases, the DOM's prop->attr binding does the thing you would expect, so this helps people maintain their existing mental model (and use existing HTML code).

All of that is somewhat involved, but our major goal was to try to smooth out the attrs/props distinction if at all possible for many, many cases. So the TLDR is "write attributes as you would have before, and use the string form if you want to pass a string as opposed to a value". We weighed a lot of different usage patterns, and given the capabilities of a pre-processor, this seemed like the best path.

In general, we are trying to keep our HTML dialect very close to regular HTML (especially compared to the Angular 2.x announcement and React's approach), but are willing to make small tweaks that wouldn't work with a traditional HTML parser if it simplifies how people write templates in a way that matches the natural expectation.

@rwjblue
Copy link
Member

rwjblue commented Nov 3, 2014

Will Ember 2.0 remain easy to pull in to a custom build system, etc. without the CLI?

The guides and documentation will definitely be focusing on usage with Ember CLI, but it will absolutely be straight-forward to use with whatever build tool you would like. We will continue to have builds published to the various channels (currently we use Bower, RubyGems, http://emberjs.com/builds/).

@workmanw
Copy link
Contributor

workmanw commented Nov 3, 2014

I think the only thing that gives me pause is the Routeable Components. On the surface I appreciate the harmony this will bring to the API. And might be a little easier for new users to understand. But this feels like a bit of a move away from MVC. One of the greatest things about the separation between views and controllers is their life cycles.

To put a head on my concerns.

  • Persistency of temporary domain state. With the current V/C pattern it is possible for a user to navigate away and return to where they are. Keeping the controller state in tacked.
  • Separation of class hierarchy. We have quite a few really really customized views and similarly controllers. These do everything from drag/drop, mouseMove, keyUp, etc on the view side, to selection, commenting, realtime support, etc on the controller side. That's a wide range of responsibilities to get mashed on to a single class. And organizing that becomes a bit harder.
  • Separation of responsibilities. Views handling user interaction (app state). Controllers handling ajax requests (domain state). I.E. it feels weird that my mouseDown event handler is right next to my ajax server call.

TL;DR; Concerns: Blurred lines between app state and domain state w/ Routable Components.


Edit: Adding another concern:

  • Caching of server query results. With the current V/C pattern, it's possible for users to jump between a list of items, a full detail view for an individual item when they do not share a route resource hierarchy. The list controller can keep a cached copy of that query results as to not add a delay an impact UX.

@mgenev
Copy link

mgenev commented Nov 3, 2014

I can't say I understand well what's happening with controllers / components. What is to gain with phasing out controllers and how are we going to handle the arrayController - itemController relationship?

@sandstrom
Copy link
Contributor

I like this roadmap!

The idea of 'Stability without Stagnation' is great. You've stricken a good balance so far, and it's important to stay on top of changes in html/js/browsers to remain relevant as a framework. The future is bright for Ember! 😄

I have some gripes with routable components, mostly with the naming (apart from naming, the changes sound reasonable, so no immediate objections there).

In my mind a component is a small, reusable piece of code. Some are reusable to the point where other projects could use them, and other components are reusable within a project.

I'd argue that a 'routable component' is remote from what most people associate with a component, to the point where it would be better if it's called something else.

Perhaps there another name (which doesn't allude to reusability) that would be a better fit for this route-driven component. It could be identical to a component, but with a name that makes its role less confusing.

Also, will controllers remain (as item-controllers) and virtual/generated controllers for these new, routable components? Although I assume they remain, perhaps that could be clarified in the section on routable components.

@mitchlloyd
Copy link

@mgenev Using an array controller with an itemController behaves a lot like creating a component inside of an {{#each}} block. I would imagine that the itemController concept could be replaced with a component, but I would be interested in hearing a core team member weigh in on itemController.

I'm with @Pradeek as far as being concerned about naming and vocabulary when losing "controller". I think just as we have different names for different types objects in OO programming we're going to need to develop names for the "small, reusable components" and the "domain-specific, application components".

I'm also curious about the life-cycle of routable components. I like being able to click a checkbox in my UI, navigate away and then return to see that checkbox still checked. I'll be interested to see how moving this application state to routes changes things.

@kumavis
Copy link

kumavis commented Nov 3, 2014

Re: Routeable Components

Does this mean we will put our {{outlet}} tags in our component's templates?

Currently components only emit actions that have been specified. Does this mean we need to name all actions we expect to bubble through our routable components?

Here is a contrived example as I'm not sure what it would actually look like

<video-section playingBegins={{action "videoStart"}} videoSelected={{action "videoChanged"}}>
  <video-player playing={{action "playingBegins"}}></video-player>
  <video-list selected={{action "videoSelected"}}></video-player>
</video-section>

@wycats
Copy link
Member

wycats commented Nov 3, 2014

The comments about "component" connoting "reusable" are very good. @tomdale had said something similar to me (and at the face to face), but it was hard to know without general feedback, so this is very good.

Thanks all!

@gtrak
Copy link

gtrak commented Nov 3, 2014

Composable components! Exciting news for a clojurist trapped in ember-land. Overall, this looks really coherent and addresses many of my gripes with 1.x.

@alexblom
Copy link

alexblom commented Nov 3, 2014

Way to go. Very excited for Block Params. 👍

@mgenev
Copy link

mgenev commented Nov 3, 2014

"Currently components only emit actions that have been specified. Does this mean we need to name all actions we expect to bubble through our routable components?"

@kumavis I wondered the same about that. It would be highly inconvenient.

Overall, I don't see how a component can replace controllers cleanly and maintain the ease of use. I'm of course open to persuasion by the smart guys on the core team, but I'd need to see all the possible usages addressed like

-arrayControllers
-itemControllers
-queryParams
-sorting
-filtering
-actions
etc.

to me as well, a component is something that should be reusable across apps. A controller has many other uses.

@changeweb
Copy link

One may need to use lots of dependencies between components. needs in controller manages dependencies between controllers pretty well. We need something like needs or better dependency handler for route as well as components in Ember 2.0.

@knownasilya
Copy link
Contributor

@changeweb
Copy link

@knownasilya Sorry I've not seen them before. I used needs which is functionally equivalent to Ember.inject.controller().

Thanks for mentioning Ember.inject.service(). I think Ember.inject.service() will do the work by making properties easily accessible in the model hook.

@mgenev
Copy link

mgenev commented Jan 20, 2015

@changeweb this stuff is just coming out now in 1.10 that's why you haven't seen it

@kristianmandrup
Copy link

@hipertracker I totally agree with sentiments. Time has run out for "complete" MVC frameworks. Ember should be split up into smaller parts. Why be forced into a specific template language such as Handlebars. I just don't get it. It made sense at the time I guess (~4 years ago). All about being lightweight and flexible and build the architecture to your specific needs... Travel light ;)

@drogus
Copy link

drogus commented Feb 1, 2015

Why be forced into a specific template language such as Handlebars.

You're not forced to use Handlebars.

@kristianmandrup
Copy link

@drogus oh cool, well I assumed only Handlebars since I have yet to see an example of another Template language being used with Ember. How easy is it to opt out and use your own favourite (Reactive) rendering engine? Opens up some new exciting possibilities :)
I know there is a React-Ember library, but assumed it hooked into Handlebars as well... Thanks!

@changeweb
Copy link

@kristianmandrup Have you read this can-reactjs-be-used-as-a-view-within-emberjs. For short Using React and Using Ember view.

I think you can do almost all react thing with Ember view.

@kristianmandrup
Copy link

@changeweb Awesome! Must admit I had been a bit disillusioned about both Ember and Angular lately... will be interesting to see how Ember 2.0 will shape up in the end. It is key that it is suficiently lightweight/flexible and doesn't "lock you in" IMO

@taras
Copy link

taras commented Feb 1, 2015

@kristianmandrup

Why be forced into a specific template language such as Handlebars.

You can use Emblem.js with Ember instead of Handlebars, but I'm not sure what it's future is. Ember is all about creating happy paths. Handlebars is the happy path for tempting with Ember. Once HTMLBars if fully baked into Ember, it will probably be possible to have other syntaxes use it to provide other templating syntaxes.

Ember should be split up into smaller parts.

Ember is already made out of many small parts. Templating is provided by Handlebars.js, Promise implementation is done with RSVP.js. The run loop is backburner.js. The router is router.js. There are many more.

All about being lightweight and flexible and build the architecture to your specific needs... Travel light ;)

Ember never aimed to be lightweight. That's why it's a framework and not a library. It's always been created to provide everything that developers need to be productive.

@kylecoberly
Copy link

I agree with Taras- there are plenty of roll-your-own options out there,
and Ember is already pretty pretty modular.

On Sun, Feb 1, 2015 at 10:19 AM, Taras Mankovski notifications@github.com
wrote:

@kristianmandrup https://github.com/kristianmandrup

Why be forced into a specific template language such as Handlebars.

You can use Emblem.js http://emblemjs.com with Ember instead of
Handlebars, but I'm not sure what it's future is. Ember is all about
creating happy paths. Once HTMLBars if fully baked into Ember, it will
probably be possible to have other syntaxes use it to provide other
templating syntaxes.

Ember should be split up into smaller parts.

Ember is already made out of many small parts. Templating is provided by
Handlebars.js http://handlebarsjs.com, Promise implementation is done
with RSVP.js https://github.com/tildeio/rsvp.js/. The run loop is
backburner.js https://github.com/ebryn/backburner.js/. The router is
router.js https://github.com/tildeio/router.js/.

All about being lightweight and flexible and build the architecture to
your specific needs... Travel light ;)

Ember never aimed to be lightweight. That's why it's a framework and not a
library. It's always been created to provide everything that developers
need to be productive.


Reply to this email directly or view it on GitHub
#15 (comment).

@knownasilya
Copy link
Contributor

The only thing missing is tree-shaking, to remove the unused parts and make your app speedier.

@mgenev
Copy link

mgenev commented Feb 2, 2015

@knownasilya +111111

@heat
Copy link

heat commented Feb 9, 2015

Ember never aimed to be lightweight. That's why it's a framework and not a library. It's always been created to provide everything that developers need to be productive.
I agree
It's what I looking for. It sounds great when I hear about decoupled parts and pluggable. But nowadays what I want is productivity.

@davidlormor
Copy link

So I just wanted to chime in again on the discussion around routable components - I think I've seen the light, so to speak. After migrating my "very large" ember project to ember-cli and adopting a "component-centric" development approach, I "get it"...actually it feels painful when I have to spin up a View to wrap my route-associated templates now.

While I still feel there is definite validity to the arguments around the separation of concerns, object/array controller associations, and service controller, I've heard a lot from core team members lately via various channels and am confident that they're driving this forward in a way that will properly deal with those concerns. The development momentum I've built the past couple months using this approach can't be denied, and am super excited about the future of this framework!

@quantuminformation
Copy link

best news of all:

Instead, we plan to do the vast majority of new work on master (behind feature flags), and land new features in 1.x as they become stable.

@adrianboston
Copy link

NSArrayController->selectedObject cici n'est pas une cocoa

@wycats
Copy link
Member

wycats commented Feb 21, 2015

This was a really awesome discussion that significantly informed the Ember 2.0 direction. From this point forward, it makes more sense to open new RFCs for new features. If there's a feature you want implemented, definitely start a conversation about it.

Pieces of this RFC have since been expanded to full RFCs, or have been implemented, so definitely continue any relevant discussion on those RFCs.

For the big enchilada, expect an RFC for Routable Components to come in the next few days. You can also follow along with the new component implementation at emberjs/ember.js#10501

@mmun mmun force-pushed the ember-2.0-rfc branch from 6e0fba7 to ffdf7ef Compare June 7, 2015 18:47
mmun added a commit that referenced this pull request Jun 7, 2015
@mmun mmun merged commit ae0215d into master Jun 7, 2015
@mmun mmun deleted the ember-2.0-rfc branch June 7, 2015 18:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.