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

Template-only Components #278

Merged
merged 3 commits into from
Jan 3, 2018
Merged

Template-only Components #278

merged 3 commits into from
Jan 3, 2018

Conversation

chancancode
Copy link
Member

@chancancode chancancode commented Dec 11, 2017

@cibernox
Copy link
Contributor

cibernox commented Dec 11, 2017

I have two questions about this, on two areas that might cause breakages not listed:

  1. Right now, all applications have an implicit wrapper, that is sometimes targeted in CSS as body > .ember-view. Will the implicit top-level outlet behave like a template-only component? If not, why?
  2. A similar issue happens in testing, where there is a #ember-testin > .ember-view wrapper around everything. Same questions: Will that go away? Why/why not?

0278-template-only-components.md Show resolved Hide resolved
0278-template-only-components.md Outdated Show resolved Hide resolved
0278-template-only-components.md Outdated Show resolved Hide resolved
@chancancode
Copy link
Member Author

chancancode commented Dec 11, 2017

@cibernox this RFC does not change that (would you like to pick that up in another RFC? I think that is a good idea, just not particularly related to this)

Update: here it is! #280

@chancancode chancancode changed the title Add "Template-only Components" RFC Template-only Components Dec 12, 2017
@sdhull
Copy link

sdhull commented Dec 13, 2017

Possibly a dumb question:
Can you already achieve this by doing {{template-only-component tagName=''}}?

EDIT: Just tested this on my app and it does indeed work. I guess this discussion is about making that be default behavior...

@chancancode
Copy link
Member Author

chancancode commented Dec 13, 2017

I implemented the feature (behind a flag). You can try this on canary now: https://ember-twiddle.com/a2013417648c4dced26ae78e8aaa5e6a?openFiles=templates.application.hbs%2C

Reminder: since the new semantics does not auto-reflect arguments as properties, you will have to use the named arguments syntax in #276 if you want to access them. (See hello-world.hbs for an example.)

@rtablada
Copy link
Contributor

@chancancode Looking at this PR I think there's some confusion in what are called "Template Only Components"

Based on recent meetup and conference talks the idea of a Template Only component seems to be understood as a component that can be statically optimized and inlined where used or used as a single lookup without the overhead of a stateful component (similar to ember-ast-helpers or the current Glimmer implementation).

While this RFC definitely removes the blocker of the surrounding div, I think that naming the removal of this div as "Template Only Components" will lead to confusion.

@rtablada
Copy link
Contributor

As a suggestion I think "Template Only Component HTML".

@chancancode
Copy link
Member Author

chancancode commented Dec 13, 2017

@rtablada it actually does pave the way for all of that.

