📱

ReactNative(Expo)環境構築からFirebaseログイン

2024/09/25に公開

個人でReactNativeを使ったNativeアプリを作りたいと考えているので
Expoを使用した環境構築とFirebase連携までメモしようと思います。

ReactNative(Expo)とは??

メリット

  1. Expoとは?
    Expoは、React Nativeの拡張ツールキットです。通常のReact Native開発では、Xcode(iOS)やAndroid Studio(Android)などのセットアップが必要ですが、Expoを使うと、その多くが簡略化されます。環境構築が非常にシンプルになり、すぐにアプリの開発を始めることが可能です。

  2. Expoのメリット
    Expoには、次のような多くのメリットがあります。

簡単なセットアップ
Expoを使うと、モバイルアプリの開発を始めるのに必要なツールのセットアップが非常に簡単です。iOSやAndroid向けの複雑な設定を気にする必要がなく、Node.jsとExpo CLIをインストールするだけですぐに開発を開始できます。

  1. OTA(Over-the-Air)更新
    Expoを使ってデプロイされたアプリは、OTA更新が可能です。これにより、App StoreやGoogle Playに新しいバージョンを公開することなく、コードの変更をユーザーのアプリに即座に反映させることができます。開発中のテストや緊急の修正が非常に簡単です。

デメリット

1.ネイティブモジュールの制限
Expoは、多くのネイティブ機能を簡単に利用できるAPIを提供していますが、カスタムのネイティブコード(iOSのObjective-C/SwiftやAndroidのJava/Kotlin)をプロジェクトに追加するのが難しいです。的には、Expoでは提供されていないネイティブ機能やライブラリが必要とする場合、Expoから**「eject」**という作業を行って通常のReact Nativeプロジェクトに移行しなければなりません。

この「eject」を行うと、Expoの快適さが失われ、React Nativeの複雑な環境設定が必要になります。そのため、最初からReact Nativeを選んだ方が良い場合もあります。

2.バイナリサイズが大きくなりやすい
Expoを使って作成されたアプリには、先に多くの機能が含まれています。そのため、使っていない機能も含めてアプリのサイズが大きくなりやすく、最終的な**バイナリサイズ(アプリの容量) **が肥大化する傾向があります。これは、アプリの配信やユーザーのダウンロードに影響を与える可能性があります。

通常のReact Nativeプロジェクトでは、必要な機能だけを含めることができるために、アプリのサイズを最適化しやすいです。

  1. iOSアプリのビルドにはMacが必要
    Expoは、WindowsやLinuxでも開発が可能ですが、iOS向けのビルドを行うためには最終的にMacが必要になります。Expoのクラウドビルドサービスを利用することでMacなしでiOSアプリを生成するそれは可能ですが、ローカルでのデバッグや高さの設定が必要な場合はMacを使う必要が出てきます。

  2. Expoの依存関係に縛られる
    Expo を使うことで開発が簡単になる逆に、Expo のバージョンに依存する形になります。Expo は定期的に更新されますが、使用しているバージョンの保持や非互換性によって、特定のライブラリや機能時にはバージョンアップ、コードの変更や修正が必要になることもありますが、これが大規模なプロジェクトでは煩わしさを感じることもあります。

5.高パフォーマンスなアプリには限界がある
Expoは、一般的なアプリ開発に適しており、多くのケースで十分なパフォーマンスを発揮します。しかし、ゲーム開発や複雑なアニメーション、重い計算処理を行うアプリでは、パフォーマンスの面で限界があります。このような場合には、ネイティブコードやカスタムの最適化が必要になるため、Expoでは十分に対応できないことがあります。

環境構築

ここからは実際に環境構築をしていきます。ターミナルより以下のコマンドを入力してください。

npx create-expo-app@latest --template default
テンプレート 説明
default デフォルトのテンプレート。マルチスクリーン アプリを構築するために設計されています。Expo CLI、Expo Router ライブラリ、TypeScript 構成などの推奨ツールが含まれています。ほとんどのアプリに適しています。
blank ナビゲーションを構成せずに、必要な最小限の npm 依存関係をインストールします。
blank-typescript TypeScript が有効になっている空のテンプレート。
tabs Expo Router と TypeScript を有効にしてファイルベースのルーティングをインストールおよび構成します。
bare-minimum ネイティブ ディレクトリ (android および ios) が生成された空のテンプレート。npx expo prebuild セットアップ中に実行されます。

