Expoではアプリのメタ情報や設定値をapp.json
に記載します。ただapp.json
はstaticなJSONファイルのためそのままだと環境別(例えばdevelopment, staging, productionのように)に値を指定できません。
そこで環境別に設定値を記述するにはどうしたらよいか説明します。
以前のExpoでは以下のように起動時に--config
オプションで設定ファイルを指定することができましたが、その方式についてはdeprecatedになっているため、利用しないでください。
expo start --config app.dev.json
expo start --config app.production.json
fyi/config-flag-migration.md at master · expo/fyi
設定を動的に切り替える場合、app.config.js
またはapp.config.ts
をエントリファイルとして利用します。環境別にエントリファイルを分けるのではなく、同一のエントリファイルで中身を動的にスイッチする仕組みです。
以下のように環境変数を指定して起動し
APP_ENV=dev expo start
app.config.ts
でその環境変数に応じて設定の中身を動的に切り替えます。
import { ConfigContext } from "@expo/config"
export default ({ config }: ConfigContext) => {
const appEnvName = process.env.APP_ENV || "dev"
return {
...config,
// 動的な記述を追加
}
}
環境によって変わらない部分(またはデフォルト値)についてはapp.json
(またはapp.config.json
)に記載しておくとよいです。Expoの起動時、app.json
が存在する場合はまずそれを読み込んだ上でapp.config.ts
が読み込まれるためです。
// app.jsonにデフォルト設定を記載
{
"expo": {
"name": "xxxxxx",
"slug": "xxxxxx",
"orientation": "portrait"
...
}
}
app.json
の中身はfunctionの引数として参照できます。
app.config.ts
から更に環境別に用意した設定ファイルをインポートしたいケースがあると思います。その場合、app.config.dev.ts
等、tsファイルで用意しておきたいところですが、app.config.ts
からはtsファイルをimportすることはサポートされていません。
expo/configuration.md at main · expo/expo
Importing/requiring other JavaScript files. Using import/export syntax in external files is not supported. All imported files must be transpiled to support your current version of Node.js.
そのためjsファイルまたはjsonファイルで用意しておく必要があります。
tsファイルにしておきtranspileするという手もありますが、管理の手間が増えてしまうため辞めたほうがよいと思います。また、設定ファイルを分けずにすべての環境の設定をapp.config.ts
に記載してしまうというのも一つの手段です。
以下のどちらかでファイルを用意しておき、
// app.config.<env>.json
{
name: "yyyyy",
...
}
// app.config.<env>.js
module.exports = {
name: "yyyyy",
...
}
app.config.ts
からimportして利用します。個別の設定はapp.json
とは異なりルートに{ "expo": {}}
は記述する必要が無い点に注意してください。
import { ConfigContext } from "@expo/config"
import merge from "deepmerge"
import devConfig from "./app.config.dev"
import productionConfig from "./app.config.production"
type APP_ENV_NAME = "dev" | "production"
const envMapping: { [key in APP_ENV_NAME]: Record<string, any> } = {
dev: devConfig,
production: productionConfig,
}
export default ({ config }: ConfigContext) => {
const appEnvName = process.env.APP_ENV || "dev"
if (!["dev", "production"].includes(appEnvName)) {
throw new Error(`APP_ENV: ${appEnvName} is not supported.`)
}
const envConfig = envMapping[appEnvName as APP_ENV_NAME]
const o = merge(config, envConfig)
return o
}
アプリのコードからexpo-constantsを使って設定値にアクセスさせたい場合、以下のようにextra
フィールドに環境変数の値を設定しておきます。
{
extra: ["APP_NAME", "API_ENDPOINT"].reduce((envs, key) => ({
...envs,
[key]: process.env[key],
}), {})
}
コードからは以下のようにアクセスできます(Expo SDKが46以降の場合)。
import Constants from 'expo-constants'
console.log("API_ENDPOINT:", Constants.expoConfig.extra.API_ENDPOINT)
Expo SDKが45以前の場合、Constants.manifest
を使います。
import Constants from 'expo-constants'
console.log("API_ENDPOINT:", Constants.manifest.extra.API_ENDPOINT)
開発環境ではExpoサーバの起動時にAPP_ENV=dev expo start
のように環境変数を指定できますが、EAS Buildでアプリバンドルをビルドする場合はサーバを起動するわけではないため、別途APP_ENVを渡す設定が必要です。
EAS Buildで環境変数を渡すにはeas.json
で各プロファイルの"env"
フィールドに項目を追加します。最低限APP_ENV
だけ渡してあげれば、あとはapp.config.ts
でその値に応じて設定を切り分けることができます。
{
"build": {
"dev": {
"env": {
"APP_ENV": "dev"
}
},
"production": {
"env": {
"APP_ENV": "production"
}
}
}
}
eas.json
に個別の環境変数をすべて設定してしまうこともできますが、eas.json
の環境変数は開発時のExpoサーバ起動時に読み込まれないため、結局重複した設定を更に別の箇所に記載しなくならなくなってしまうため辞めたほうがよいです。
また、もしも値をGit上で管理せず秘密にしたい場合、EAS BuildのSecretsを利用するのがよいと思います。この値は開発時(Expoサーバ起動時)には参照できないため、ビルドされたアプリバンドルからのみ使う想定になります。
Environment variables and secrets - Expo Documentation