angular / angular

Deliver web apps with confidence 🚀
https://angular.dev
MIT License
96.09k stars 25.43k forks source link

[feature] variants: overriding components & routes (aka experiments support) #11151

Closed mprobst closed 3 years ago

mprobst commented 8 years ago
[x] feature request

This is a summary of a design discussion with @tbosch and @vsavkin.

Applications commonly need to support multiple variants out of the same code base. That is, we need to serve a slight variation of our application under certain circumstances, but at the same time still need to serve the original version.

Common use cases:

All of these have in common that we only want to surgically vary a specific part of our app under some circumstances, but not wholesale replace or fork the code base. Another consideration is that we'll have many of these variants available concurrently, and an individual app download might need to include multiple variations at the same time (admin user on Black Friday or so). Yet another thing is that disabled variants should have no effect on the served code of the rest of the application at all, i.e. they can be used for code hiding of unlaunched features.

The basic idea is to encapsulate variants in source files, with the source files patching global symbols on load, and in that way changing how the application behaves. The server side chooses to serve the appropriate combination of source files to a user, depending on what variants apply to them, or the client side lazily loads particular variants as needed.

There are two use cases we should support initially:

  1. changing how a single component behaves
  2. adding an entire route to the application

    Components

For components, from the user side we'll support syntax like this:

@Component({
  ...,
  overrides: OriginalComponent,
})
class ComponentVariant implements OriginalComponent { ... }

Worth noting: ComponentVariant must be assignment compatible to OriginalComponent (e.g. implement its interface), as it will be injected in place of OriginalComponent across the application. Also, ComponentVariant must have the same content view projection as OriginalComponent, so it can be a drop in from the Angular 2 component side of things.

Routes

For routes, the basic idea is to lazily load routes that contain variants:

export const routes: Routes = [
  ...,
  {path: '', loadChildren: 'some-id'},
];

The module loader then has a chance to inspect 'some-id' and load the appropriate module (or even have the server side return the appropriate module). There will likely be a nicer API wrapping this, but it might be specific to the module loader used.

wardbell commented 8 years ago

Interesting.

@mhevery has been a vigorous opponent of component inheritance. I imagine he'll weigh in on the Components suggestion.

The generalization of loadChildren: 'some-id' is a plugin router loader as I recall AND the ability to specify a loader function/class. How do those mechanisms intersect the Routes proposal here?

chuckjaz commented 8 years ago

subtype does not imply subclass.

It might be better to use the term assignment compatible as it is slightly more correct and avoids the confusion between subtype and subclass.

mprobst commented 8 years ago

@chuckjaz done.

@wardbell I'm not sure I follow re Routes proposal. This is not proposing any change to routes, it just proposes for users to intercept an arbitrary load call and do the right thing there, which is what the API already supports.

wardbell commented 8 years ago

@mprobst re: routes ... gotcha. I wasn't sure if we were proposing something new or not.

@chuckjaz the use of the extends keyword threw me off.

chuckjaz commented 8 years ago

We should be clear that you can use extends but are not required to.

mprobst commented 8 years ago

@chuckjaz I updated the text above not to use extends, and explicitly say assignment compatible.

shlomiassaf commented 8 years ago

@mprobst when you say

ComponentVariant must have the same content view projection as OriginalComponent

You mean they must have a matching template? or the same meta api (@Input, @Output, etc...)?

mprobst commented 8 years ago

@shlomiassaf They need the same meta API (@Input, @Output, but also <ng-content>). It can (and should, that's the point!) have a different template, and also include other components than the original component.

vishalbiswas commented 4 years ago

Has there been any progress on this? Do newer angular versions have some workarounds to make this work?

angular-robot[bot] commented 3 years ago

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

angular-robot[bot] commented 3 years ago

Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

You can find more details about the feature request process in our documentation.

angular-automatic-lock-bot[bot] commented 3 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.