DEV Community

Sudhakar George
Sudhakar George

Posted on

Integrating Stencil Web Components in Angular Project

Image description
Web Components is a suite of different technologies allowing you to create reusable custom user interface components.

In this article, we’ll explore how to create custom Web Components using Stencil.js and integrate them into Angular applications.

What is Stencil.js?
Stencil is an open-source compiler that generates standards-compliant web components. It builds highly performant, reusable components that can be used with any JavaScript framework or library. Created by the Ionic team, Stencil combines the best features of popular frameworks like Angular, React, and Vue, providing a simple and efficient way to build custom elements.

Advantages of Stencil Components

  • Stencil provides some syntactic sugar with TSX (JSX with TypeScript), which makes it much easier to build web components with cleaner, reduced code.
  • Stencil’s compiler performs static analysis on each component to customize the build. This results in a highly optimized runtime with minimal size
  • Stencil will automatically polyfill modern browser features and APIs for browsers that don’t support them.
  • Stencil uses APIs built directly within the browser instead of writing custom client-side JavaScript

# Creating a Stencil Project :

Step 1: Install Stencil CLI

First, we need to set up the stencil CLI globally. Go to your terminal and run the below command:

npm install -g @stencil/core
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a new Stencil Project

To create a new Stencil Project, Go to the desired folder location and run the below command:

npm init stencil
Enter fullscreen mode Exit fullscreen mode

When you run the above command, it will be prompted to select the project type, Please select the component and provide a project name.

? Select a starter project.

Starters marked as [community] are developed by the Stencil Community,
rather than Ionic. For more information on the Stencil Community, please see
https://github.com/stencil-community » - Use arrow-keys. Return to submit.
>   component                Collection of web components that can be used anywhere
    app [community]          Minimal starter for building a Stencil app or website
    ionic-pwa [community]    Ionic PWA starter with tabs layout and routes
Enter fullscreen mode Exit fullscreen mode

Step 3: Install Dependencies

Navigate to your stencil project location (cd your-stencil-project) and install the dependencies as shown below

npm install
Enter fullscreen mode Exit fullscreen mode

Once the dependencies are installed, run the below command to make sure the Stencil project is running correctly.

 npm start
Enter fullscreen mode Exit fullscreen mode

Go to this location and check your output http://localhost:33333

Image description

Creating a Web Components :

Now let’s create a custom Web Component. For this example, we’ll create a simple Button component.

Step 1: Generating a new Component

Go to your project location in the terminal and execute the below command to generate a new component:

npm run generate
Enter fullscreen mode Exit fullscreen mode

You’ll be prompted to enter the name of your component. For this article, we name the button component as “new-button”. Enter the component name and press Enter.

> my-stencil-project@0.0.1 generate
> stencil generate

[38:18.7]  @stencil/core
[38:19.1]  v4.22.1
√ Component tag name (dash-case): ... new-button
√ Which additional files do you want to generate? » Stylesheet (.css), Spec Test  (.spec.tsx), E2E Test (.e2e.ts)

$ stencil generate new-button

The following files have been generated:
  - src\components\new-button\new-button.tsx
  - src\components\new-button\new-button.css
  - src\components\new-button\test\new-button.spec.tsx
  - src\components\new-button\test\new-button.e2e.ts
Enter fullscreen mode Exit fullscreen mode

New components will be added to your project.

Image description

Step 2: Define the Component

Go to your generated component file location(src/components/new-button/new-button.tsx) and define your component as shown below:

import { Component, h,  Prop } from '@stencil/core';

