Giter VIP home page Giter VIP logo

Comments (16)

nathanhammond avatar nathanhammond commented on May 15, 2024 1

Another option is to require "static" imports into the component itself of everything it could possibly render via "dynamic" lookup. This could be opt-in behavior which makes it a concept you can put off "until you need it." (Power user feature with a mostly painless late-opt-in strategy.)

{{import "hello-world"}} (uses default resolution behavior)
{{import "hello-world" from="starter-app/hello-world.js"}} (uses path traversal from root namespace)
{{import "hello-world" from="../hello-world.js"}} (uses relative path traversal)

This means you don't have to specify what is whitelisted per component helper (though that could become a perf optimization) you would just do it per template (since the template truly drives what is included, not the backing JS file).

from rfcs.

ef4 avatar ef4 commented on May 15, 2024 1

"Power user feature" is the last resort when there is no solution that stays within concepts everybody needs to learn anyway. That is a high bar and I don't think we've hit it here.

In-template import is a pretty large design space that goes beyond this particular issue. If we were to introduce it, it would need to actually do all the things people might reasonable expect it to do, and I think it will rapidly become all of ECMA import. And it would risk bifurcating community efforts between people who think you should import everything and people who think you should use the resolver. There needs to be an unambiguous answer to "which way should I do this?" that is not "whatever floats your boat".

I think we can just make the resolver itself sufficiently static, fast, and friendly that it does the right thing for beginners and power users alike. And we have public API for writing your own resolver anyway, which is the true power user escape valve.

from rfcs.

nathanhammond avatar nathanhammond commented on May 15, 2024

/cc @chadhietala @trentmwillis

from rfcs.

lukemelia avatar lukemelia commented on May 15, 2024

It might be useful to be able to specify a pattern, which would cover what is in my experience the most common use case for the component helper (rendering a family of similarly named components), minimize the hassle of remembering to update the whitelist as new variation are added, and still allow for graph resolution.

from rfcs.

chadhietala avatar chadhietala commented on May 15, 2024

Not sure why you can't just do this:

import ShareUpdate from './share-update';
import ViralUpdate from './viral-update';

const VALID_TYPES = [ViralUpdate.type, ShareUpdate.type];

export default class Feed {
  constructor(attrs) {
    this.updates = attrs.updates.filter((update) => VALID_TYPES.indexOf(update.type) > -1)
  }
}

export const template = hbs`
  {{#each updates as |update|}}
    {{component update.type}}
  {{/each}}
`

Colocation solves this pretty nicely for these types of problems.

from rfcs.

rwjblue avatar rwjblue commented on May 15, 2024

@nathanhammond:

I don't see how we can (within 2.x) make any currently valid name a build time error. The only thing that would be SemVer compatible would be something that errors today. whitelist is currently a valid property to pass into, and in general seems like a fairly common name to already be in use. In theory we could try to hedge our bets and make it something less likely to conflict, but without additional syntax anything we pick would technically be a breaking change.

@chadhietala:

Not sure why you can't just do this

You absolutely could! But yuck 😜

from rfcs.

trentmwillis avatar trentmwillis commented on May 15, 2024

As an alternative to "whitelisting" components in the templates, I tend to favor an idea like what @chadhietala suggested, where we whitelist components on the JS side of things. I don't necessarily think we need to colocate templates in the JS (though that is an option). Instead we could introduce a simple new class that represents a "union" of classes:

import SomeComponent from './some-component';
import OtherComponent from './other-component';
const SomeOtherComponent = UnionComponent.from(
  SomeComponent,
  OtherComponent
);
export default SomeOtherComponent;
{{! componentToUse = "some-component" }}
{{some-other-component componentToUse}}

Pros:

  • No build time magic needs to happen
  • Mapping dependencies should require no extra logic beyond what we need for normal components
  • New API (no backwards compatibility issues)

Cons:

  • New API
  • Requires more overhead than using a solely template-based solution

