Using Ionic Framework into Next.js application (without using @ionic/react)

For now, we can not use @ionic/react into Next.js application. When we install and import it, we’ll get […]

広告ここから
広告ここまで

目次

    For now, we can not use @ionic/react into Next.js application. When we install and import it, we’ll get these error.

    % yarn build 
    yarn run v1.22.5
    $ yarn --cwd packages/web-app build
    $ next build
    info  - Creating an optimized production build  
    info  - Compiled successfully
    
    > Build error occurred
    ReferenceError: HTMLElement is not defined

    Why can not use it?

    Probably, the answer is a Web Component.
    Ionic components are Web Component (made by Stencil), and Web Component should register it manually.
    Stencil provides a defineCustomElements() method, and Ionic React calls it internally.

    But, in SSR, several DOM properties are missing in NodeJS env.
    So the function will be failed, and several properties will be “not defined”.

    Solution: using @ionic/core instead of @ionic/react

    In the Next.js examples, they show us the example application using Stencil.
    https://github.com/vercel/next.js/tree/canary/examples/with-stencil

    It means we can use a Web Component created by Stencil can use in the Next.js application.
    And Ionic components are made by Stencil.

    So, If we want to use “Ionic Component”, we can use it as a Web Component.

    Step by step

    Step1: Create Next.js application

    # Setup project
    $ npx create-next-app nextjs-ionic
    
    # Go to web root
    $ cd nextjs-ionic
    
    # Put tsconfig.json
    $ touch tsconfig.json
    
    # Install TypeScript packages
    $ yarn add -D typescript @types/react @types/node

    Step2: Install Ionic components

    Ionic components are divided into the two library. If you want to use IonIcon or ion-icon, we should install both.

    $ yarn add @ionic/core ionicons

    Step3: Define Custom Elements Types

    We use Ionic component as a JSX element, so we need to declare these element types.

    pages/_app.tsx

    import { JSX as LocalJSX} from '@ionic/core'
    import {JSX as IoniconsJSX} from 'ionicons'
    import { HTMLAttributes, ReactText } from 'react'
    
    type ToReact<T> = {
      [P in keyof T]?: T[P] & Omit<HTMLAttributes<Element>, 'className'> & {
        class?: string;
        key?: ReactText;
      }
    }
    
    declare global {
      export namespace JSX {
        interface IntrinsicElements extends ToReact<LocalJSX.IntrinsicElements & IoniconsJSX.IntrinsicElements> {}
      }
    }

    Step4: Define Custom Element and import CSS

    When we want to use Ionic component, we should define these component.

    pages/_app.tsx

    import React, { useEffect } from 'react'
    import { defineCustomElements as ionDefineCustomElements } from '@ionic/core/loader';
    /* Core CSS required for Ionic components to work properly */
    import '@ionic/core/css/core.css';
    
    /* Basic CSS for apps built with Ionic */
    import '@ionic/core/css/normalize.css';
    import '@ionic/core/css/structure.css';
    import '@ionic/core/css/typography.css';
    
    /* Optional CSS utils that can be commented out */
    import '@ionic/core/css/padding.css';
    import '@ionic/core/css/float-elements.css';
    import '@ionic/core/css/text-alignment.css';
    import '@ionic/core/css/text-transformation.css';
    import '@ionic/core/css/flex-utils.css';
    import '@ionic/core/css/display.css';
    
    function MyApp({ Component, pageProps }) {
      useEffect(() => {
        ionDefineCustomElements(window)
      })
      return <p>Hello</p>
    }
    
    export default MyApp
    

    Finally: Use Ionic component into the application

    Finally, we can use Ionic component!

    Once declare these type, we don’t have to declare again each component files.

    pages/home.tsx

    import Image from 'next/image'
    
    export default function Home() {
      return (
            <ion-refresher slot="fixed" closeDuration="10ms">
              <ion-refresher-content />
              <ion-card>
                <ion-card-header>
                  <ion-card-subtitle>Card Subtitle</ion-card-subtitle>
                  <ion-card-title>Card Title</ion-card-title>
                </ion-card-header>
    
                <ion-card-content>
                <Image
                  src="./images"
                  alt="Picture of the author"
                  width={500}
                  height={300}
                />
                  Keep close to Nature's heart... and break clear away, once in awhile,
                  and climb a mountain or spend a week in the woods. Wash your spirit clean.
                </ion-card-content>
              </ion-card>
            </ion-refresher>
      )
    }
    

    Example application

    広告ここから
    広告ここまで

    Random posts

    Home
    Search
    Bookmark