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
- GitHub: https://github.com/hideokamoto/example-nextjs-with-ionic
- Application: ionic-with-nextjs.netlify.app