angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.76k stars 11.97k forks source link

Micro-Frontend: Allow to have separate build/ releasable elements for lazy loaded modules #20056

Closed mohyeid closed 3 years ago

mohyeid commented 3 years ago

🚀 feature request

Relevant Package

@angular/cli

Description

With Micro-frontend being a hot topic those days, I have seen people taking the wrong approach with their angular projects. Thankfully, we have angular elements that allow us to create pure web-components, but unfortunately this have been misused to allow the micro frontend concept in an angular application. To allow smaller releasable packages, engineers started to create angular elements release them to a CDN site, and re-use them. This created a lot of fraction and challenges to integrate the different pieces. Not only that, but it's also awkward, as you are creating vanilla javascript code from angular code to re-use it back again from an angular code. Other solutions was iframing, which also does not scale. Or releasing smaller libs to npm and re-using them in the code, which is not desired in the case of end to end integration and mon-repo large applications.

Describe the solution you'd like

If you have a solution in mind, please describe it. Today, we are blessed by having the lazy loading approach which help us to generate separate chunks of the code and lazy load them as the user is visiting the relevant code. While this is great, there is no way to build those chunks separately and/or publish them to a standalone CDN/Server to be used later. I think to help teams avoid mistakes like listed above, it would be awesome if we can have angular CLI able to build these chunks separately, generate an artifact for it, which can be released individually. When this is accomplished, we can then have something like this: ``` const routes: Routes = [ { path: 'items', loadChildren: () => import(env.prod? 'https://CDN-XYA/chunk1.js' : './items/items.module' ).then(m => m.ItemsModule) } ]; ``` ### Describe alternatives you've considered Yes, above but it's not ideal. I think angular team need to get into the micro frontend business.
flash-me commented 3 years ago

We can for a long time already, see here

cheers flash ⚡

mohyeid commented 3 years ago

@flash-me that's interesting approach, but does it seem what I am trying to avoid? If you can have a pure lazy loaded angular code chunk, why do you need to create a web-component? Append the script manually and enable custom component schema which allow for bad elements to be added to the code without error handling? I wish we can accomplish something with the basic angular lazy loading!

flash-me commented 3 years ago

@flash-me that's interesting approach, but does it seem what I am trying to avoid? If you can have a pure lazy loaded angular code chunk, why do you need to create a web-component? Append the script manually and enable custom component schema which allow for bad elements to be added to the code without error handling? I wish we can accomplish something with the basic angular lazy loading!

Because this way you can use the resulting web-components everywhere. E.g. embed them in other frameworks etc. You also have the option to use them as regular NgModules and import them as usual. I'm not sure to what you are referring to by saying bad elements, but you won't find any CUSTOM_ELEMENTS_SCHEMA in that repository. Once you start to decouple the compilation of your apps into multiple parts, things get really interesting, believe me. E.g. Versioning of the different parts, their dependencies, etc.. just to name some.

If you want a basic approach, go with the lazy loading. It's not like in other frameworks where you can just fetch some files and append your application. In angular you also have the powerful DI and it's dependency tree, which needs to be considered. Dynamically loading some modules on runtime is always critical and error prone. Just curious: How would you load your independently compiled lazy loaded modules, which are not known at compile time to the app itself, if appending the script is that bad? Anyway, that repo is a POC. If the approach doesn't fit, don't use it. Also no one stops you from hiding / wrapping that complexity in some easy to use functions.

But this doesn't mean it's impossible. To dynamically "import" NgModules, you can have a look on the answer here (also note the issues that guy had there) You can even go a step further and completely lazy load angular libraries including their childroutes. Example code would here. Even though that repo is not really up2date, the approach is still the same. These days we could even solve that in a cleaner way by using ESM, but that's another topic. The interesting part for you would be this particular function

cheers flash ⚡

alan-agius4 commented 3 years ago

Thank you all for chiming in.

Lazy-loading modules and microfrontends are very different and each solves different problems. Lazy-loaded modules are dependent on other parts of the application, are not self contained and cannot be built without building the entire application. It also means that changes in a lazy-loaded module might cause either one or more of the common/shared modules to be invalidated. A microfrontend on the other hand is dependency free and can be built and released on its own, in other words it's isolated.

There are multiple ways to achieve microfrontends, it mostly depends on your use-case.

If you are using lazy-loading modules and want to release only what changed you can always check the diff and push to production the changed files. But again, lazy-loading and microfrontend are two different things and each solves different problems.

Thankfully, we have angular elements that allow us to create pure web-components, but unfortunately this have been misused to allow the micro frontend concept in an angular application. To allow smaller releasable packages, engineers started to create angular elements release them to a CDN site, and re-use them.

This is interesting, I don't know that approach used here, but, I wonder if Angular Elements have been created at a low level instead of a higher level. For example, let's say I have an item details page, in this case I would only create the top level component of the as an Elements and of it's child components are still standard Angular components.

Items microfrontend application

- item-details-page     // Angular Element Component
-- item-item-component  // Angular Component
--- add-to-chart-button // Angular Component

- item-list-page           // Angular Element Component
-- item-grid-item-component // Angular Component
--- item-item-component     // Angular Component
---- view-more-button       // Angular Component

A lazy-loaded module in an application is not self contained and hence it breaks the microfrontend concept. Therefore, I am closing this issue as at this point I don't see anything which is actionable by the tooling team.

Module federation is being tracked here https://github.com/angular/angular-cli/issues/17556

Feel free to reply.

flash-me commented 3 years ago

Unpopular opinion: If I have to recompile my shell in order to modify the micro Frontends I want to load, as it is required in kinda EVERY EXAMPLE out there, (e. g. here), then it is not micro Frontends we're talking about. Absolutely not. This is just lazy loading with some overhead. Kill me to it

This doesn't mean it's impossible to accomplish it with webpack. Even more, back in 2019, my first approaches were done with webpack. But this was not the development experience I want to have and I couldn't expect this from casual developer to handle it the right way. Which lead me to ng-packagr, which comes with everything out of the box. Even ESM works

Anyway, everyone can do everything and call it whatever one wants to call it. I really don't give a single f@ck anymore. Live and let live, right?

Have a nice day folks and don't let anyone f@ck you up. There are better things in life

I'm going to archive my repos, but won't touch them anymore.

cheers flash ⚡

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.