Angular-cli: Improve bundling experience for supporting multiple Angular Elements on a page

Created on 11 Mar 2020  Â·  16Comments  Â·  Source: angular/angular-cli

Hi,

I’d like to bring some attention back to this original post

https://github.com/angular/angular/issues/23732

Where it’s stating that in previous Angular version it was not possible to run multiple Angular Elements on a single page and we had to wait for Ivy release.

Now that we are at version 9 and Ivy is enabled by default, I was wondering if there are any progress regarding this issue.

Thanks

#

_UPDATE by @gkalpak (for visibility):_

List of related issues (with useful context, info, explanations):

  • angular/angular#23732 (in particular https://github.com/angular/angular/issues/23732#issuecomment-388670907)
  • angular/angular#30951
  • angular/angular#32726
  • angular/angular#35429
devkibuild-angular feature

Most helpful comment

In the linked issue and in many other related issues, the advised solution was to use ngx-build-plus and many threads were flagged as "won't fix".

I think this cannot be the solution, for four reasons:

  1. This is a base feature. The concept of modularity through elements is meaningless if you can't use multiple angular applications on the same page
  2. ngx-build-plus works by disabling some optimizations in the webpack build configuration. If the Angular team would embrace the feature I think that a smarter solution may be found
  3. Despite the effort put in ngx-build-plus, it still has some limits: the bundles are still too large since, after concatenations, you end up including in each file a lot of duplicated code. Furthermore, you need to perform some operations in your HTML document in order to externalize the polyfills and include all the (and only the) required dependencies. Do I need to import the @angular/router package? And the @angular/forms? I don't know! I need to check it component by component
  4. ngx-build-plus is an independent project ran by volunteers. There's no warranty that the development will be taken forward in the future and that's safe to be used in production. As now, the latest commit has been 1 month ago and the issues that I remember open months ago, are still open now

All 16 comments

+1

is there any news? thanks :)

In the linked issue and in many other related issues, the advised solution was to use ngx-build-plus and many threads were flagged as "won't fix".

I think this cannot be the solution, for four reasons:

  1. This is a base feature. The concept of modularity through elements is meaningless if you can't use multiple angular applications on the same page
  2. ngx-build-plus works by disabling some optimizations in the webpack build configuration. If the Angular team would embrace the feature I think that a smarter solution may be found
  3. Despite the effort put in ngx-build-plus, it still has some limits: the bundles are still too large since, after concatenations, you end up including in each file a lot of duplicated code. Furthermore, you need to perform some operations in your HTML document in order to externalize the polyfills and include all the (and only the) required dependencies. Do I need to import the @angular/router package? And the @angular/forms? I don't know! I need to check it component by component
  4. ngx-build-plus is an independent project ran by volunteers. There's no warranty that the development will be taken forward in the future and that's safe to be used in production. As now, the latest commit has been 1 month ago and the issues that I remember open months ago, are still open now

Take a look at this issue: https://github.com/angular/angular/issues/35429

I also posted a solution with pure angular toolchain which is working.

cheers
flash :zap:

thanks @flash-me. I'll read through all your replies and see how it goes. My intention was to ask if there was an official way to have multiple angular elements living togheter and not using some special/custom hacks. In my case I have implemented a simple script which renames the webpackJsonp variable during the building process.

Hi @dsozzi

the only "hack" is that you need to compile your angular element as a library (ng-packagr with that builder that comes with the angular-cli) instead of an application.

Instruction and implementation can be found in the repo I posted

cheers
flash :zap:

It's already longer possible to bootstrap multiple applications. The tricky part was, to run them all with one dependency injection container and one change detection umbrella. But wasn't that fixed with the new @Injectable({providedIn: 'platform'})? https://angular.io/api/core/Injectable

@sod I don't know how "platform" Provision is related to change detection and even the mentioned issue of this topic.

How should I profit from providing Injectables (e. g. A token or Service) at platform level when I want to bootstrap angular elements (which are wrapped angular Components)?

I don't see any relation between Change Detection, "platform" Provisioning & Components. Can you describe your intent?

cheers
flash :zap:

@sod If you want to reuse any existing Angular Platform, you get it and use it to bootstrap further applications. Like I already did it here.

But again, how is @Injectable related to this?

cheers
flash :zap:

Should I make a comment to bring more attention to this matter?
We are trying to export all our stateless components as angular elements and seems like Angular has not really been optimized for that? Can we be confident to use this feature in production?

What kind of optimization do you expect? What do you think is missing?

