メインコンテンツへスキップ
チュートリアル

ReactとCapacitorでモバイルアプリを構築する

ReactとCapacitorを使ったモバイルアプリの構築方法に加え、Capgoによるネイティブなナビゲーション、トランジション、iOSレイアウトのベストプラクティスを学びましょう。

ReactとCapacitorでモバイルアプリを構築する

このチュートリアルでは、まず新しい React アプリを作成し、Capacitorを使ってネイティブモバイル開発へと移行します。Capgo Native Navigation and Transitionsを追加してネイティブらしい操作感を実現したり、safe area対策に tailwind-capacitor を使用したりすることも可能です。

Capacitor を使えば、ReactのWebアプリケーションを、大幅な修正や React Native のような新しいスキルの習得なしに、簡単にネイティブモバイルアプリへ変換できます。

ほんの数ステップで、ほとんどのReactアプリケーションをモバイルアプリに変換できます。

このチュートリアルでは、新しいReactアプリから始めて Capacitor を組み込み、ネイティブモバイルアプリへ移行する手順を解説します。Capgo Native Navigation、Transitions、セーフエリア用の tailwind-capacitor も使えます。

Capacitor について

CapacitorJS はまさにゲームチェンジャーです!あらゆるWebプロジェクトに簡単に組み込むことができ、アプリケーションをネイティブWebViewでラップし、XcodeやAndroid Studioのネイティブプロジェクトを自動生成します。さらに、プラグインを使えば、JSブリッジ経由でカメラなどのネイティブデバイス機能にアクセスできます。

Capacitor を使えば、複雑なセットアップも高い学習コストも不要で、素晴らしいネイティブモバイルアプリを手に入れられます。軽量な API と無駄のない機能で、プロジェクトへの統合もとても簡単です。Capacitor なら、フル機能のネイティブアプリをこれほど簡単に作れることにきっと驚きますよ!

Reactアプリの準備

Reactアプリの作成方法はいろいろありますが、このチュートリアルでは最もシンプルな、空のReactアプリを作成する方法を使います:

npx create-react-app my-app

ネイティブモバイルアプリを作成するには、プロジェクトの エクスポート が必要です。そこで、シンプルなスクリプトを package.json に追加しましょう。これはReactプロジェクトのビルドとエクスポートに使えます:

{
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}

実行できるようになりました。 npm run build 心配は不要です。プロジェクトのルートディレクトリに新しい out フォルダが作成されているはずです。

このフォルダは後ほど Capacitor で使用されますが、まずは正しくセットアップする必要があります。

React アプリに Capacitor を追加する

Web アプリをネイティブのモバイルコンテナにパッケージ化するには、最初にいくつかの手順を踏む必要がありますが、その後は単一のコマンドを実行するだけで完了します。 sync コマンドを実行してください。

まず、最初に Capacitor CLI を開発用依存関係としてインストールし、プロジェクト内でセットアップします。セットアップ中に、名前と bundle ID のデフォルト値を受け入れるには「enter」を押してください。

次に、コアパッケージと iOS および Android プラットフォーム用の関連パッケージをインストールする必要があります。

最後に、プラットフォームを追加します。Capacitor を実行すると、プロジェクトのルートに各プラットフォーム用のフォルダが作成されます:

# Install the Capacitor CLI locally
npm install -D @capacitor/cli

# Initialize Capacitor in your React project
npx cap init

# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android

# Add the native platforms
npx cap add ios
npx cap add android

この時点で、Angular プロジェクト内に新しい iOS と Android Reactプロジェクト内のフォルダ。

これらは本物のネイティブプロジェクトです!

後で Android プロジェクトにアクセスするには、次をインストールする必要があります: デバッグ。iOSの場合はMacが必要で、次をインストールしてください: iOSプロファイリング.

さらに、プロジェクト内に次のファイルがあるはずです: capacitor.config.ts プロジェクト内のファイルで、同期時に使用される基本的なCapacitor設定が含まれています。注意すべき点は webDirは、ビルドコマンドの出力先を指している必要があります。現在は正しくありません。

これを修正するには、 capacitor.config.json ファイルを開き、次を更新してください: webDir:

