Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Cannot use env data in dynamic configuration #2782

Closed
RedMickey opened this issue Oct 13, 2020 · 9 comments
Closed

Cannot use env data in dynamic configuration #2782

RedMickey opened this issue Oct 13, 2020 · 9 comments
Assignees
Labels
help wanted Extra attention is needed stale

Comments

@RedMickey
Copy link
Contributor

Hello,
I am a maintainer of React Native Tools VS Code extension. The extension is used for debugging React Native (including Expo) applications.

Description

We received an issue with usage of env variables in dynamic configuration. Then we tried to reproduce it on a plain Expo project running it from the terminal and we also got an error. In the project we use the babel-plugin-dotenv-import package to access env variables.

We have already faced a similar problem before and proposed a fix for it in this PR.

Expected Behavior

It would be great to have an opportunity to use env variables in dynamic configuration as it worked earlier.

Observed Behavior

When we start a project from the terminal using the expo start, we get the following error:
Screen Shot 2020-10-13 at 08 53 27

We found out that this problem arose since @expo/xdl@58.0.4 package after the cf63ad0 commit. We consider that the problem could be in the config file compilation here. We think so, because according to the original error it cannot use @env module:

'MODULE_NOT_FOUND'

'Cannot find module '@env'\nRequire stack:\n- /Users/user/Documents/test_react/Expo/myNewProject039ex/app.config.ts\n- /Users/user/Documents/vscode-react-native-extension/original/vscode-react-native-3/vscode-react-native/node_modules/@expo/config/build/evalConfig.js\n- /Users/user/Documents/vscode-react-native-extension/original/vscode-react-native-3/vscode-react-native/node_modules/@expo/config/build/getConfig.js\n- /Users/user/Documents/vscode-react-native-extension/original/vscode-rea…/vscode-react-native-3/vscode-react-native/src/extension/commandPaletteHandler.js\n- /Users/user/Documents/vscode-react-native-extension/original/vscode-react-native-3/vscode-react-native/src/extension/rn-extension.js\n- /Users/user/Documents/Visual Studio Code.app/Contents/Resources/app/out/vs/loader.js\n- /Users/user/Documents/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-amd.js\n- /Users/user/Documents/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-fork.js'

But it used to work properly when a separate process with @babel/register was used.

Environment

  System:
    OS: macOS 10.15.7
    CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
    Memory: 347.30 MB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 10.19.0 - ~/.nvm/versions/node/v10.19.0/bin/node
    Yarn: 1.22.0 - /usr/local/bin/yarn
    npm: 6.13.4 - ~/.nvm/versions/node/v10.19.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.8.4 - /usr/local/bin/pod
    Gradle: 5.5.1 - /usr/local/bin/gradle
    Homebrew: 2.5.2 - /usr/local/bin/brew
    pip3: 20.0.2 - /usr/local/bin/pip3
    RubyGems: 3.0.3 - /usr/bin/gem
  Utilities:
    CMake: 3.16.1 - /usr/local/bin/cmake
    Make: 3.81 - /usr/bin/make
    GCC: 4.2.1 - /usr/bin/gcc
    Git: 2.23.0 - /usr/local/bin/git
    Clang: 1200.0.32.2 - /usr/bin/clang
    Subversion: 1.10.4 - /usr/bin/svn
  Servers:
    Apache: 2.4.41 - /usr/sbin/apachectl
  Virtualization:
    Docker: 19.03.1 - /usr/local/bin/docker
  SDKs:
    iOS SDK:
      Platforms: iOS 14.0, DriverKit 19.0, macOS 10.15, tvOS 14.0, watchOS 7.0
    Android SDK:
      API Levels: 25, 27, 28, 29
      Build Tools: 23.0.1, 25.0.1, 25.0.2, 27.0.3, 28.0.3, 29.0.0, 29.0.1, 29.0.2
      System Images: android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
  IDEs:
    Android Studio: 3.6 AI-192.7142.36.36.6241897
    Nano: 2.0.6 - /usr/bin/nano
    VSCode: 1.50.0 - /usr/local/bin/code
    Vim: 8.1 - /usr/bin/vim
    Xcode: 12.0.1/12A7300 - /usr/bin/xcodebuild
  Languages:
    Bash: 3.2.57 - /bin/bash
    Java: 1.8.0_222 - /usr/bin/javac
    Perl: 5.18.4 - /usr/bin/perl
    PHP: 7.3.11 - /usr/bin/php
    Python: 2.7.16 - /usr/bin/python
    Python3: 3.8.3 - /usr/local/bin/python3
    Ruby: 2.6.3 - /usr/bin/ruby
  Databases:
    SQLite: 3.28.0 - /usr/bin/sqlite3
  Browsers:
    Chrome: 86.0.4240.80
    Edge: 86.0.622.38
    Firefox: 75.0
    Safari: 14.0

Expo SDK version: 39