Expo routerを使用すると、ファイルベースのルーティングを実現することができ
普段Next.jsを使用している人だと馴染みがあると思います。

作成されたディレクトリで npm run startでexpoが立ち上がるのでios android web環境を立ち上げてください。

以下の画面が立ち上がればOKです。
コマンド一つでここまで出来上がるのは簡単でいいですね。

Firebase連携

ここからはFirebaseと連携させて認証まで行える様にしましょう。
以下URLよりプロジェクトを作成します。名前などはお好みで設定しましょう。
URL

作成後サイドバーのAuthenticationをクリックし、メールアドレスとパスワードを有効にしましょう。

その後にログインに使うためのユーザを作成しましょう。
Authentication->ユーザを追加からemail、passwordを入力して
ユーザを作成します。

Firebaseを利用するにはアプリの追加が必要になるのでコンソール画面に戻って画面中央にある</>ボタンをクリックしてください。アプリを利用するためのコードを取得します。

作成する途中で表示されるapi keyなどは後ほど使用するので
大切に保存しておきましょう。

次はエディタの方に戻り、引き続きfirebase周りの設定を行います。
ターミナルでfirebaseライブラリをインストールします。

npx expo install firebase

次にルートディレクトリにlibフォルダを作成して、その中にfirebase.tsを作成し
ユーザ登録などで呼び出せる様にしましょう。apiKeyなどは先ほどfirebase consoleで表示されたものを使用します。

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const firebaseConfig = {
  apiKey: '',
  authDomain: '',
  projectId: '',
  storageBucket: '',
  messagingSenderId: '',
  appId: '',
};

const app = initializeApp(firebaseConfig);

export const auth = getAuth(app);

次にログイン用のpageを作成します。
app/(tabs)以下にlogin.tsxを作成しましょう。
今回はバリデーションなどは特に設定しません。

import React, { useState } from "react";
import { View, TextInput, Button, StyleSheet, Text } from "react-native";
import { router } from "expo-router";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "@/lib/firebase";

export default function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");

  const handleLogin = async () => {
    try {
      await signInWithEmailAndPassword(auth, email, password);
      router.replace("/");
    } catch (error) {
      setError("Login failed. Please check your email and password.");
      console.error(error);
    }
  };

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
      />
      <TextInput
        style={styles.input}
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      <Button title="Login" onPress={handleLogin} />

      {error ? <Text style={styles.errorText}>{error}</Text> : null}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    padding: 16,
  },
  input: {
    height: 40,
    borderColor: "gray",
    borderWidth: 1,
    marginBottom: 12,
    paddingHorizontal: 8,
  },
  googleButton: {
    backgroundColor: "#4285F4",
    padding: 10,
    alignItems: "center",
    marginTop: 10,
  },
  googleButtonText: {
    color: "white",
    fontWeight: "bold",
  },
  errorText: {
    color: "red",
    marginTop: 10,
  },
});


作成したコンポーネントをnavigationに追加しましょう。

app/(tabs)/_layout.tsx

import { Tabs } from "expo-router";
import React from "react";

import { TabBarIcon } from "@/components/navigation/TabBarIcon";
import { Colors } from "@/constants/Colors";
import { useColorScheme } from "@/hooks/useColorScheme";

export default function TabLayout() {
  const colorScheme = useColorScheme();

  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
        headerShown: false,
      }}
    >
      <Tabs.Screen
        name="index"
        options={{
          title: "Home",
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon
              name={focused ? "home" : "home-outline"}
              color={color}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="explore"
        options={{
          title: "Explore",
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon
              name={focused ? "code-slash" : "code-slash-outline"}
              color={color}
            />
          ),
        }}
      />
      <Tabs.Screen
        name="login"
        options={{
          title: "login",
          tabBarIcon: ({ color, focused }) => (
            <TabBarIcon
              name={focused ? "code-slash" : "code-slash-outline"}
              color={color}
            />
          ),
        }}
      />
    </Tabs>
  );
}


これでdeviceを立ち上げて、firebase consoleで作成したユーザでログインをして
homeに遷移すればOKです。

まとめ

今回はReactNativeのExpoを使用して、環境構築からfirebaseログインまでを解説しました。
firebaseにはgoogleログインや匿名認証などあるので他にもいろいろ試していこうと思います!
ここまでみてくださりありがとうございました!

Discussion