Angular + Web Components

My article on Angular Elements - building Web Components with Angular. At my job, we iteratively turn an existing ASP.NET <VC app into a single page app by converting each page to a Web Component, later to be merged into an SPA. This article is about the challenges our team faced when implementing this solution.

Hi Armen,

Did you see whether Ivy decreases the bundle size yet?

I’m actually still stuck on Angular 7. But after my task at hand (hopefully next week) I will get to upgrade to 8 and then 9 and try out Ivy. The bundle sizes right now… Well, they are not bad, but certainly suboptimal. For example, the web component that I make now is a huge page with forms and lots of interconnected components. It actually uses NGRX under the hood to handle permissions/configurations that are multiple, lots of ngif-s and so on. Bundle size after a production build stands firmly at 1mb. This is the best I could get after several days of optimizing. It’s not bad, but definitely would benefit from becoming smaller. So I hope Ivy fixes that

1 Like

I will run some experiments to create the smallest Elements bundle possible.

1 Like

That would be great, keep us posted on the results and how you managed!

1 Like

Try building web components with preact and preact-custom-elements, that would be quite interesting.

I’ve finished my first experiment.

33.5 KB gzipped (107 KB uncompressed).

Hello World Angular element without NgZone.

The browser platform, 1 element, 1 Angular module, 1 component.

Next up, renderComponent based minimal Angular element bundle.

Second experiment.

8.82 KB gzipped (24.5 KB uncompressed).

Hello World Angular element using renderComponent.

No NgZone, no platform, no Angular module, 1 element, 1 component.

Third experiment.

13.5 KB gzipped (40 KB uncompressed).

Zippy Angular element using renderComponent and a feature render module.

No NgZone, no platform, 1 Angular module, 1 element, 1 component, 1 directive, 1 pipe.

Note: Still need to implement Shadow DOM and content projection.

So I upgraded to ng9 today. I didn’t yet put out ngzone and the other stuff yet, so I actually have an increase in bundle size, almost 30%. But obviously that will change, so tomorrow I’m going to get rid of ngzone. @LayZee, thanks for your examples, I will definitely take a look at them

So here I try to remove ngmodules and zone.js, and hit a wall now:

forms.js:1067 Uncaught Error: Cannot inject Renderer2 when the application uses Renderer3!
at getOrCreateRenderer2 (forms.js:1067)
at injectRenderer2 (forms.js:1077)
at push…/…/node_modules/@angular/core/ivy_ngcc/fesm5/core.js.Renderer2.NG_ELEMENT_ID (primeng-button.js:61)
at getOrCreateInjectable (core.js:26019)
at Module.ɵɵdirectiveInject (forms.js:4714)
at NodeInjectorFactory.NgClass_Factory [as factory] (core.js:17044)
at getNodeInjectable (core.js:26211)
at instantiateAllDirectives (core.js:30663)
at createDirectivesInstances (core.js:30054)
at Module.ɵɵelementStart (forms.js:4860)

As you can see, this gives me an error related to a primeng component, but I am using primeng@9.0.0-rc4, which is (as they claim) Ivy compatible. And honestly I don;t understand how this injectRenderer2 got there at all. I don’t have that many dependencies (only ngrx and primeng), and I already took care of almost all of them, and this error just ruins it all.

It appears that the problems lies in the implementation of the NgClass directice (what a surprise!). Here is the line of code that causes trouble:
private _renderer: Renderer2
Well, NgClass uses Renderer2 (obviously), but somehow Ivy does not permit to use Renderer2 because it already uses Renderer3! Any ideas on How to bypass this problems?

There is no Renderer3 in the public API, only a new implementation. The interface is the same. Why do you think NgClass is broken? A lot changed with styles in v9. PrimeNG might have relied on old, broken behavior.

Fourth experiment.

21.1 KB gzipped (65.9 KB uncompressed).

Hello World Angular element using hacked createCustomElement without platform and NgZone.

1 element, 1 component.