Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next.jsでIonic Reactを利用したWebサイトを開発した話とIonic / CapacitorでStripe /ionic-stripe

Next.jsでIonic Reactを利用したWebサイトを開発した話とIonic / CapacitorでStripe /ionic-stripe

More Decks by Hidetaka Okamoto (Stripe)

Other Decks in Programming

Transcript

  1. Next.jsでIonic Reactを利用した Webサイトを開発した話 + α Ionic Meetup #19 Tokyo @hide__dev

    May 2022 1 #ionic_jp
  2. 岡本 秀高 ( @hidetaka_dev ) • Stripe Developer Advocate (ex-developer

    in Digitalcube) • JavaScript / TypeScript developer • AWS / Next.js / WordPress / etc… • WordCamp Kyoto 2017 / JP_Stripes Connect 2019 / AWS Samurai 2017 / etc… • 🐈(猫フラご容赦󰢛) 2 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp
  3. https://wp-kyoto.net/ 3 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp

  4. https://wp-kyoto.net/ 4 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp • 忘備録 & 実験場 •

    もともとWordPressテーマ開発の実験場だったのを、 2017年ごろからSPA or Jamstack構成に • Backend: ◦ WordPress / WP API: Content API ◦ AWS: Application infrastructure ◦ AWS CDK: Infrastructure management • Frontend: ◦ Next.js: Web application framework ◦ Ionic: UI library ◦ Algolia: search form AWS Amplify: Auth
  5. できそうな書き方: pages/_app.tsx 5 Next.jsでIonic Reactを利用したWebサイトを開発した話 import '../styles/globals.css' import type {

    AppProps } from 'next/app' import { IonApp } from '@ionic/react'; function MyApp({ Component, pageProps }: AppProps) { return( <IonApp> <Component {...pageProps} /> </IonApp> ) } export default MyApp #ionic_jp
  6. 6 実行結果: Error

  7. Next.jsのトランスパイラと相性がよくないらしい 7 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp https://github.com/ionic-team/ionic-framework/issues/24481#issuecomment-1016792922

  8. next.config.jsを更新しても、エラーになる 8 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp https://github.com/ionic-team/ionic-framework/issues/24481#issuecomment-1016792922

  9. next/dynamicでSSRを止める • 動的にComponentなどを importするためのライブラリ • Suspense的な使い方も可能 • SSR: falseでSSRを止めれる •

    Ionic Componentすべて これを書くのはかなり手間 9 Next.jsでIonic Reactを利用したWebサイトを開発した話 import dynamic from 'next/dynamic'; const IonApp = dynamic( async () => { const mod = await import('@ionic/react'); return mod.IonApp; }, { ssr: false } // this is what makes it work ); function MyApp({ Component, pageProps }: AppProps) { return( <IonApp> <Component {...pageProps} /> </IonApp> ) } export default MyApp #ionic_jp
  10. 別案: @ionic/coreだけを使う • IonicのComponentは Web Component • StencilのWeb Componentとして Next.js内で利用する

    • useEffectで defineCustomElements • <ion-app>など、 Web componentとしてJSXで利用 10 Next.jsでIonic Reactを利用したWebサイトを開発した話 import React, { useEffect } from 'react' import { defineCustomElements as ionDefineCustomElements } from '@ionic/core/loader'; function MyApp({ Component, pageProps }) { useEffect(() => { ionDefineCustomElements(window) }) return <p>Hello</p> } export default MyApp #ionic_jp
  11. TSXでIonic componentを利用する • JSXの型定義を拡張する • 定義さえしておけば、 ion-xタグもtsxで書ける 11 Next.jsでIonic Reactを利用したWebサイトを開発した話

    import { JSX as LocalJSX} from '@ionic/core' 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> {} } } #ionic_jp
  12. @ionic/core利用の注意点 • ioniconのパスがうまく動かない • Ion-infinite-scrollなど、 動かないものもいくつかある • @ionic/reactで サポートしてないものは諦める •

    @ionic/reactなら動くものだけ、 next/dynamicで定義しておく 12 Next.jsでIonic Reactを利用したWebサイトを開発した話 import dynamic from 'next/dynamic'; export const IonIcon = dynamic( async () => { const mod = await import('@ionic/react'); return mod.IonIcon; }, { ssr: false } // this is what makes it work ); #ionic_jp
  13. 別案その2: AppまるごとDynamic import • Pageに表示するComponentを まるごとdynamic import • https://github.com/mlynch/nextj s-tailwind-ionic-capacitor-starte

    r • TSの型情報もちゃんとわたる • pageファイルごとにimportが必要な のことに注意 13 Next.jsでIonic Reactを利用したWebサイトを開発した話 import dynamic from 'next/dynamic'; const App = dynamic(() => import('../components/AppShell'), { ssr: false, }); export default function Index() { return <App />; } #ionic_jp
  14. まとめ • SSRやSSGのあるFWに、@ionic/reactは不向き • SSRせずに動く方法がないかをFW側でまず調べる • 「動き」のないComponentは、@ionic/coreを使う方が楽なケースもある ◦ ただし少なくとも、IonIconは@ionic/react側を使いたい 14

    Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp
  15. Ionic / CapacitorでStripe Ionic Meetup #19 Tokyo - おまけ @hide__dev

    May 2022 15 #ionic_jp
  16. アプリ / Webでの決済方法 • 決済代行会社等が用意する決済ページにリダイレクトする • 決済代行会社等のAPIを利用し、 カード情報をtoken化した上で自社サーバーに送信する • カード情報は、自社サーバーを通過させてはいけない

    ◦ 「カード情報の非保持化」 ◦ 改正割賦販売法・クレジットカード取引におけるセキュリティ対策の強化に向けた実行計画 2018 16 Ionic / CapacitorでStripe #ionic_jp
  17. リダイレクト型のCheckoutと、token化のElements 17 Ionic / CapacitorでStripe #ionic_jp

  18. Checkout(リダイレクト型)はアプリ内ブラウザを利用 • サーバー側でCheckoutの セッションを作成 • セッションObjectに リダイレクト先URLがある • CapacitorのBrowser pluginで、

    決済ページを開く • 決済完了後もリダイレクトなので、 着地できるページなどが追加で必要 18 Ionic / CapacitorでStripe import { Browser } from '@capacitor/browser'; const openStripeCheckout = async () => { const res = await fetch('https://api.example.com/create_checkout_session') const session = await res.json() await Browser.open({ url: session.url }); }; #ionic_jp
  19. Elementsは、Capacitor pluginを利用する • Created by @rdlabo React hookだけ手伝った • Payment

    IntentやCustomerを サーバー側で作成 • createPaymentSheetと presentPaymentSheetで表示 • iOS / Androidでの対応を考えると、 自前実装はちょっと難易度高め 19 Ionic / CapacitorでStripe <IonItem button onClick={async e => { e.preventDefault() const { customer, paymentIntent, ephemeralKey } = await createPaymentIntent() await stripe.createPaymentSheet({ paymentIntentClientSecret: paymentIntent, customerId: customer, customerEphemeralKeySecret: ephemeralKey, merchantDisplayName: 'rdlabo' }) await stripe.presentPaymentSheet() }} > <IonLabel>Order</IonLabel> </IonItem> #ionic_jp
  20. More info 20 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp https://stripe.capacitorjs.jp/

  21. @stripe/react-stripe-js with React 18 (話者未検証) 21 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp https://github.com/stripe/react-stripe-js/issues/273#issuecomment-1127902121

  22. まとめ • カード情報は、自前で処理しようとしない。 • tokenに変換するAPI / SDKか、リダイレクトさせよう • Stripe &

    Capacitorの場合、@capacitor-community/stripe • リダイレクト(Checkout)では、 「決済完了後の処理(リダイレクト・表示)」に注意 22 Next.jsでIonic Reactを利用したWebサイトを開発した話 #ionic_jp