跳到主要内容

expo的环境变量管理相关问题

原生配置和expo配置间的一些优先级问题

EAS Build打包时出现这个提示:

expo eas build时出现提示:Loaded "env" configuration for the "production" profile: EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, EXPO_PUBLIC_REVENUE_CAT_API_KEY_ANDROID, EXPO_PUBLIC_MOONSHOT_BASE_URL. Learn more  
Specified value for "android.package" in app.config.js or app.json is ignored because an android directory was detected in the project.
EAS Build will use the value found in the native code.

首先,提示的第一部分是:

Loaded "env" configuration for the "production" profile: EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, EXPO_PUBLIC_REVENUE_CAT_API_KEY_ANDROID, EXPO_PUBLIC_MOONSHOT_BASE_URL.

这意味着 Expo 已正确加载了你为 "production" 环境配置的 env 变量。这部分的提示表明你的环境变量(如 EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS 等)已经被加载,并且将在构建过程中使用。

因此,app.json 中的 env 配置仍然有效,尤其是这些公共的环境变量 (EXPO_PUBLIC_*)。它们会在构建时被读取并注入到你的应用中。

第二部分的提示是:

Specified value for "android.package" in app.config.js or app.json is ignored because an android directory was detected in the project.
EAS Build will use the value found in the native code.

这句话的意思是,尽管你在 app.jsonapp.config.js 中指定了 android.package,但由于你的项目中已经存在 android 目录(即你已经弹出到 Expo 管理的原生代码之外),EAS Build 将忽略 app.json 中的 android.package 配置,并优先使用位于原生代码中的包名配置(通常是在 android/app/src/main/AndroidManifest.xml 文件中定义的 package 属性)。

因此,除了 android.package 之外,其他的配置项(如环境变量)仍然可以在 app.json 中继续生效。

app.config.js和eas.json配置环境变量的关联

我用的是公共环境变量 (EXPO_PUBLIC_*)模式,用process.env.*调用,如改用app.config.js 的extra配置,那么原来eas.json的配置还需要吗?代码调用方式还是process.env吗?

答案如下:

如果你将环境变量配置在 app.config.jsextra 字段中,那么 eas.json 中的 env 配置仍然是有用的,但是 你需要改变代码中对环境变量的调用方式。下面是详细的解释。

1. eas.json 配置的作用

eas.json 中的 env 配置决定了 构建时需要注入哪些环境变量。这些环境变量会通过 process.env 注入到你的构建环境中。在你使用 app.config.js 时,eas.jsonenv 配置仍然非常重要,因为它确保了在构建时,环境变量能够被正确地提供给 Expo 项目的配置文件(app.config.js)。

当你在 eas.json 中配置环境变量时,在构建过程中这些变量会自动加载到 process.env 上。例如:

{
"build": {
"production": {
"env": {
"EXPO_PUBLIC_API_URL": "https://example.com",
"EXPO_PUBLIC_API_KEY": "your-api-key"
}
}
}
}

在 EAS Build 过程中,process.env.EXPO_PUBLIC_API_URLprocess.env.EXPO_PUBLIC_API_KEY 会被注入。

2. 使用 app.config.jsextra 字段

如果你在 app.config.js 中使用 extra 来动态传递环境变量,那么你可以利用 process.env 读取这些变量,并将它们传递到 Expo 的配置中。这样做的好处是,你可以在 extra 中集中管理所有你需要的环境变量,并通过 expo-constants 访问它们。

例如,app.config.js 文件可以这样写:

export default ({ config }) => {
return {
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
apiKey: process.env.EXPO_PUBLIC_API_KEY
}
};
};

这里的 process.env.EXPO_PUBLIC_API_URLprocess.env.EXPO_PUBLIC_API_KEY 是从 eas.json 中的 env 配置中获取的。

3. 如何在代码中访问这些变量

一旦你在 app.config.js 中配置了 extra 字段,Expo 会将这些 extra 数据注入到应用中,你可以通过 expo-constants 访问它们,而不再需要直接使用 process.env

例如:

import Constants from 'expo-constants';

const apiUrl = Constants.expoConfig.extra.apiUrl;
const apiKey = Constants.expoConfig.extra.apiKey;

console.log(apiUrl, apiKey);

通过这种方式,环境变量从 extra 中获取,而不是直接从 process.env 获取。

4. 代码调用方式:从 process.env 转变为 Constants.expoConfig.extra

  • 原先的调用:

    如果你直接从 process.env 读取环境变量,代码可能是这样的:

    const apiUrl = process.env.EXPO_PUBLIC_API_URL;
    const apiKey = process.env.EXPO_PUBLIC_API_KEY;
  • 修改后的调用:

    当你将环境变量移到 app.config.jsextra 中后,代码需要改成:

    import Constants from 'expo-constants';

    const apiUrl = Constants.expoConfig.extra.apiUrl;
    const apiKey = Constants.expoConfig.extra.apiKey;