@Component({
  tag: 'new-button',
  styleUrl: 'new-button.css',
  shadow: true,
})
export class NewButton {
  @Prop() text: string; 
   render() {
    return (
      <button>
         {this.text}
      </button>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Note:

@Prop decorator lets you create parameters with access to component attributes.

Step 3: Add Styles

Add some basic styles to your component in the new-button.css file:

button {
  background-color: #0056b3;
  color: white;
  border: none;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
  border-radius: 4px;
}

button:hover {
  background-color:#1500ffde; 
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Build Your Component

Build your component by running:

npm run build
Enter fullscreen mode Exit fullscreen mode

Step 5: Test your Component

You can test your component by adding the component name to your index.html

<new-button text="My First Component"></new-button>
Enter fullscreen mode Exit fullscreen mode

Here text is the label name of your button component.

Your index.html file looks like this:

<html dir="ltr" lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
    <title>Stencil Component Starter</title>

    <script type="module" src="/build/my-stencil-project.esm.js"></script>
    <script nomodule src="/build/my-stencil-project.js"></script>
  </head>
  <body>
    <new-button text="My Component"></new-button>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now, run the below command and check the output in your browser (http://localhost:33333)

Image description

You can find the complete source code on GitHub

# Integrating Web Components into Angular Application
Now that our custom Web Component is built with Stencil.js, let’s integrate it into an Angular application. For this article, we are using Angular v18.

We can integrate the Stencil Web Components in different ways.

  • You can publish your web component as an NPM package and configure the dependency in your angular application.
  • You can manually copy and paste the web components into your angular application and configure it based on it.
  • You can directly integrate your stencil project into the angular application.

In this article, We are going to integrate your stencil project directly into the angular applicaion.

Create an Angular Application

Step 1: Set Up the Environment

Go to your terminal and install the Angular command-line interface (CLI). This will help you get up and running quickly with Angular:

npm install -g @angular/cli
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a New Angular Project

Once Angular CLI is installed, you can use it to create a new Angular project. Navigate to the directory where you want to create your project and run the following command:

ng new stencil-angularapp --standalone=false
Enter fullscreen mode Exit fullscreen mode

Step 3: Add the Stencil Project as depedency in Angular Application.

Now, We are going to add the stencil project in our Angular Application as a depedency.

Open your tsconfig.json from your angular project (stencil-angularapp) and include relative path of your Stencil Project under compilerOptions like below.

    "paths": {
         "@web-components/*": ["../my-stencil-project/*"]
     }
Enter fullscreen mode Exit fullscreen mode

Now create a folder called /libs/stencil-generated under the src folder this is where we will use the typescript path feature for keeping the stencil project as its dependency.

Image description

Now add an angular module from we will export our components inside this libs directory like below, We are creating a module calledweb-components.module.ts

Image description

We are done with the basic configuration, Now we need to configure the stencil project to copy the component into the angular application.

Adding the Angular Output Target
Go to your stencil project and Install the @stencil/angular-output-targetdependency to your Stencil component library package.

npm install @stencil/angular-output-target --save-dev
Enter fullscreen mode Exit fullscreen mode

In your project’s stencil.config.ts, add the angularOutputTarget configuration to the outputTargets array:

import { Config } from '@stencil/core';
// New Import
import { angularOutputTarget, ValueAccessorConfig  } from '@stencil/angular-output-target';

// props binding
const angularValueAccessorBindings: ValueAccessorConfig[] = [];

export const config: Config = {
  namespace: 'my-stencil-project',
  outputTargets: [
    {
      type: 'dist',
      esmLoaderPath: '../loader',
    },
    {
      type: 'dist-custom-elements',
      customElementsExportBehavior: 'auto-define-custom-elements',
      externalRuntime: false,
    },
    {
      type: 'docs-readme',
    },
    {
      type: 'www',
      serviceWorker: null, // disable service workers
    },
    // Newly Added Target
    angularOutputTarget({
      componentCorePackage: '', // Update the path
      directivesProxyFile: '', // Update the path
      valueAccessorConfigs: angularValueAccessorBindings,
    })
  ],
  testing: {
    browserHeadless: "new",
  },
};
Enter fullscreen mode Exit fullscreen mode

Now update angularOutputTarget with relative paths of your angular application.

angularOutputTarget({
      componentCorePackage: '@web-components/dist/components', 
      directivesProxyFile: './../stencil-angularapp/src/libs/stencil-generated/proxies.ts', 
      valueAccessorConfigs: angularValueAccessorBindings,
    })
Enter fullscreen mode Exit fullscreen mode

Now, build the stencil project with the following command.

npm run build
Enter fullscreen mode Exit fullscreen mode

Once the build is successful you would see the stencil-generated folder in your angular application is populated with some files.

Image description

If you notice because of our tsconflg.json settings, angular is able to know what @web-components/dist/components is referring to.

Consume the webcomponent in your Angular Application

Now we will see how to consume the webcomponents in our Application

Step 1: Registering Custom Elements

update the web-components.module.ts with our component definition in the declarations and exports block.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
// Added for Component Rendering
import {defineCustomElements} from '@web-components/loader';
import { NewButton } from './stencil-generated/proxies';

defineCustomElements(window);  // Added for rendering the component 
                                  in the browser


@NgModule({
  declarations: [NewButton],   // Declare the Webcomponent
  imports: [
    CommonModule
  ],
  exports: [NewButton]        // Ecport the Webcomponent         
})
export class WebComponentsModule { }
Enter fullscreen mode Exit fullscreen mode

Please note that *declareCustomElements *(not declareCustomElement) is used to initate the loader to load the custom web component , This line is very important without which the browser would render nothing.

Step2 : Update your Angular component

Now , we are going to consume the web components in our angular application module and HTML file.

Update your app.module.ts by importing the WebComponentsModuleas shown below:

import { WebComponentsModule } from '../libs/web-components.module'; // Add webcomponent

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    WebComponentsModule   // Import it here 
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

Now update app.component.html to consume your webcomponent.

  <div class="content">
    <h1>Integrating the Stencil WebComponent</h1>
    <hr>
     <new-button text="My First Component"></new-button>
  </div>

<router-outlet />
Enter fullscreen mode Exit fullscreen mode

run the angular app in dev mode

ng serve
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:4200 in your browser and check your webcomponent output.

Image description

You can find the complete Angular application source code on GitHub

Conclusion:

Stencil offers a powerful way to build reusable and performant components that can be easily integrated into Angular applications. If you’re looking for a solution that promotes framework independence, performance optimization, and better component reusability, Stencil is a great option to consider.

Hope this article is useful to you and your project, If you like this article, like & share it with your friends.

Follow Me for more articles.

Top comments (0)