Exposing Angular Components as Custom Elements From a Custom Angular Library
Since Angular 6 "Angular Elements" and "Angular Library" creation are possible via the CLI. This post covers how to create a library and share components from that library as "Angular/Custom Elements" so any third party application can consume them.
In the age of Microservices the frontend is catching up, the term Micro frontends has been getting more traction of late. Discarding the hype, the real value is in framework agnostic Web Components, allowing applications to compose components.
A lot of the examples I found didn't cover combining Elements and Libraries. Also, the elements examples only cover very simple components with no dependencies. So I've included a service dependency that makes a HTTP call in the custom element exposed.
Why? Well this approach is not suited to all applications but it does offer some nice features:
- Code organisation
- Shareable library that can be hosted in public or private npm repo
- Custom elements that any application may consume
- Host application that can compose library components
I wanted an Angular library that I could publish and get all the npm goodness. I also wanted to expose components from my library as elements.
The Set Up
Create the Application
ng new my-application
cd my-application
Create The Library
ng g library my-library
This library will contain the components that may be imported into the my-elements project and defined as Custom Elements. Of course, you could have multiple libraries and pick and choose which components need to be exposed as Custom Elements.
Create the Elements Project
ng g application my-elements
This is where we will import and define the components we want to expose as custom elements.
To add elements support run:
ng add @angular/elements
The above commands will update the angular.json file to use document-register-element to create our custom elements.
ng new my-elements
Notes
I've modified the tsconfig.json to target es2015 which won't work for IE, but you can workaround this by updating the polyfills.ts file in the main application to include webcomponents.js.
npm install @webcomponents
src/polyfills.ts
`/*******************************************************
- WebComponent JS required for native view encapsulation.
*/
import '@webcomponents/webcomponentsjs/webcomponents-sd-ce.js';`
Wrap Up
As your app grows you may find this approach saves architectural headaches down the line. This approach does add some overhead so if your app is likely to stay small(ish) this is not the way to go. I always advocate keeping it simple and reviewing every couple of weeks.
Serve and Rejoice!