5. eas.json 中的配置是否还需要?

是的,eas.json 中的配置依然需要eas.json 中的 env 配置是 构建时 提供环境变量的地方,供 process.env 在构建时使用。即使你将环境变量放到了 app.config.jsextra 中进行管理,eas.jsonenv 配置仍然是注入这些变量的来源。

6. 完整流程

  1. eas.json 中配置环境变量:这些变量将在构建时注入到 process.env

    {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_API_URL": "https://example.com",
    "EXPO_PUBLIC_API_KEY": "your-api-key"
    }
    }
    }
    }
  2. app.config.js 中使用 extra 字段:将 process.env 中的环境变量传递到 expo 配置中。

    export default ({ config }) => {
    return {
    ...config,
    extra: {
    apiUrl: process.env.EXPO_PUBLIC_API_URL,
    apiKey: process.env.EXPO_PUBLIC_API_KEY
    }
    };
    };
  3. 在代码中使用 expo-constants 访问环境变量

    import Constants from 'expo-constants';

    const apiUrl = Constants.expoConfig.extra.apiUrl;
    const apiKey = Constants.expoConfig.extra.apiKey;

    console.log(apiUrl, apiKey);

总结

  • eas.json 中的 env 配置仍然需要,因为这是你定义环境变量的地方,它们会在构建时注入。
  • 代码调用方式需要改变:如果你使用 app.config.jsextra 字段管理环境变量,代码中应通过 Constants.expoConfig.extra 来访问这些变量,而不是直接使用 process.env

这样做的好处是,你可以在应用中更明确地管理环境变量,并避免直接依赖 process.env,提供更清晰的结构和更好的可维护性。

我们是不是更推荐app.config.js配置方式?

使用 app.config.js 配置 extra 字段来管理环境变量有多个好处,尤其是在 Expo 或 React Native 项目中。这种方式为项目带来了更多的灵活性、可维护性和安全性。以下是使用 extra 字段配置环境变量的一些主要好处:

1. 集中管理环境变量

将环境变量集中在 app.config.js 文件的 extra 字段中,可以使项目的配置更加统一和清晰。

  • 好处:所有的环境变量都在一个地方定义和管理,无需在不同的文件中查找,避免了环境变量分散在代码各处的混乱。

  • 示例

    export default ({ config }) => {
    return {
    ...config,
    extra: {
    apiUrl: process.env.EXPO_PUBLIC_API_URL,
    apiKey: process.env.EXPO_PUBLIC_API_KEY
    }
    };
    };

2. 灵活处理不同环境的配置

app.config.js 是一个 JavaScript 文件,因此你可以根据不同的构建环境(如开发、生产等)动态生成不同的配置。这可以让你更灵活地控制环境变量。

  • 好处:可以根据构建环境(如 developmentproduction)动态生成不同的 extra 配置,避免硬编码。

  • 示例

    export default ({ config }) => {
    const isProduction = process.env.NODE_ENV === 'production';

    return {
    ...config,
    extra: {
    apiUrl: isProduction
    ? process.env.EXPO_PUBLIC_API_URL_PROD
    : process.env.EXPO_PUBLIC_API_URL_DEV,
    apiKey: process.env.EXPO_PUBLIC_API_KEY
    }
    };
    };

    在这个例子中,apiUrl 会根据环境自动选择开发或生产的 URL。

3. 便于访问环境变量

Expo 提供了 expo-constants 模块,可以让你在应用中轻松访问 extra 中的配置。这比直接依赖 process.env 更加直观和安全。

  • 好处:通过 Constants.expoConfig.extra 访问环境变量比直接使用 process.env 更加安全,有助于避免泄露不必要的信息,并且减少与 Node.js 环境的耦合性。

  • 示例

    import Constants from 'expo-constants';

    const apiUrl = Constants.expoConfig.extra.apiUrl;
    const apiKey = Constants.expoConfig.extra.apiKey;

    console.log(apiUrl, apiKey);

    通过 extra 字段传递的环境变量可以很方便地在应用中获取,并且 Expo 会注入这些变量,简化了访问流程。

4. 避免在客户端暴露敏感信息

Expo 的 extra 字段是专门用于传递客户端需要使用的公共配置。与直接使用 process.env 不同,extra 提供了一种明确的方式来管理哪些变量是需要暴露给客户端的。

  • 好处:你可以更清楚地管理哪些变量是安全的、可以暴露给客户端的,而哪些变量不应该暴露。使用 process.env 时,所有变量都可能在客户端暴露,但通过 extra,你可以有选择性地传递需要的变量。