from rfcs.

chadhietala avatar chadhietala commented on May 15, 2024

@trentmwillis We are sort of re-creating a type system as I don't know what the return type UnionComponent.from would return.

from rfcs.

nathanhammond avatar nathanhammond commented on May 15, 2024

@rwjblue You're correct that this would be a breaking change. Anything in this proposal (or the alternatives described by Chad/Trent) would be implemented as an addon and then possibly be imported into core. Since this is relatively simple to implement as an addon I don't care about timeline. It could probably be implemented in 2.X as a positional parameter with something like (whitelist "component-name other-name") but that's likely a bad idea for perf reasons.

@trentmwillis / @chadhietala Both of your proposals are easy to accomplish with a stupid-simple addon. It's effectively a custom component helper with a custom backing class. We can identify dependencies by tracing imports in the backing JS file.

The big tradeoffs I see:

  • The attribute would be a lot easier to teach and a bit more difficult to code up as it requires walking the HBS files to calculate the dependency graph.
  • The explicit imports are a lot more clear as to what's happening and would require no additional pass of the HBS files to calculate the dependency graph.

from rfcs.

trentmwillis avatar trentmwillis commented on May 15, 2024

So I decided to take a stab at implementing my UnionComponent idea. To answer @chadhietala's question, from returns a "component factory". The implementation is pretty straightforward, but suffers from one big issue: re-rendering with a different component type doesn't work. Now I'm not sure if that's a major use-case, but given that it is supported by the {{component helper it would probably be a desirable feature for parity.

The only way I can think of supporting it at this time would be via registering all "unions" as new keywords (similar to {{component), but that obviously has large, negative consequences with it.

from rfcs.

mixonic avatar mixonic commented on May 15, 2024

I'd suggest this be done with a linting rule and a helper to allow static analysis. Create a helper for whitelisting:

{{component (allow-components dynamicName 'permitted-comp' 'another-permitted-comp')}}

At dev-time, allow-components can assert for unexpected values. At prod time it is cheap enough to leave probably, or you can strip it out.

And then add a rule for the https://github.com/rwjblue/ember-cli-template-lint linter that requires all {{component helpers to be passed an allow-components subexpression.

Hell if you went wild with the template pre-processors, you could make the whitelist= syntax work and just compile it to be above :-)

I'm not sold on the value of making this into an Ember feature though, since the main value seems to be for a static analysis tool from outside of Ember.

from rfcs.

chadhietala avatar chadhietala commented on May 15, 2024

@mixonic I think the purpose was to tie everything together e.g. JS + HBS. When you are trying to resolve the dependency graph it's probably best to use Import/Export declarations than having to parse both JS and templates to arrive at the final graph.

from rfcs.

mixonic avatar mixonic commented on May 15, 2024

@chadhietala can you say more? I'm not clear on why an argument to the component helper is easier to resolve dependency-wise than a user-space helper. Seems basically the same?

from rfcs.

chadhietala avatar chadhietala commented on May 15, 2024

Not really arguing framework v. user space. I'm coming from the approach that if you want to understand how components are used in your application, its easier to do static analysis on something that has a module system.

from rfcs.

ef4 avatar ef4 commented on May 15, 2024

This came up in discussion of module unification and static resolver. A leading idea was a 'namespace' option on the component helper. Namespaces are already a thing in rfc 143 and they make a good-sized bucket for restricting dynamic component resolution. We can even forbid unqualified targeting of other namespaces as part of the module unification rollout.

This has nice behaviors even for people who don't do anything special: unused components could be shaken out of all their addons, despite usage of the dynamic component helper in their apps namespace. And people who want shaking within their app can segregate dynamically targeted components into their own package.

from rfcs.

rwjblue avatar rwjblue commented on May 15, 2024

This will be addressed by "template imports" which is currently being discussed in #454. Closing this in favor of that PR.

from rfcs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.