cheers
flash âš¡

What kind of optimization do you expect? What do you think is missing?

cheers
flash âš¡

Thanks for answering, flash

In our company, we have been developing multiple angular project in the recent years. 10s of them, each with some components that follow company UX UI guideline, resulting in duplicated work
Now with emerging Angular Elements, we would like to export all the components that we created in the 10 projects into reusable element for the Jquery/React world also.

I would like to know if
1/ Is It now possible to include angular elements generated from different projects?
2/ Each project would generate an Angular mini-app with its own change detector and app/module lifecycle independent of each other ( Am I right? ) - would that come with a performance penalty if heavily used?
3/ I believe that due to each element being so independent of each other, there will not likely a chance to optimize dependency. Ex:
Project 1 generate Element A that depend on module/package P1 P2 P3 P4
Project 2 generate Element B that depend on module/package P2 P3 P4 P5

Whoever use both Element A and B would suffer the bundle size of duplicated P2 P3 P4 right

// Did my question spiraled out of context considering the current issue?

@qkhanhpro The key point is to place all of such components into one placeholder application that allows you to generate only the same runtime bundle for them. So the ideal strategy is to use probably some monorepo, as Nx, for example, and if it has a sense (depends on the type of those components), use lazy loading. Their code will be loaded lazily and individually then, in a moment of their real use.

What kind of optimization do you expect? What do you think is missing?
cheers
flash âš¡

Thanks for answering, flash

In our company, we have been developing multiple angular project in the recent years. 10s of them, each with some components that follow company UX UI guideline, resulting in duplicated work
Now with emerging Angular Elements, we would like to export all the components that we created in the 10 projects into reusable element for the Jquery/React world also.

I would like to know if
1/ Is It now possible to include angular elements generated from different projects?
2/ Each project would generate an Angular mini-app with its own change detector and app/module lifecycle independent of each other ( Am I right? ) - would that come with a performance penalty if heavily used?
3/ I believe that due to each element being so independent of each other, there will not likely a chance to optimize dependency. Ex:
Project 1 generate Element A that depend on module/package P1 P2 P3 P4
Project 2 generate Element B that depend on module/package P2 P3 P4 P5

Whoever use both Element A and B would suffer the bundle size of duplicated P2 P3 P4 right

// Did my question spiraled out of context considering the current issue?

You may have a Look at this: https://github.com/flash-me/angular-micro-frontends
There I'm showing one solution on how to adapt an approach such you're looking for with angular only tools.

But in that repo I'm aiming for minimal usage of dependencies. So I even removed the cli and ng-packagr and directly use ngc + rollup. Depending on the skillset of the developers, this might be an issue regarding developer experience. If you prefer the angular cli toolchain, you can have a look on this previous commit: https://github.com/flash-me/angular-micro-frontends/tree/d2cdf8975ff29b7b9e7d9ff127a88104d09c006e

back to the questions:

  1. yes, it is. Even on runtime without reloading the page. (described in the readme)
  2. with my approach, the elements share the angular runtime and so the change detection, since they are bootstrapping using the same platform
  3. They are "optimized", as each project comes only with its own code. Thx to ng-packagr (+rollup), no external dependencies is included in the bundled. Given that, you need to provide these dependencies yourself once.

But to be honest. Such solution is not handy for the average angular developer, since a lot more knowledge is required.

Hope I could help you a little bit

cheers
flash âš¡

@qkhanhpro The key point is to place all of such components into one placeholder application that allows you to generate only the same runtime bundle for them. So the ideal strategy is to use probably some monorepo, as Nx, for example, and if it has a sense (depends on the type of those components), use lazy loading. Their code will be loaded lazily and individually then, in a moment of their real use.

This way, your projects are hard coupled to one application and everything needs to be bundled on every change. If this fits the requirements, I'd strongly recommend this way, since it's officially intended and supported.
If you need more flexibility on your projects, e. g. the final composition happens on runtime + you want to reuse them in a framework agnostic way (custom elements) you may have a look on my answer above, which allows you to develop completely independently without a big messy monorepo with hundreds of dependencies

cheers
flash âš¡

Moving this to the CLI repo since it relates to bundling. I believe this would fall under the feature request umbrella for CLI.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gotschmarcel picture gotschmarcel  Â·  3Comments

sysmat picture sysmat  Â·  3Comments

MateenKadwaikar picture MateenKadwaikar  Â·  3Comments

delasteve picture delasteve  Â·  3Comments

hareeshav picture hareeshav  Â·  3Comments