Reproducible Demo

  1. Create a plain Expo project

  2. Add the babel-plugin-dotenv-import package to the project and do all the preparation written in the Usage guide

  3. Add app.config.ts file to the project as written here. Here is our config file:

    import { ExpoConfig, ConfigContext } from '@expo/config';
    import {TEST1, TEST2} from "@env";
    
    export default ({ config }: ConfigContext): ExpoConfig => {
        console.log(TEST2);
        return {
            extra: {
                testConf: TEST1,
            },
            name: config.name || "name",
            slug: config.slug || "slug",
        };
    };
    
  4. Create a .env file, e.g.:

    TEST1=test1
    TEST2=123123
    
  5. Start the project using the expo start command

@superandrew
Copy link

watching this issue, it stopped working suddenly

@superandrew
Copy link

anyone could point me on how to restore @expo/xdl@58.0.3 or less in order to have the possibility of reading the configuration dynamically?

@EvanBacon EvanBacon self-assigned this Oct 13, 2020
@EvanBacon
Copy link
Contributor

EvanBacon commented Oct 13, 2020

I'd imagine the issue is related to the more stringent rules used in the babel transform:

This recent change seems related to the PR you originally proposed 0464f6c

@brentvatne
Copy link
Member

brentvatne commented Oct 20, 2020

hi there! i discussed this with @EvanBacon, here's a summary:

why babel-plugin-dotenv-import isn't working with app.config.js anymore

we stopped using the project's babel config for transpiling the app config because the environment that your app code runs in is dramatically different from the environment that the app config code runs in, and also many of the transforms that you need for your app may not be needed for your app config. it's easy to get into a state where some babel plugin you use in your react app in javascript core on an ios and android device will produce code that does not run in the expo-cli environment in node. so we use @expo/babel-preset-cli instead. we think this is the right choice even if it is unintuitive in some situations like this. but i think we do need to document this.

alternatives you can use now

  • you can use direnv to set environment variables and then pass those through to your app using app.config.js.
  • you can set up your own transpilation pipeline to transpile your config to app.config.js using the babel config of your choice.

possible future solutions

  • we could pass in the envName option to babel when transforming the config. we should only use the project babel config if the config env is provided. this would allow developers to do something like this:
{
  "env": {
    "config": {
       // ...
     },
    "development": {
       // ...
    },
    "production": {
      // ...
    }
  }
}
  • support a separate babel config file used for app config, eg: app.config.babel.js

if anyone wants to take a shot at one of these solutions (i prefer the envName option) it would be appreciated. if you have other ideas, let us know!

@brentvatne brentvatne added the help wanted Extra attention is needed label Oct 20, 2020
@superandrew
Copy link

superandrew commented Oct 23, 2020

thank you @brentvatne

Correct me if I'm wrong, I should use direnv for the appconfig, and a different approach (e.g. dotenv) for runtime logic?

Because direnv does't seem to work when I try to load a dinamic tab bar in environment.ts

export const mainNavigator = () =>require(./tenant_configs/${process.env.TENANCY_NAME}.MainTabNavigator).default();

Failed building JavaScript bundle.
environment.ts: environment.ts:Invalid call at line 49: require("./tenant_configs/" + process.env.TENANCY_NAME + ".MainTabNavigator")

also, would this method require special care when building in order for the variables to be hooked?

@marcor-ts
Copy link

Hi everyone
@brentvatne I'm very intrested about your second alternative but I have no idea where to start.
Could you kindly give me some hints?
Thanks

@brentvatne
Copy link
Member

Correct me if I'm wrong, I should use direnv for the appconfig, and a different approach (e.g. dotenv) for runtime logic?

correct @superandrew! something like babel-plugin-inline-dotenv will inline your env vars at build time, which is the only sensible thing to do with them on the front end because there is no process.env environment that you control in that context (the user's device).

with respect to this:

export const mainNavigator = () =>require(./tenant_configs/${process.env.TENANCY_NAME}.MainTabNavigator).default();

i'm not familiar what technique you would use to make this work. in metro your imports need to all be static, it's not like node where you can define the import string at runtime. perhaps you can get this working with babel but i have never explored this so i can't comment.


@marcor-ts - you can refer to #2786 - notice that you can control the options that are passed in to babel there. you'd need to check if there is some config file with the specific name we choose to use (above i said app.config.babel.js but i'd prefer a better name although i don't have one).

@github-actions
Copy link

This issue is stale because it has been open for 60 days with no activity. If there is no activity in the next 7 days, the issue will be closed.

@github-actions github-actions bot added the stale label Apr 12, 2022
@EvanBacon
Copy link
Contributor

We don't plan on exposing a custom babel config for the app.config.js file. You can set up your own pipeline for transpiling the app.config.js using something like babel directly. We similarly recommend using ts-node locally for more advanced TypeScript support.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help wanted Extra attention is needed stale
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants