angular / angular

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

Make Angular componets exportable to Web Components by default #38730

Closed tirithen closed 3 years ago

tirithen commented 4 years ago

🚀 feature request

Description

The company I work for wants to reuse Angular custom UI components that is built by another team in a larger project I'm working in. The project I'm a part of uses standard web components with some basic helpers through lit-html/lit-element.

It seems that it's hard with Angular to use only a single component outside the Angular "engine". Does the Angular project have a roadmap on when the Angular components will be usable outside an all-in Angular app? It would probably help preventing large code re-writes as when AngularJS became Angular as web components using different helpers could then coexist, during migration as well as for the lifespan of a project. Much like the packages in the Node.js world where basically any package could be used separately from another.

Do you have a roadmap for this, when would it be available?

Describe the solution you'd like

The possibility to export any pre-existing Angular component as a standard web component (customElements.define) without internal custom modification.

Describe alternatives you've considered

Angular elements, it seems like great start for this approach, but as I understood when talking to the team developing the custom Angular components they would have to re-write the components to make it possible to export them.

I understand that currently might be the case for a project that started without a thought on exporting their components, but what if the Angular API/syntax was designed as such that the default and only way to create the components was one where they could always be exported.

Surely that would also help reduce the need for complete re-writes when the next major Angular release comes along as was the case from AngularJS to Angular.

gkalpak commented 4 years ago

I am little confused. Could you elaborate on what rewrites/internal custom modifications you refer to?

tirithen commented 4 years ago

Basically I'm looking for a feature/way to export components built with Angular like say buttons/lists/forms ect as stand alone standard Web Components so that they can be used in other projects that does not use Angular without initializing the entire Angular application. Of course assuming I'm still using that components API externally.

A way to pull in and re-use the Angular components (as is without modification through e.g. npm) in plain JavaScript or in applications with other libraries/frameworks.

If each Angular component be default was exported as a Web Component they could be re-used in non-Angular projects.

cristianhosu commented 4 years ago

Angular elements work just fine for your use case. The only changes that need to be made is to actually use the customElements.define for each component that you want to export. This is assuming that the components are exported from an Angular app instead of an Angular Library project. In that case, you can resort to a hack-ish method and built an Angular app that exposes one component for each angular library component that you have. Basically you would wrap those Library Components and export them yourself. (https://medium.com/swlh/angular-elements-create-a-component-library-for-angular-and-the-web-8f7986a82999) The downside is that you would basically need an instance of the Angular runtime in every app where you plan to use those components.

Maybe adding some sort of support for Angular Elements in an Angular Library project is a feature worth considering.

tirithen commented 4 years ago

Thanks for a good answer to my question that was caused as I got a task re-using Angular (version 10) components from a huge project (18mb JS download in the browser in dev mode! wow that really is huge, never seen anything that size before!) that I cannot change and encountered real challenges exporting it's components. The components would then be used in another larger project that is based around standard Web Components.

The problems I'm having might also be related to how that specific project was built with dependency injections and so on. When I tried exporting components from a clean Angular project everything worked fine (really nice to see that @angular/elements exists, hoping to see more like that), but with a project created without exporting in mind it might maybe simply be harder depending on how all the components having various dependencies and so on.

Thanks for the hint about creating an application and having that as an extra runtime on the side, as long as it's one extra runtime and not one per instance or similar it will probably be fine. I think that running it on the side was what I tried, but I'll dig into workarounds for that a bit more.

Still I would suggest using standard web components be default once an Angular project is transpiled down to plain JavaScript would probably make this so much easier, as Angular creates custom tag names anyway it looks on the surface that this would not be to far away at all. It would make Angular components so much more accessible for other projects as well as prevent the need for large re-writes in case breaking changes to API where to be needed.

All above said, I'm not an Angular expert, I only know the basics, as I mainly work in other setups and preferably as close to the Browser API as possible.

I'll leave the issue open, but feel free to close in case my description is not clear/concise enough. I can also try to provide (not all, but some) details about the setup of the project in case it would be useful for improving the compatibility between the Web Components and @angular/elements .

mlc-mlapis commented 4 years ago

@tirithen You should consider that there is some amount of Angular runtime environment (it's possible to have it as only one bundle) that has to be also loaded, so it has the logical consequences to have such a bundle only one and sharable (loaded only once) for a set of some components (used as web components from other sides). Another factor is the ability to lazy-load of those components on demand and not all of them together and eagerly (even if the sharable runtime bundle is loaded once and eagerly).

tirithen commented 4 years ago

@mlc-mlapis Thanks, it's fine to have some extra runtimes as long as they don't slow down to much (I'm expecting some slowdown for sure). Hopefully the Angular project would be run as it's own closed environment (possibly including some extra boilerplate to export the components) and . I think I need to dig into the specific project a bit more before saying to much about the specific setup as it was a week since I last tried.

The thing I remember was that it would not compile when I tried to add new entryComponents (I'm still new to @angular/elements) due to how the projects build system was setup. It worked perfectly in a new clean project to do that and then in app module constructor use createCustomElement with customElements.define, but it seem to not be as straight forward to do this in a project that did not have exporting in mind when created.

This was why I suggested to change Angular in a way so that there is always (within reason and if following Angular guidelines) possible to export components regardless dependencies on other Angular services/imports/events or other bindings.

There is some more experiments I'll try, like for example creating one additional component to each component that I want to export, to see if that allows the export, but as it would possibly mess up the related CSS and add even more layers to an already complex setup, so that might be a less attractive option. If it was possible to just export the components as is, same as in a clean project with @angular/elements that would keep complexity down but as I understood from the developers of this specific Angular project that would severely limit the Angular features that they depend on. Ah, this is no good without concrete case examples I guess, I'll get back with one the next time I'm working on that project.

cristianhosu commented 4 years ago

@tirithen - It really is on a case by case basis here, and from my personal experience with using Angular's web components integration, things run pretty smooth-ish. There are some things to consider, for example, routing, rxjs and other's like that, but by using the middleware angular project that i suggested might come in handy when exporting one component to also be able to bundle all the required dependency, especially if there is some sort of lazy loading involved in the original project. When using web components with Angular, there is one more thing that really boggles the mind and that is the webpack export module which causes a lot of issues when working with multiple "angular projects" in the same context. have in mind that you might need ngx-build-plus to overwrite the output.jsonpFunction to a proper unique name. But without knowing more info about your particular case, it's hard to help out, so i'm just putting things out there that I have come across while doing roughly the same thing :)

davidyew commented 4 years ago

@tirithen , I have similar related problems as yours.

FYI, I have explored single-spa.js, and angular-extensions-elements.

I am pleased to have a working POC with the latest reactJS and Angular 10 components within an Angular app shell with Angular Extension Elements. The different web components are able to interface with each other and for the Angular component, only a minor configuration change and code change at app.module.ts.

So the app shell will need to house the common libraries used by reactJS and Angular components, so that the web component can be lean to be lazy loaded.

This helps me in my micro-frontends application design. Hope it works for you.

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.

gkalpak commented 3 years ago

Thx for the insights, everyone. It is not clear what the specific issues are that would prevent an Angular Component from being exported as a Custom Element and whether they are generic or related to the specific project setup. As such, this issue is not really actionable for us.

I believe the main underlying problem is being able to easily consume Angular Elements in non-Angular apps, for which we don't have a great solution yet. This is tracked in other GitHub issues though (such as #25421 and #33942), so let's close this one and track the problem there.

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.