{
  "appId": "com.example.app",
  "appName": "my-app",
  "webDir": "out",
  "bundledWebRuntime": false
}

以下のコマンドを実行して試すことができます:

npm run build
npx cap sync

最初のコマンドは npm run build は、Reactプロジェクトをビルドして静的ビルドをエクスポートするだけです。

一方、2番目のコマンドは npx cap sync すべてのWeb code をネイティブプラットフォームの適切な場所に同期し、アプリ内で表示できるようにします。

さらに、syncコマンドはネイティブプラットフォームの更新やプラグインのインストールを行う可能性があるため、新しい Capacitor プラグイン 実行しましょう npx cap sync を再度呼び出してください。

いつの間にか完了しています。それでは、実際にデバイスでアプリを確認してみましょう!

ネイティブアプリのビルドとデプロイ

iOSアプリを開発するには、 iOSプロファイリング のインストールが必要です。また、Androidアプリの場合は、 デバッグ のインストールが必要です。さらに、アプリをApp Storeで配布する場合は、iOS用にApple Developer Programへ、Android用にGoogle Play Consoleへの登録が必要になります。

ネイティブモバイル開発が初めてなら、Capacitor CLI を使って両方のネイティブプロジェクトを簡単に開けます:

npx cap open ios
npx cap open android

ネイティブプロジェクトの設定が完了すれば、接続されたデバイスへのアプリのデプロイは簡単です。Android Studioでは、準備が整うのを待つだけで、設定を変更することなく接続デバイスへアプリをデプロイできます。例を以下に示します:

android-studio-run

Xcodeでは、シミュレーターだけでなく実機にアプリをデプロイするために、署名アカウントの設定が必要です。初めての場合は、Xcodeが手順を案内してくれます(ただし、Developer Programへの登録が必要です)。設定後は、上部で接続済みのデバイスを選択し、再生ボタンを押すだけでアプリを実行できます。以下に例を示します:

xcode-run

おめでとうございます!React Webアプリのモバイルデバイスへのデプロイに成功しました。以下に例を示します:

react-mobile-app

でもちょっと待ってください。開発中にもっと速い方法があります…

Capacitor Live Reload

最近のフレームワークを使っていれば、ホットリロードには慣れているはずです。嬉しいことに、同じ機能を モバイルデバイス上でも 最小限の手間で利用できます!

Live Reloadでローカルでホストしているアプリへのアクセスを有効にする ネットワーク上で Capacitor アプリに特定のURLからコンテンツを読み込ませることで実現します。

最初のステップは、ローカルのIPアドレスを確認することです。Macを使用している場合は、ターミナルで次のコマンドを実行して確認できます:

ipconfig getifaddr en0

Windowsの場合は、次を実行してください:

ipconfig

次に、IPv4アドレスを探します。

また、Capacitor にサーバーから直接アプリを読み込むよう指示することもできます。そのためには、 capacitor.config.ts ファイル内で参照します:

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'my-app',
  webDir: 'out',
  bundledWebRuntime: false,
  server: {
    url: 'http://192.168.x.xx:3000',
    cleartext: true
  }
};

export default config;

必ず以下のものを使用してください: 正しいIPアドレスとポート番号を。この例では、Reactのデフォルトポートを使用しています。

それでは、これらの変更をネイティブプロジェクトにコピーして適用しましょう:

npx cap copy

この copy コマンドは次と似ています syncただし、 webフォルダと設定への変更内容だけをコピーし、 ネイティブプロジェクトは更新しません。

Android StudioやXcodeを使用して、アプリを再度デプロイできます。その後、Reactアプリに変更を加えた場合は、 アプリが自動的にリロードされ、 変更が反映されます!

注意点として、 カメラなどの新しいプラグインをインストールする場合、ネイティブプロジェクトの再ビルドが必要です。ネイティブファイルが変更されるため、その場で行うことはできません。

設定には正しいIPアドレスとポートを使用してください。上記のcodeブロックでは、デモ用にデフォルトのReactポートを表示しています。

Capacitor プラグインの使用

これまで何度か触れてきた Capacitor プラグインの実際の使い方を見てみましょう。次のコマンドを実行して、かなりシンプルなプラグインをインストールできます:

npm i @capacitor/share

特別なものはありませんが、 プラグインを共有、それでもネイティブの共有ダイアログが表示されます!これには、パッケージをインポートしてアプリから share() 関数を呼び出すだけでOKです。では、 src/App.js を次のように変更します:

import React from 'react';
import { Share } from '@capacitor/share';

function App() {
  const share = async () => {
    await Share.share({
      title: 'Open Youtube',
      text: 'Check new video on youtube',
      url: 'https://www.youtube.com',
      dialogTitle: 'Share with friends'
    });
  };

  return (
    <div>
      <h1>Welcome to React and Capacitor!</h1>
      <p>
        <h2>Cool channel</h2>
        <button onClick={() => share()}>Share now!</button>
      </p>
    </div>
  );
}

export default App;

先ほど説明したように、新しいプラグインをインストールするときは、sync 操作を行ってからアプリをデバイスに再デプロイする必要があります。これを行うには、次のコマンドを実行してください:

npx cap sync

ボタンを押すと、美しいネイティブの共有ダイアログが実際に動作する様子を確認できます!

react-capacitor-share

次に、Capgo のナビゲーションとトランジションで、iOS と Android でアプリをよりネイティブに感じさせ、横方向のオーバーフローやセーフエリアの欠けを引き起こす iOS でよくあるレイアウト問題も修正できます。

Capgo Native Navigation and Transitions によるネイティブ感のあるUI

私は長年、 Ionic to build cross-platform applications, but integrating it with React is hacky and rarely worth it when you already have Tailwind CSS.

React + Capacitor アプリでネイティブなモバイル体験を実現するには、Konsta UIのようなWeb専用のUIキットではなく、Capgo プラグインを使用しましょう:

  • @capgo/capacitor-native-navigation — ネイティブのナビゲーションバー、iOSでのLiquid Glassタブバー、Androidでのブラー加工されたタブバー。React Routerでルート状態を管理し、プラグインがネイティブのUI(chrome)を制御します。
  • @capgo/capacitor-transitions — Ionic UIを採用することなく、WebViewレイヤー上でIonicスタイルのページ遷移やiOSのエッジスワイプバックを実現します。

両方をインストールします:

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

CSSのinsetモードを使用してネイティブナビゲーションを設定し、Webコンテンツがネイティブバーと重ならないようにします:

import { NativeNavigation } from '@capgo/capacitor-native-navigation';

await NativeNavigation.configure({
  contentInsetMode: 'css',
  animationDuration: 360,
  glass: {
    effect: 'liquidGlass',
  },
});

Liquid Glassタブバーをレンダリングします(iOSはシステムによるレンダリング、AndroidはブラーのかかったWebViewバックドロップを使用):

await NativeNavigation.setTabbar({
  selectedId: 'home',
  labelVisibilityMode: 'labeled',
  icons: true,
  colors: { dynamic: true },
  tabs: [
    { id: 'home', title: 'Home', icon: { svg: '...' } },
    { id: 'settings', title: 'Settings', icon: { svg: '...' } },
  ],
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  navigate(`/${id}`);
});

アプリシェルにネイティブのページ遷移を追加します:

import { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/react';

initTransitions({ platform: 'auto' });

export function AppShell() {
  const navigate = useNavigate();
  const outletRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (outletRef.current) {
      setupRouterOutlet(outletRef.current, { platform: 'auto', swipeGesture: 'auto' });
    }
  }, []);

  const openSettings = () => {
    setDirection('forward');
    navigate('/settings');
  };

  return <cap-router-outlet ref={outletRef}>{/* routes */}</cap-router-outlet>;
}

ルーティングされたページを以下でラップします: cap-router-outlet, cap-pageや cap-content、そして呼び出します setDirection('forward') または setDirection('back') 遷移前に実行してください。ネイティブナビゲーションがその領域を管理している場合、Webのヘッダーやフッターを重複させないでください。

ガイドの全文はこちら: @capgo/capacitor-native-navigation の活用 と @capgo/capacitor-transitions の活用.

Tailwind によるセーフエリア対応

