Hamdi Al Masalmeh
Hamdi Al Masalmeh

Reputation: 21

How to Use Environment Variables in Expo React Native for Firebase Initialization

I'm working on a React Native project using Expo and I'm trying to initialize Firebase using environment variables for better security and configurability. However, I'm facing issues in properly setting up these environment variables in my Expo project.

What I've done so far:

//app.config.ts
import "dotenv/config";
import { ExpoConfig, ConfigContext } from "expo/config";

export default ({ config }: ConfigContext): ExpoConfig => ({
  ...config,
  name: "expo-app",
  slug: "expo-app",
  extra: {
    apiKey: process.env.API_KEY,
    authDomain: process.env.AUTH_DOMAIN,
    projectId: process.env.PROJECT_ID,
    storageBucket: process.env.STORAGE_BUCKET,
    messagingSenderId: process.env.MESSAGING_SENDER_ID,
    appId: process.env.APP_ID,
  },
});

//firebase.ts
import { initializeApp } from "firebase/app";
import { getReactNativePersistence, initializeAuth } from "firebase/auth";
import ReactNativeAsyncStorage from "@react-native-async-storage/async-storage";
import { getFirestore } from "firebase/firestore";
import Constants from "expo-constants";

const firebaseConfig = {
  apiKey: Constants.expoConfig?.extra?.apiKey,
  authDomain: Constants.expoConfig?.extra?.authDomain,
  projectId: Constants.expoConfig?.extra?.projectId,
  storageBucket: Constants.expoConfig?.extra?.storageBucket,
  messagingSenderId: Constants.expoConfig?.extra?.messagingSenderId,
  appId: Constants.expoConfig?.extra?.appId,
};

const app = initializeApp(firebaseConfig);

const auth = initializeAuth(app, {
  persistence: getReactNativePersistence(ReactNativeAsyncStorage),
});

export const database = getFirestore();
export { auth };

runing npx expo config gives me the right values from .env

Issues Encountered:

I'm not sure if the environment variables from dotenv are being correctly passed from app.config.ts to firebase.ts.

I have tried the following:

Questions:

How do I ensure that my environment variables set in app.config.ts are properly passed to the Firebase initialization script? How can i create 2 env files for the development and production? Is there a recommended approach or best practice for managing sensitive config like Firebase in an Expo React Native environment? Any help or guidance on this would be greatly appreciated!

Upvotes: 2

Views: 434

Answers (1)

Valentin
Valentin

Reputation: 204

Something internet is rather suprising (in a bad way) when you face such generic case anybody having two firebase project would face...

So as I m someone resilient, here is the answer for anyone who face it in the future

  1. Install this dependencies (with npm or yarn)
yarn add react-native-dotenv
yarn add -D @types/react-native-dotenv # For TypeScript
  1. Update your babel.config.js

module.exports = {
  plugins: [
    [
      'module:react-native-dotenv',
      {
        moduleName: '@env',
        path: '.env',
      },
    ],
  ],
};
  1. Import All Variables using your module (e.g : firebase.ts)
import AsyncStorage from "@react-native-async-storage/async-storage";
import { initializeApp } from "firebase/app";
import { initializeAuth, getReactNativePersistence } from "firebase/auth";

import {
    FIREBASE_API_KEY,
    FIREBASE_AUTH_DOMAIN,
    FIREBASE_PROJECT_ID,
    FIREBASE_STORAGE_BUCKET,
    FIREBASE_MESSAGING_S_ID,
    FIREBASE_APP_ID,
    FIREBASE_MEASURE_ID,
} from "@env";

// Initialize Firebase
const firebaseConfig = {
    apiKey: FIREBASE_API_KEY,
    authDomain: FIREBASE_AUTH_DOMAIN,
    projectId: FIREBASE_PROJECT_ID,
    storageBucket: FIREBASE_STORAGE_BUCKET,
    messagingSenderId: FIREBASE_MESSAGING_S_ID,
    appId: FIREBASE_APP_ID,
    measurementId: FIREBASE_MEASURE_ID,
};

export const firebaseApp = initializeApp(firebaseConfig);

export const firebaseAuth = initializeAuth(firebaseApp, {
    persistence: getReactNativePersistence(AsyncStorage),
});

Wildcard import do not work here, not with this library.

You can create another file to create your custom export and import this file directly if you want.

  1. Add Typescript declaration (e.g : .env.d.ts)
declare module '@env' {
  export const FIREBASE_API_KEY: string;
  export const FIREBASE_AUTH_DOMAIN: string;
  // Add more variables as needed
}

It works, both on development and production, in my case I'm using EAS Build passing variable from EAS Secrets and it still work (if anyone face such scenario).

For EXPO, this should NOT be used to configure your app.config.ts file, this one should directly use expo-constants

Hope it's help you :)

Upvotes: 0

Related Questions