rasor / react-stencil-poc

PoC for testing using custom stencil webcomponents in a ionic create-react-app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Setting up test projects

Using guides:

npm init stencil
# Choose component - name: my-stencil-components

npm init stencil
# Choose app - name: my-stencil-app

npm init stencil
# Choose ionic-pwa - name: my-stencil-pwa

# npm install -g ionic
npx ionic start
# choose react - template: blank - name: my-ionic-react-app

npx ionic start
# choose react - template: tabs - name: my-ionic-react-tabs

npm install -g create-react-library
create-react-library --help
# Usage: create-react-library [options] [package-name]
# Options:
#   -V, --version                        output the version number
#   -d, --desc <string>                  package description
#   -a, --author <string>                author's github handle (default: "rasor")
#   -l, --license <string>               package license (default: "MIT")
#   -r, --repo <string>                  package repo path
#   -g, --no-git                         generate without git init
#   -m, --manager <npm|yarn>             package manager to use (default: "npm")
#   -t, --template <default|typescript>  package template to use (default: "default")
#   -p, --template-path <string>         custom package template path
#   -s, --skip-prompts                   skip all prompts (must provide package-name via cli)
#   -h, --help                           output usage information
create-react-library --template typescript my-react-components
# 

Serve the default demo webcomponent

# TERMINAL 2
cd my-stencil-components
npm install
npm start
# xdgopen http://localhost:3333/

The webcomponent will be served in to main files:

It is displayed in http://localhost:3333/index.html and loaded with:

  <script type="module" src="/build/my-stencil-components.esm.js"></script>
  <script nomodule src="/build/my-stencil-components.js"></script>

And instanciated with:

  <my-component first="Stencil" last="'Don't call me a framework' JS"></my-component>

Serve the default demo stencil-app with the webcomponent

# TERMINAL 3
cd my-stencil-app
npm install
npm start
# xdgopen http://localhost:3334/

The app is displayed in http://localhost:3334/index.html. In my-stencil-app/src/index.html you can paste the webcomponent loading lines from my-stencil-components above app.esm.js:

  <script type="module" src="http://localhost:3333/build/my-stencil-components.esm.js"></script>
  <script nomodule src="http://localhost:3333/build/my-stencil-components.js"></script>

And instanciate one in my-stencil-app/src/components/app-home/app-home.tsx with:

  <my-component first="External Stencil" last="'Don't call me a framework' JS"></my-component>

Now you can see the webcomponent on the home page if both projects are started.

Serve the default demo stencil-pwa with the webcomponent

# TERMINAL 4
cd my-stencil-pwa
npm install
npm start
# xdgopen http://localhost:3335/

As with the my-stencil-app:

  • Paste <script> into src/index.html
  • Paste <my-component> into src/pages/Home.tsx

Now you can see the webcomponent on the home page if both projects are started.

Serve the default demo ionic-react-app with the webcomponent

# TERMINAL 5
cd my-ionic-react-app
npm install
npm start
# xdgopen http://localhost:3000/

As with the my-stencil-app:

  • Paste <script> into public/index.html
  • Paste <my-component> into src/components/app-home/app-home.tsx

Create a new file src/declaration.d.ts with the content

export declare global {
    // From /my-stencil-app/node_modules/@stencil/core/dist/index.d.ts
    namespace JSX {
        interface IntrinsicElements extends d.JSX.IntrinsicElements, d.JSXBase.IntrinsicElements {
            [tagName: string]: any;
        }
    }
}

Now you can see the webcomponent on the home page if both projects are started.

npm publish demo webcomponents to github registry

Add a personal access token

Add to my-stencil-components/package.json.
If you have several projects (as in this case) you also need to add section repository - otherwise it will use the name on the project to try to locate the package folder (which it fetches from the repo name...)

 // increase version
 "version": "0.0.2",
 // add 
 "publishConfig": {
    "registry":"https://npm.pkg.github.com/@rasor"
  },
  "repository" : {
    "type" : "git",
    "url": "ssh://git@github.com:rasor/react-stencil-poc.git",
    "directory": "react-stencil-poc"
  },

Login to npm registry.
You can do that with a ~/.npmrc file or
in CLI as here:

# TERMINAL 2
npm login --registry=https://npm.pkg.github.com/
# Username: (rasor in my case)
# Password: (Paste personal access token)
# Email: (your email)

cd ../my-stencil-components
npm publish
# + my-stencil-components@0.0.2

You should now see the package uploaded to https://github.com/rasor/react-stencil-poc/packages/

Extend webcomponents with element having typed attributes

The demo webcomponent <my-component> has attributes, that are assigned strings.

It would be nice to feed it a typed object.
From Tab3.tsx code in 'Announcing Ionic React' put the export interface Person into my-stencil-components/src/models/person.ts

In my-stencil-components/src/components/my-component/my-component.tsx add the Person, too

import { Person } from '../../models/person';

export class MyComponent {
  /**
   * A typed object
   */
  @Prop() person: Person;

  render() {
    return <div>
      <div>Hello, World! I'm {this.getText()}</div>
      {this.person &&
        <div >
          <div slot="start">
            <img src={this.person.photo} />
          </div>
          <div>
            <h2>{this.person.name}</h2>
            <p>{this.person.position}</p>
          </div>
        </div>
      }
    </div>;
  }
}

then increase version in package.json and re-publish

WARNING - it must be PROD build in order to include the dist/loader folder Integration with StencilJS problem - Cannot find module test-components/dist/loader

# Re-publish
cd ..\my-stencil-components
# must build for PROD to 
npm run build
npm login --registry=https://npm.pkg.github.com/
npm publish

Use the new package

Create file /my-stencil-app/.npmrc containing

registry=https://npm.pkg.github.com/@rasor

If you need more orgs see here.
If you use MyGet packages see here.

Install the component:

cd ../my-stencil-app
npm install --save my-stencil-components@0.0.4

In /my-stencil-app/src/index.html remove the <script> loading of the my-stencil-components.
... also meaning you don't need the webserver hosting my-stencil-components on port 3333 running - you can Ctrl+c it.

So now you need to import it from the downloaded package instead in my-stencil-app/src/index.ts:

// https://stenciljs.com/docs/react
// Load your web components
import { applyPolyfills, defineCustomElements } from 'my-stencil-components/loader'

applyPolyfills().then(() => {
     defineCustomElements(window);
   });

Links

The End

About

PoC for testing using custom stencil webcomponents in a ionic create-react-app


Languages

Language:TypeScript 60.5%Language:CSS 28.8%Language:HTML 8.5%Language:JavaScript 2.2%