Skip to content
Learni
Voir tous les tutoriels
Développement Mobile

Comment créer une app hybride Ionic Capacitor 2026

Read in English

Introduction

Les applications mobiles hybrides révolutionnent le développement en 2026 : un seul codebase JavaScript/TypeScript pour cibler le Web, iOS et Android simultanément. Ionic, avec son framework UI basé sur des composants web standards (StencilJS), et Capacitor, le moteur natif moderne de Ionic, permettent d'accéder aux APIs natives comme la caméra ou les notifications via des plugins bridge.

Pourquoi choisir cette stack ? Contrairement à React Native (plus lourd), Ionic + Capacitor offre une perf proche du natif via WebView optimisée, un hot reload ultra-rapide, et une maintenance simplifiée. Imaginez : votre app PWA devient native en quelques commandes. Ce tutoriel intermédiaire vous guide pas à pas pour un projet complet avec une page d'accueil interactive et un plugin caméra. À la fin, vous builderez pour Android/iOS. Temps estimé : 30 min. Parfait pour les devs React qui veulent conquérir le mobile sans réécrire tout.

Prérequis

  • Node.js 20+ et npm 10+
  • Connaissances en React et TypeScript
  • Ionic CLI (installée ci-après)
  • Android Studio (pour Android) ou Xcode 15+ (pour iOS, macOS requis)
  • Capacitor CLI
  • Un émulateur Android ou simulateur iOS configuré

Installer Ionic CLI et créer le projet

terminal
npm install -g @ionic/cli@latest
ionic start photoGallery tabs --type react --capacitor
cd photoGallery
ionic serve

Cette commande installe globalement la CLI Ionic, crée un projet tabs React avec Capacitor intégré, et lance le serveur dev. Le template 'tabs' fournit une structure navigable prête. Évitez 'blank' pour un démarrage rapide ; testez toujours avec 'ionic serve' pour vérifier le hot reload.

Structure du projet généré

Votre projet contient :

  • src/ : Composants React/Ionic (pages, hooks).
  • capacitor.config.ts : Configuration Capacitor.
  • android/ et ios/ : Générés après sync.

Ouvrez http://localhost:8100 : tabs Explore, Tab1, Tab2 avec UI Material Design-like. Analogie : comme un Next.js mais pour mobile, avec routing Ionic.

Configurer Capacitor pour plugins natifs

capacitor.config.ts
import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.learni.photogallery',
  appName: 'Photo Gallery',
  webDir: 'build',
  bundledWebRuntime: false,
  plugins: {
    Camera: {
      permissions: {
        camera: true,
        photos: true
      }
    }
  }
};

export default config;

Ce fichier centralise l'ID app unique (pour stores), le dossier de build web, et active le plugin Camera avec permissions iOS/Android. 'bundledWebRuntime: false' utilise le WKWebView natif pour perf max. Piège : oubliez 'webDir' et le build web échoue.

Ajouter le plugin Camera et sync

terminal
npm install @capacitor/camera @capacitor/core
npm install @capacitor/android @capacitor/ios
npx cap sync
npx cap add android
npx cap add ios

Installe le plugin Camera officiel, les plateformes natives, sync le web vers natives, et ajoute les projets Android/iOS. 'cap sync' copie assets et régénère. Attention : exécutez après tout changement de dépendances pour éviter crashes natifs.

Intégrer la caméra dans une page

Modifiez maintenant src/pages/Explore.tsx pour capturer/prendre photo. Utilisez useCamera hook fourni par Ionic.

Page Explore avec capture photo

src/pages/Explore.tsx
import { useState } from 'react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonFab, IonFabButton, IonIcon, IonImg, useCamera } from '@ionic/react';
import { camera } from 'ionicons/icons';

const Explore: React.FC = () => {
  const [photo, setPhoto] = useState<string>();
  const { photo: cameraPhoto, takePhoto } = useCamera();

  const takePicture = async () => {
    const photoTaken = await takePhoto({
      quality: 90,
      allowEditing: true,
      resultType: 'dataUrl'
    });
    setPhoto(photoTaken.dataUrl);
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Explore</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        {photo && <IonImg src={photo} alt="Photo capturée" />}
        <IonFab vertical="bottom" horizontal="center" slot="fixed">
          <IonFabButton onClick={takePicture}>
            <IonIcon icon={camera}></IonIcon>
          </IonFabButton>
        </IonFab>
      </IonContent>
    </IonPage>
  );
};

export default Explore;

Ce composant complet utilise le hook useCamera() pour prendre une photo éditée (qualité 90%), l'affiche via , et un FAB flottant. Hook gère permissions auto. Piège : sans resultType: 'dataUrl', pas d'affichage web ; testez sur device pour permissions.

Build web et sync Capacitor

terminal
npm run build
npx cap sync
npx cap open android
# Ou pour iOS : npx cap open ios

Build l'app web en prod (dist/build), sync vers natives, et ouvre Android Studio/Xcode. Lancez l'émulateur depuis l'IDE. Évitez de skip 'sync' : natives ne voient pas les assets mis à jour.

Tester sur device

Web : ionic serve.
Android : Studio > Run.
iOS : Xcode > Run.
Permissions demandées auto pour caméra. Debug : Chrome DevTools via chrome://inspect pour Android.

Permissions Android personnalisées

android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-feature android:name="android.hardware.camera" android:required="true" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name">
    <activity android:exported="true" android:launchMode="singleTask" android:name="com.getcapacitorcommunity.camera.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>
</manifest>

Extrait clé du Manifest Android : ajoute permissions caméra/stockage. 'required=true' force présence caméra. Éditez post-'cap sync' ; rebuild APK. Piège iOS : équivalent dans Info.plist via Xcode.

Bonnes pratiques

  • Toujours sync après build : npx cap sync avant toute ouverture IDE.
  • Utilisez hooks Ionic pour plugins : abstraction permissions/state.
  • PWA first : testez web avant native pour 80% des bugs.
  • Gérez erreurs offline : Capacitor plugins wrap try/catch.
  • Versionnez capacitor.config.ts en Git : clé pour CI/CD.

Erreurs courantes à éviter

  • Oubli de npm run build : natives chargent version dev cassée.
  • Permissions non déclarées : crash silencieux sur device (ajoutez en Manifest/Info.plist).
  • resultType: 'uri' sans stockage : photos perdues (préférez 'dataUrl' pour simplicité).
  • Pas de 'bundledWebRuntime: false' : perf WebView dégradée sur iOS.

Pour aller plus loin

  • Plugins avancés : Geolocation, Push Notifications (docs Capacitor).
  • State management : Zustand ou Jotai pour apps complexes.
  • CI/CD : GitHub Actions pour auto-build APK/IPA.
Découvrez nos formations Learni Dev sur le mobile hybride et masterisez Flutter ou React Native.