🫢

Expo(React Native)で環境変数を使いたいあなたへ。

に公開
1

この記事を読むとわかること・解決すること

  • Expoでの環境変数のいい感じの管理方法を知りたい!
  • eas build/updateのときになぜか、.envが読み込まれない!」

実験のために作成したリポジトリもあるので、よろしければ参考にしてみてください 👋
https://github.com/zackerms/expo-playground-credential

[宣伝] komichi というアプリを作っています!

「どこ行こうかなぁ〜」と考えてたら休日が終わることってありませんか?
このアプリを使うと、現在地や好きな場所から、自動的に付近の場所を検索してお出かけプランを提案してくれます!
見知った場所でも意外としらないスポットが出てきて面白いですよ!
https://komichi.app

先日、Android版をリリースいたしましたので、Androidユーザの方はぜひインストールお願いします!
https://play.google.com/store/apps/details?id=app.komichi&hl=ja

ローカル開発環境

Publicな環境変数を .env ファイルで管理する

Expoでは .env ファイルに EXPO_PUBLIC_ というプレフィックスをつけて環境変数を登録すると自動的に読み込んでくれます。(公式ドキュメント

// .env
EXPO_PUBLIC_APP_VERSION=1.0.0

参照方法

process.env.EXPO_PUBLIC_APP_VERSION

だいたい、Webの方法と同じですね。

そして、どうやらEXPO_PUBLIC_とした場合、環境変数を見に行っている訳ではなく、ビルド時に置き換えを行っているらしいため、process.env.EXPO_PUBLIC_XXXという書き方でないとだめだそうです(参考)。

// OK
process.env.EXPO_PUBLIC_KEY

// NG
process.env["EXPO_PUBLIC_KEY"]
const { EXPO_PUBLIC_KEY } = process.env

Privateな環境変数を使いたい!

Private な環境変数などは、公開されてほしくないのでEXPO_PUBLIC_とつけることはできません。 そんな方のための方法も用意されています。

EXPO_PUBLIC_ をつけない場合は process.env から参照することができなくなるので、Expo Constantsというライブラリを用いて参照します。

Expo Constantsをインストール

npx expo install expo-constants

今回、参照したい環境変数

// .env.local
API_KEY=sample

Expo Constantsで参照できるようにするためには、app.config.ts で登録してあげる必要があります。

// app.config.ts
import {ConfigContext} from "@expo/config"

export default ({config}: ConfigContext) => {
    config.extra = {
        ...config.extra,
        API_KEY: process.env.API_KEY,
    }
    return config;
};

参照方法

import Constants from "expo-constants";

Constants.expoConfig?.extra?.API_KEY

EAS

EAS Environment variables

EASのダッシュボードを開くと、Environment variablesというタブがあり、そこから環境変数を登録することができます。


引用:https://docs.expo.dev/eas/environment-variables/

環境変数には3つの種類があります

  • Plain Text
    • Publicな環境変数
    • 登録後もWebコンソールやCLIから中身を閲覧できます
  • Sensitive
    • Privateな環境変数
    • 登録後もWebコンソールやCLIから中身を閲覧できます
  • Secret
    • Privateな環境変数
    • 登録後は中身を閲覧できません

ビルド方法

EASを使ったビルド方法には2種類あります。
ビルド方法によって、どの環境変数を参照できるかが変わるので注意が必要です!

  • eas build
    • やること:ネイティブモジュールからビルドする
    • 参照可能な環境変数
      • .envファイルに記録されたEXPO_PUBLIC_で始まる環境変数
      • eas.json, eas.jsonで定義された環境変数
      • EASに登録した Plain Text, Sensitive, Secret
  • eas update
    • やること:JS部分だけを更新する
    • 参照可能な環境変数
      • .envファイルに記録されたEXPO_PUBLIC_で始まる環境変数
      • [ローカルで実行時] .env.* に記録された環境変数
      • [EAS上で実行時] EASに登録した Plain Text, Sensitive, Secret

したがって、ビルド時にのみ必要な機密情報(GOOGLE_SERVICES_JSONなど)はSecretsとして登録し、eas updateのときにも必要な機密情報はSensitiveとして登録する必要があります。

Production環境でPrivateな環境変数を使いたい!

EAS Buildを使う場合

ローカルで開発するときは、.env ファイルや.env.localファイルを使えば良いのですが、EASビルドを行う場合は話が変わってきます。

公式ドキュメントに以下のような記述があります。

Because your EAS Build job runs on a remote server, these .env files might not be available. For instance, .env files are excluded from your uploaded project if they are listed in .gitignore or not committed to your local version control system.

つまり、.env.local など .gitignore で git で管理されていないファイルはEASビルド時に参照できないのです。

そこで、先述した EAS Environment variables を利用します!

ここで登録された環境変数は、EASビルド時に参照することができ、app.config.ts に登録すると、アプリ内で利用することができます。

// app.config.ts
import {ConfigContext} from "@expo/config"

export default ({config}: ConfigContext) => {
    config.extra = {
        ...config.extra,
        API_KEY: process.env.API_KEY,
    }
    return config;
};

アプリケーション上では以下のように参照できます

Constants.expoConfig?.extra?.API_KEY
// process.env.API_KEY では参照できません

EAS Updateを使う場合

単純にeas updateを実行するとローカルの.env.*ファイルが読み込まれます。 そして、app.config.ts上ではその内容を参照することができますが、Constantsでなぜか参照できないという謎仕様があります。

そこで、以下のように、--environmentと指定することで、ローカルの.envファイルは参照せずに、EASで管理している環境変数を参照するようにすることができます。

eas update --environment production

参考:https://docs.expo.dev/eas/environment-variables/#use-environment-variables-with-eas-update

.env ファイルから自動で環境変数をEASに登録したい!

Expo Secretへの環境変数の登録はEASダッシュボードからもできますが、CLIを利用して、.env ファイルから自動的に import させることも可能です。

eas secret:push --scope project --env-file .env.local

Firebase(GCP)のサービスアカウントをEASに登録したい

サービスアカウントのクレデンシャルファイルのようなものは環境変数とは違い、扱いが難しくなりがちです。

しかし、EASにはファイルをアップロードする方法もあるためカンタンに管理することができます。

eas secret:create \
  --scope project \
  --name GOOGLE_SERVICES_JSON \
  --type file \
  --value ./google-services-android-production.json
  --force

このファイルを登録するときは以下のようにするとできます。

// app.config.ts
export default ({config}: ConfigContext) => {
    // Firebase
    config.android.googleServicesFile = process.env.GOOGLE_SERVICES_JSON || "./google-services-android.json";
    config.ios.googleServicesFile = process.env.GOOGLE_SERVICES_PLIST || "./GoogleService-Info.plist";

    return config;
}

Appendix

EASビルドでPrivateな環境変数を登録したい!(ローカルビルド編)

EASの厄介なところは、ローカルビルドではExpo Credentailを参照することができないという点です。

https://github.com/expo/eas-cli/issues/2392

ただ、ローカルビルドの場合は、.env.local ファイルを読み込むことが可能です。

Production環境とStaging環境で参照される環境変数を切り替えたい!

.env ファイルを用いた開発スタイルでは .env.staging, .env.production などのように、ファイル名に環境の名前をつけることで、ビルド環境ごとに自動的に読み込む環境変数ファイルを切り替えることが可能でした。 これにより、stagingとproductionで同じ環境変数が利用できるという恩恵があります。

しかし、Expo Secretsを利用すると、そのような切り替えは行ってくれません。

ProductionとStagingで環境変数の名前を分ける必要があります。

ですが、アプリ内のコードで環境ごとに参照する環境変数名を切り替えるということはしたくないです。

そこで、app.config.ts 内で環境に応じで、参照する環境変数を切り替えることで、アプリ内では同じ環境変数で利用できるようにします。

そのために、少しだけ工夫をします。

以下のように今の環境が何かを知れるようにします。

// .env.production
APP_ENV=production

// .env.staging
APP_ENV=staging

Expo Secretsに登録するときには、環境の名前をSURFFIXとして追加します。

// Expo Secrets
API_KEY=production-api-key
API_KEY_STAGING=staging-api-key

これで準備完了です。

app.config.ts で環境に応じて自動的に参照する環境変数の名前が切り替わるようにします。

// app.config.ts
export default ({config}: ConfigContext) => {
     const SUFFIX =
        config.extra.APP_ENV === "staging"
            ? "_STAGING"
            : "";
      
      config.extra = {
         API_KEY: process.env[`API_KEY${SUFFIX}`],
      }
}

これによって、参照するときには同じ環境変数名で参照することができます。

Constants.expoConfig?.extra?.API_KEY

Discussion

zackerzacker

環境変数の管理についてもっといいやり方があるよ!という方がいらしたら
ぜひアドバイスをいただきたいです!