Here is the code to support Ember.Component (actually, that doesn't even include the Ember.Component class itself and all its mixins!) and here is all the code needed to support the new style template-only component in this RFC.

Even if you are not familiar with the internals, you can probably intuit that the latter is doing a lot less work. More importantly, since it does not have an instance associated with it (create, getSelf and getDestructor all returns null), the VM will be able to take advantage of that fact and do some of the optimizations you mentioned.

However, optimizability is not really a user visible change. From the user's perspective, this is mostly just a developer ergonomic improvement (which IMO stands on its own and then some). It just happens to also be a trojan horse for landing Glimmer Components and performance improvements as well.

It's not how I would choose to teach it, but you are welcome to call this stateless component, pure component or functional component if you want 😉

@bartocc
Copy link

bartocc commented Dec 14, 2017

I like the idea of "Outer HTML" very much, but at the moment, 2 things bother me with this RFC:

  • I believe the ember-component-css addon would definitely break. If I am correct, the addon adds componentCssClassName/styleNamespace on every Ember.Component instance and then uses this property to render the CSS from styles.less. With no Ember.Component instance for template only components, ember-component-css would become unusable, and not being able to style components with this addon is a drawback that outweighs the benefit of "Outer HTML" in my opinion. Adding an empty .js file would be a workaround though, but quite cumbersome.

  • We would have different behaviours for components with a .js file and components without it. This could be confusing for developers. In my mental model, all components should behave the same. Should we consider using a different folder for template only components to make things clearer ?

@joukevandermaas
Copy link

I agree with @bartocc; adding a javascript file shouldn't change what is being rendered. I very often start out with just a template and then add a javascript file later when I need a computed, for example.

It would be very nice to have a way to preserve the 'outer html' behavior for components with a javascript file to support this 'upgrading' scenario.

@cibernox
Copy link
Contributor

@joukevandermaas you can. Add tagName: '' to your component's JS file.

@wycats
Copy link
Member

wycats commented Dec 14, 2017

@cibernox exactly! We already have the outerHTML behavior via tagName: '', so a good practice for adding a JS file later is to add tagName: '' to the JS component once you create it.

Glimmer components have a generally better story here for avoiding the need for a this.element in general (through adding event handlers to the top-level element in the component).

My general hope that we can move through these RFCs quickly enough so that the correct transition here will be from "template-only components" to "new-style JS file", and I think everyone is motivated to avoid letting the current status sit for long enough for these problems to become a very serious hassle.

@bartocc
Copy link

bartocc commented Dec 14, 2017

Great! I did not realize that adding tagName: '' was equivalent to outerHTML
🎉

This gives us a pretty good transition path I believe

@webark
Copy link

webark commented Dec 14, 2017

@bartocc things like ECC would adjust their architecture and ergonomics to account for this welcome change!

@mikkopaderes
Copy link

This seems very similar to the functional component in React which I like.

I welcome the change! I hate seeing my template without a root element and when it renders, it'll have <div>. So a lot of my components are just those with tagName: ''. I only have around 1-3 out of hundreds which doesn't define tagName: '' and that's because I needed to access this.element on those.

@chancancode
Copy link
Member Author

This RFC was nominated and approved for Final Comment Period (FCP) yesterday, since most comments have already been replied to. The FCP with last for a week. If there are any substantial new arguments that are brought up during this time, the FCP will be restarted (or aborted). If you haven't reviewed the proposal yet, now would be a great time to do so.

If I may, here is a summary of the main objections:

  1. How does this affect Ember Inspector?

    For now, template-only components will be invisible to Ember Inspector. We will collaborate with @teddyzeenny to propose new APIs that would allow Ember Inspector to track the components tree more accurately.

  2. It is strange that adding a JS file changes the component's behavior.

    This is indeed a change in the model. In the future with the Custom Components API, Ember.Component will no longer be the only kind of components that exists in the ecosystem. But choosing to use a certain type of component in the JS file, you are also opt-ing into the special features/semantics that comes with that breed of components. For Ember.Component, this means having a wrapper element that you can customize in the JS class, for Glimmer Components, that might mean a different API/feature-set, and so on.

    Over time, with the addition of Glimmer Components and other kinds of community components become more popular, we think this will feel very natural.

Meanwhile, since the feature have landed in canary behind a flag, I encourage you to give it a spin and get a feel for it, either using this Ember Twiddle or by using a canary build with the ember-glimmer-named-arguments and ember-glimmer-template-only-components feature flag set to true.

@jamesarosen
Copy link

jamesarosen commented Dec 22, 2017

Will this break ember-feature-flags for template-only components? That addon injects service:features into every component.

If so, I have two ideas:

  1. ember-feature-flags itself can offer a helper like {{feature-enabled 'foo'}}
  2. ember or a simple addon could offer a helper like {{service 'features'}} and template-only components can do {{get (service 'features') 'foo'}}. It may be useful to link to that addon in the addon that enables the global no-wrapping-div flag.

@webark
Copy link

webark commented Dec 22, 2017

i assume one of these template files has to contain valid html.. It can’t be like a series of attributes and you could include on another tag, right?
It could however just include text i assume, and no markup.

@chancancode
Copy link
Member Author

@webark correct, it has to be valid HTML content (which, by extension, includes "just text")

@chancancode
Copy link
Member Author

@jamesarosen Correct. Since there are no instance in this case, {{this.features}} will be undefined. It is unclear that injection will/should work for components other than Ember.Component (my guess is no), but that is probably a question for #213.

I think your first suggestion is spot on.

@chancancode chancancode self-assigned this Dec 22, 2017
@chancancode
Copy link
Member Author

Thanks everyone for your participation! Since no major issues were found during the FCP, we will now close and merge this proposal.

@chancancode chancancode merged commit fa8367b into master Jan 3, 2018
@chancancode chancancode deleted the template-only-components branch January 3, 2018 18:07
@wycats wycats mentioned this pull request Jan 7, 2018
@akatov
Copy link

akatov commented Jan 18, 2018

The link in the description is wrong! Should be https://github.com/emberjs/rfcs/blob/master/text/0278-template-only-components.md

@wycats
Copy link
Member

wycats commented Jan 21, 2018

@akatov looks like it was fixed! Thanks!

chancancode added a commit to emberjs/ember.js that referenced this pull request Jan 24, 2018
These features are enabled by turning them into a runtime flag. These
flags are intended to be set by @emberjs/ember-optional-features. In
the future, these runtime flags might be removed in favor of build-time
flags once the infrastructure is in place.
chancancode added a commit to emberjs/ember.js that referenced this pull request Jan 24, 2018
These features are enabled by turning them into a runtime flag. These
flags are intended to be set by @ember/optional-features. In
the future, these runtime flags might be removed in favor of build-time
flags once the infrastructure is in place.
rwjblue added a commit to emberjs/ember.js that referenced this pull request Jan 24, 2018
@pzuraq pzuraq mentioned this pull request Jan 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.