Browsers are becoming more and more powerful. Browsers are now able to do what was previously only possible with native apps, and web apps that take advantage of the modern browser capabilities go under the name Progressive Web Apps. This includes a browser specification that enables browsers to have functionality such as offline availability, hardware support, and Bluetooth. Also, new browser specifications are enabling what was previously only available for SPA frameworks to the browser natively using web components that are encapsulating functionality and styling with techniques such as shadow dom and creating web components using custom-elements.
What is custom-elements? Custom-elements is part of the web component standard and is custom HTML tags that encapsulate functionality and styling. It is the browser-native implementation of what Angular is doing with javascript rendered components, just running natively and framework agnostic in the browser!
Angular has created a library for converting components into custom elements. This enables us to write components using the Angular framework and run the component in non-Angular applications. That way you can mix different front-end frameworks, as it all gets compiled to custom-elements.
Let’s see how easy it is to convert an Angular component to a custom element.
Converting an Angular component to a custom-element using @angular/elements
We are gonna create a simple demo of an Angular app by creating a component and using it to create a custom-element like in my Github demo.
The first step is to create a new Angular CLI project:
ng new angular-elements-demo
We need to install Angular elements:
npm i --save @angular/elements
And install some polyfills for web component browser compatibility:
npm i --save @webcomponents/custom-elements
And add the following lines to polyfills.ts
:
import '@webcomponents/custom-elements/src/native-shim';
import '@webcomponents/custom-elements/src/custom-elements';
Hereafter you create a new component, that will later become a custom-element.
ng g c hello
Make sure to set ViewEncapsulation
to native
since we are to be working with custom-elements.
In the HelloComponent
‘s decorator:
encapsulation: ViewEncapsulation.Native
For making Angular elements outside of Angular you need to change a couple of things in the AppModule
:
- The
HelloComponent
is the component we want to create a custom element from. To do this we need to add it todeclarations
andentryComponents
because the component is being created programatically (not created in a template). - We want to use our custom element as our bootstrapped component, so to do this we need to setup the
ngDoBootstrap
lifecycle hook. Also we need to ensure thatAppComponent
is removed from thedeclarations
andbootstrap
properties in the decorator ofAppModule
. - In the
ngDoBootstrap
create a new custom-element usingcreateCustomElement
. Make sure to provide the injector. - Define the custom element using
define
. Here you specify the custom-elements HTML tag and the custom element to create.
Now when the app runs it will run a custom-element
. You can remove everything from index.html and only specify the custom element as:
<hello></hello>
And you should see the HelloComponent
being rendered!
The benefit of this is that this custom-element can be rendered in any framework now, as long as the compiled javascript bundles are provided. It is possible to run this app inside a React app and also there might be some performance benefits because of how browsers optimize for running web components vs running a javascript framework.
Publication of custom-elements
Unfortunately the way to use a custom elements created with Angular Elements is to build the bundles with ng build --prod --output-hashing=none
and concat all the js files into one. Currently this creates a pretty big bundle size, especially for an App that just displays some text. For this reason, it might not be reasonable to use Angular Elements in production yet.
Angular v7 and the Ivy renderer should make the published bundle of custom-elements created with Angular Elements even smaller, making this more useful in production. Also as the custom-element standard gets implemented in more browsers polyfills might not be needed anymore.
Conclusion
We discussed the benefits of creating framework agnostic apps using Angular Elements and saw how easy it is to convert an Angular component to a custom-element. Still, the technology has some drawbacks in a big bundle size and the need for polyfills to ensure browser support for custom-elements.
Do you want to become an Angular architect? Check out Angular Architect Accelerator.