EXAMPLE: Integration StencilJS Web Component in Ionic App

Hi all!

In case it’s helpful, I created an example of integrating a web component built with StencilJS into an Ionic APP.

Integration: https://github.com/abritopach/ionic-test-stencil-web-component

Stencil Web Component: https://github.com/abritopach/stencil-counter

Greetings,

3 Likes

It is great but could you also share how you set it up ?

Thanks

Hi @gillestasse!

To create new components in StencilJS:

git clone https://github.com/ionic-team/stencil-app-starter app-name
cd app-name
git remote rm origin
npm install
npm start

Stencil components are created by adding a new file with a .tsx extension.

Modify existing project code or create your new component. Follow the official documentation if you have any questions.

Once you have tested build for production with

npm run build

This will generate a minified distribution of your stencil component in build folder.

Integrate Web Component in Ionic

Steps

  1. In your Ionic project copy web componet build folder in src/assets/lib (for example).
  2. In src/app/app.module.ts

import { CUSTOM_ELEMENTS_SCHEMA } from ‘@angular/core’;

Add schemas: [ CUSTOM_ELEMENTS_SCHEMA ]

Example

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { CounterWrapperComponent } from '../components/counter-wrapper/counter-wrapper';

@NgModule({
    declarations: [
        MyApp,
        HomePage,
        CounterWrapperComponent
    ],
    imports: [
        BrowserModule,
        IonicModule.forRoot(MyApp)
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        MyApp,
        HomePage
    ],
    providers: [
        StatusBar,
        SplashScreen,
        {provide: ErrorHandler, useClass: IonicErrorHandler}
    ],
    schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class AppModule {}
  1. Use your web component in page (for example home.ts)

<ion-header>
    <ion-navbar>
        <ion-title>
            Stencil WC Ionic
        </ion-title>
    </ion-navbar>
</ion-header>

<ion-content padding>
    <counter-wrapper>
        <my-counter start="10" min="0" max="100" step="5"></my-counter>
    </counter-wrapper>
</ion-content>
2 Likes

Perfect. Thank you ! I am gonna dive into it right now !

I just gonna let that here because, at least for me now, the way to import the component built with Stencil into Ionic was a bit different

First there is a description of what to do with angular on the official StencilJS website https://stenciljs.com/docs/framework-integration

What I did in case of Ionic (after having build and installed the component, named “my-component” in my case):

  1. Like describe above, the CUSTOM_ELEMENTS_SCHEMA need to be declared

  2. In app.modulte.ts an import should be added, like

    import 'my-component/dist/mycomponent';
    
  3. The component lib installed under node_modules not gonna be included in the vendor.js file. Therefor it need to be copied. To do so, I have overwritten copy.config.js from app-scripts and add a the copyMyComponent block like following

    copyMyComponent: {
         src: ['{{ROOT}}/node_modules/my-component/dist/mycomponent**/*'],
         dest: '{{BUILD}}'
    }
    

UPDATE

@AaronSterling describe nicely, in his component’s README, all the steps needed to include a component in an Ionic project https://forum.ionicframework.com/t/stencil-importing-stencil-components-into-ionic-angular/

2 Likes

So you don’t need to add a <script> to index.html?

Exactly I don’t have too, I guess the import is the tricks :smiley:

Furthermore I could add that I tested till the end respectively ionic build iOS --prod and ran the app on my (real) phone. Maybe I was just lucky :wink:

I think I’ve come up with a small improvement. I added two build instructions to copy.config.js, instead of pushing everything into copySwToolbox. Writeup here.

Cool @AaronSterling thx for the input, you are right, adding a block and not modifying an existing one is cleaner :thumbsup:

I have modified my above post, own component and project :slight_smile:

I gonna link my issue here because I think it might be related to the way I import the component into my project. Long story short, it works locally, on iPhone, on Android 6 but doesn’t on my Android 8.1 device

https://forum.ionicframework.com/t/stencil-error-on-nexus-5x-android-8-1-only/?source_topic_id=106083

Do you think for a large mobile app would be necessary using a framework or we can just go with ionic components and write our own page components with stencil?

The integration has been updated in the latest StencilJS docs. Refer to Framework Integration, angular for integrating it in Ionic Angular app. LInk https://stenciljs.com/docs/angular.

Instead of importing the component directly, import a loader and call defineCustomElements(window) from main.ts

// File: main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

import { defineCustomElements } from 'test-components/dist/loader';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));
defineCustomElements(window);

1 Like