5. 增强安全性和可维护性

通过 app.config.jsextra 字段,可以更容易地控制哪些变量是公开的。Expo 中建议将公开的环境变量以 EXPO_PUBLIC_ 开头,这样可以明确哪些变量是可以暴露给客户端的,而不需要担心敏感信息被意外泄露。

  • 好处:通过 extra 字段,你可以更安全地管理环境变量。你可以确保只有明确标记为 EXPO_PUBLIC_ 的变量会被加入到 extra 中,而不会误将敏感信息暴露给客户端。

  • 示例

    export default ({ config }) => {
    return {
    ...config,
    extra: {
    apiUrl: process.env.EXPO_PUBLIC_API_URL, // 公共 API 地址
    apiKey: process.env.EXPO_PUBLIC_API_KEY // 公共 API 密钥
    }
    };
    };

6. 避免在客户端直接使用 process.env

在 React Native 环境中,process.env 并不是像在 Node.js 环境中那样天然存在的。在 Expo 中,直接使用 process.env 可能会导致一些无法预料的问题,尤其是在不同的构建环境中(比如开发、测试和生产环境)。

  • 好处:使用 extra 字段可以避免直接依赖 process.env,这种方式更符合 Expo 和 React Native 的最佳实践,并且可以更好地处理跨平台的环境配置。

7. 简化环境变量的调试

通过 app.config.js 中的 extra 字段,你可以清楚地看到在不同环境下到底哪些变量被注入到了项目中。这比直接依赖 process.env 更加直观。

  • 好处:在调试时,你可以通过 console.log 或其他方式查看 app.config.js 中的 extra 配置,确保环境变量正确注入。

  • 示例

    console.log("Extra config:", Constants.expoConfig.extra);

    通过这种方式,你可以轻松检查 extra 配置内容,调试环境变量的问题。

8. 与 EAS Build 配合良好

当你使用 EAS Build(Expo Application Services)进行构建时,eas.json 中的环境变量配置会自动注入到 process.env 中。而 app.config.jsextra 字段可以利用这些环境变量来生成最终的配置。

  • 好处extra 字段与 EAS Build 配置(如 eas.json)无缝集成,你可以在 eas.json 中配置生产或开发环境的变量,然后通过 app.config.js 动态读取这些变量,让构建更加灵活。

  • 示例

    eas.json 中:

    {
    "build": {
    "production": {
    "env": {
    "EXPO_PUBLIC_API_URL": "https://production.example.com",
    "EXPO_PUBLIC_API_KEY": "prod-api-key"
    }
    },
    "development": {
    "env": {
    "EXPO_PUBLIC_API_URL": "https://dev.example.com",
    "EXPO_PUBLIC_API_KEY": "dev-api-key"
    }
    }
    }
    }

    app.config.js 中:

    export default ({ config }) => {
    return {
    ...config,
    extra: {
    apiUrl: process.env.EXPO_PUBLIC_API_URL,
    apiKey: process.env.EXPO_PUBLIC_API_KEY
    }
    };
    };

    当你在不同环境下构建时(如 productiondevelopment),EAS Build 会根据 eas.json 中的配置自动注入正确的环境变量。

总结

使用 app.config.jsextra 字段来管理环境变量的主要好处包括:

  1. 集中管理:所有环境变量在一个位置统一配置,便于维护。
  2. 灵活性:可以根据不同环境动态设置不同的 extra 配置。
  3. 易于访问:通过 Constants.expoConfig.extra 方便地访问环境变量,避免直接使用 process.env
  4. 增强安全性:明确哪些变量是安全的、可以暴露给客户端的,避免敏感信息泄露。
  5. 简化调试:更容易调试和验证环境变量的注入情况。
  6. 与 EAS Build 集成良好:可以无缝结合 EAS Build 的环境变量配置。

通过这些好处,你可以更好地管理项目中的环境变量,提升项目的可维护性和安全性。

注意,事实证明上述app.config.js的方式只对iOS生效。 而且iOS中也不时出现Constant.expoConfig为undefined的情况,报错:Error: expo-linking needs access to the expo-constants manifest (app.json or app.config.js) to determine what URI scheme to use. Setup the manifest and rebuild 似乎最稳定的方法还是const revenueCatApiKeyIos = process.env.EXPO_PUBLIC_REVENUE_CAT_API_KEY_IOS, 注意如果用解构语法,还是会出错,就是读不出,Android尤为严重。 2024-10-23

附加

destructuring assignment 解构语法获取process.env会得到undefined。 以为是我才遇到,其实网上有讨论。 结论就是:Dont't use destructuring in process.env in most of time.