Tailwind CSS でデバイスのセーフエリアを扱うには、以下を使用します: @capgo/tailwind-capacitor ( tailwind-capacitor として npm で公開)。これは、 safe-areas ユーティリティや Capacitor と相性の良いその他の Tailwind プラグインを提供します:

bun add -D tailwind-capacitor

では src/index.css:

@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";

次のようなユーティリティを使用します: pt-safe, pb-safeや px-safe 手作業でばらまくのではなく env(safe-area-inset-*) 手動で行う必要はありません。このプロジェクトは活発に開発されており、Reactの設定に必要な機能が不足している場合は、 GitHub でPRを作成してください.

iOSのレイアウト問題を修正(ビューポート、セーフエリア、横方向のオーバーフロー)

iOSでコンテンツが切れて見えたり、ずれて見えたり、横スクロールが発生したりする場合は、さらに追加するだけでも、 overflow-x: hidden viewportタグを調整するだけでも通常は解決しません。以下のチェックを順番に確認してください。

viewport メタタグが正しく適用されているか確認する

viewport metaタグを以下に追加します index.html 既存の <head>:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

iOSのセーフエリアは1つのルートラッパーだけで処理する

単一のアプリシェルを作成し、そこにセーフエリアのパディングを適用してください — 複数のネストしたコンポーネントではなく:

html,
body,
#root {
  width: 100%;
  min-height: 100%;
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

* {
  box-sizing: border-box;
}

.app-shell {
  min-height: 100dvh;
  width: 100%;
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

すべてのページコンテンツを以下でラップします: .app-shellヘッダー、モーダル、レイアウトラッパーで safe-area のパディングが重複すると、UI が欠けたり、逆に大きすぎたりすることがよくあります。

を使用すると、 @capgo/tailwind-capacitor同じパディングを次のようなユーティリティで表現できます: pt-safe pb-safe px-safe その単一のシェル上で。

Capacitor iOS を設定 contentInset まで never 最初に

では capacitor.config.ts、native inset を無効にすることを推奨し、CSS(または Native Navigation のもの contentInsetMode: 'css')に safe area を任せる:

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'dist',
  ios: {
    contentInset: 'never',
  },
};

Capacitor の自動コンテンツ inset と CSS を混在させると env(safe-area-inset-*) paddingが原因で、余白が二重に見えることがよくあります。

実際にオーバーフローしている要素を特定する

主な原因は、以下の要素を使用している場合です: 100vwTailwind、 w-screen固定ピクセル幅、または大きな min-width.

Safari Web Inspectorで以下を実行してください:

[...document.querySelectorAll('*')]
  .filter(el => el.scrollWidth > document.documentElement.clientWidth)
  .map(el => ({
    el,
    tag: el.tagName,
    class: el.className,
    scrollWidth: el.scrollWidth,
    clientWidth: document.documentElement.clientWidth,
  }));

Tailwindを使用する場合は、可能な限り w-screen を使用して w-full 置き換えてください。水平方向のオーバーフロー問題の多くは 100vw / w-screen、重複したセーフエリアのパディング、または固定幅のコンテナに起因し、viewportのmetaタグ自体が原因ではありません。

まとめ

Capacitor は、既存のWebプロジェクトをベースにネイティブアプリを構築するための優れた選択肢です。code を簡単に共有し、一貫したUIを維持できます。

さらに、追加されたことで Capgo、アプリへのLive Updatesの追加がより簡単になり、ユーザーは常に最新の機能とバグ修正を利用できます。

ReactアプリにCapgoを追加する方法については、こちらの記事をご覧ください:

続き:ReactとCapacitorによるモバイルアプリ開発

使用している場合 ReactとCapacitorによるモバイルアプリ開発 CI/CD自動化を計画するには、次と連携してください Capgo での CI/CD 設定 Capgo CI/CDでのプロダクトワークフローについては、 Capgo Native Build Capgo Native Buildsでのプロダクトワークフローについては、 Capgo インテグレーション Capgo インテグレーションでのプロダクトワークフロー向けに、 CI/CD 連携 CI/CD Integrationの実装詳細については、 GitHub Actions 連携 GitHub Actions Integrationの実装詳細については。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。