Using Stencil Web Components in Angular and the Angular CLI
In this post, we are going to learn how to use a Stencil Web Component in a Angular CLI application. Stencil is a compiler that allows us to author reusable Web Components. To learn more check out how to get started with your first Stencil Component.
In our previous post we learned how to create our first Stencil Component, a simple drop down. Now we will take that same component and publish it to NPM to be able to use it in an Angular CLI project.
Publishing our Stencil Component
There are several ways to publish and distribute a Stencil Component. We could via a git repo, a script CDN or NPM. For this demo, we will use NPM. The code for our Stencil dropdown can be found here.
To publish our Stencil Component, we need to do the following steps. First, we need to check our stencil.config.js
. In here we set generateDistribution: true
. This setting will set the compiler to generate the files needed for other projects to consume our Stencil components.
Once configured we will run the npm script npm run build
this runs the build process to generate our components. Once built we can publish our components to NPM. To publish our components, we run npm publish
this will publish the generated components in the dist folder to our project name defined in our package.json
file. The demo project I have already published to NPM here. Next, we will look at an Angular CLI project to consume our components.
Configuring the Angular CLI
Now we have our Stencil Components published to NPM we can add them to our Angular project. In this demo, we are going use the Angular CLI. First, we need to install the demo package to our CLI project. To do this, we will run npm install stencil-demos
.
Once installed we have to make some changes to the .angular-cli.json
file. Unfortunately, at the time fo writing Stencil does not yet support ES2015 module importing of individual components which means we must configure the CLI to copy all the static JavaScript files to use at runtime. Hopefully, in new versions, this will be more configurable to allow importing direct ES2015 modules as well.
In the .angular-cli.json
we need to add a configuration object to the assets settings.
"assets": [
"assets",
"favicon.ico",
{ "glob": "**/*", "input": "../node_modules/stencil-demos/dist", "output": "./assets/stencil-demos" }
],
Our configuration object defines how the CLI should copy the JS files from our NPM package over to our assets directory to be available at runtime. Once set we need to add the following to our index.html
file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AngularStencilWebComponentDemo</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<script src="assets/stencil-demos/index.js"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
We add a script tag to link to the core code that will use the Stencil component loader. The component loader allows all the stencil components to be lazy loaded only when rendered on the screen giving some excellent default performance benefits.
Now that we have everything wired up we need to let the Angular compiler know that we are using Web Components. To do this in our app.module.ts
file we need to add the following.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent],
schemas: [
CUSTOM_ELEMENTS_SCHEMA // Tells Angular we will have custom tags in our templates
]
})
export class AppModule {}
The CUSTOM_ELEMENTS_SCHEMA
tells the Angular compiler that any unknown tags should be ignored as our custom Web Components will define them. Once defined we can now add our Stencil component to our app.component.html
template.
<h1>Stencil Web Components and Angular</h1>
<my-dropdown title="Toggle">
Hello from a Web Component build with Stencil in a Angular App!
</my-dropdown>
If we start up our Angular app using ng serve
we will see the following:
Stencil is a great way to write generic web components that can be reused anywhere including Angular. Check out the full demo below!