Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting "Failed to resolve plugin for module "expo-community-flipper" only on production build #25

Open
giacomoalonzi opened this issue Sep 13, 2022 · 12 comments
Labels
investigating Ongoing conversation about the issue SDK 46 Affects plugin in Expo SDK 46 SDK 47 Affects plugin in Expo SDK 47

Comments

@giacomoalonzi
Copy link

giacomoalonzi commented Sep 13, 2022

Hello, I'm getting this when I try to build for production with EAS build, even locally.
All works fine for staging or development builds.

[INSTALL_DEPENDENCIES] [4/4] Building fresh packages...
[READ_PACKAGE_JSON] Using package.json:
[READ_PACKAGE_JSON] {
...
[READ_APP_CONFIG] 
PluginError: Failed to resolve plugin for module "expo-community-flipper" relative to "/var/folders/86/hpx16y154yvd6kndrx_nxrqc0000gn/T/eas-build-local-nodejs/50a8c532-ea70-4801-8a62-6e3bab46ac2b/build"

I've spent a couple of hours, prebuild is ok but the build don't. Can't figure out why.

Expo SDK 46
eas-cli/2.1.0
expo-cli/6.0.5

Thanks

@giacomoalonzi giacomoalonzi changed the title Getting "Failed to resolve plugin for module "expo-community-flipper"" only on production build Getting "Failed to resolve plugin for module "expo-community-flipper" only on production build Sep 13, 2022
@jakobo
Copy link
Owner

jakobo commented Sep 14, 2022

Hey, thanks for reporting this! Can you share your app.json? Redactions are okay, I just need to see how the plugin is being included.

@jakobo jakobo added investigating Ongoing conversation about the issue SDK 46 Affects plugin in Expo SDK 46 labels Sep 14, 2022
@giacomoalonzi
Copy link
Author

giacomoalonzi commented Sep 14, 2022

This is my config :) thank you!

require('dotenv').config();
import { ExpoConfig, ConfigContext } from '@expo/config';

export default ({ config }: ConfigContext): ExpoConfig => ({
  ...config,
  name: 'My App',
  slug: 'myapp',
  scheme: 'myapp',
  version: '0.14.0',
  owner: '---',
  orientation: 'portrait',
  icon: './assets/icons/1024.png',
  userInterfaceStyle: 'automatic',
  assetBundlePatterns: ['assets/images/*', 'src/assets/images/*'],
  plugins: [
    'react-native-email-link',
    'expo-community-flipper',
    ['./plugins/withPladLinkAndroid.js', 'plaid-link-android'],
    'sentry-expo',
    [
      'expo-notifications',
      {
        color: '#ffffff',
      },
    ],
  ],
  jsEngine: 'hermes',
  splash: {
    image: './assets/splash.png',
    resizeMode: 'contain',
    backgroundColor: '#ffffff',
  },
  runtimeVersion: {
    policy: 'sdkVersion',
  },
  ios: {
    jsEngine: 'jsc',
    supportsTablet: false,
    bundleIdentifier: 'myapp',
    buildNumber: '1',
    googleServicesFile: process.env.GOOGLE_SERVICES_FILES_IOS_PATH,
    associatedDomains: [`applinks:${process.env.UNIVERSAL_LINK_URL}`],
  },
  android: {
    adaptiveIcon: {
      backgroundColor: '#FFFFFF',
      foregroundImage:
        './assets/icons/res/mipmap-xxxhdpi/liv_adaptive_fore.png',
      backgroundImage:
        './assets/icons/res/mipmap-xxxhdpi/liv_adaptive_back.png',
    },
    package: 'myapp',
    versionCode: 6,
    allowBackup: false,
    googleServicesFile: process.env.GOOGLE_SERVICES_FILES_ANDROID_PATH,
    intentFilters: [
      {
        action: 'VIEW',
        autoVerify: true,
        data: [
          {
            scheme: 'https',
            host: process.env.UNIVERSAL_LINK_URL,
            pathPrefix: '/',
          },
          {
            scheme: 'https',
            host: process.env.UNIVERSAL_LINK_URL,
            pathPrefix: '/authorization',
          },
          {
            scheme: 'plaid',
            host: process.env.UNIVERSAL_LINK_URL,
            pathPrefix: '/redirect',
          },
          {
            scheme: 'https',
            host: process.env.UNIVERSAL_LINK_URL,
            pathPrefix: '/goback',
          },
        ],
        category: ['BROWSABLE', 'DEFAULT'],
      },
    ],
  },
  web: {
    favicon: './assets/favicon.png',
    config: {
      firebase: {
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: process.env.FIREBASE_AUTH_DOMAIN,
        projectId: process.env.FIREBASE_PROJECT_ID,
        storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
        appId: process.env.FIREBASE_APP_ID,
        measurementId: process.env.FIREBASE_MEASUREMENT_ID,
      },
    },
  },
  extra: {
    env: process.env.NODE_ENV,
    universalLinkUrl: process.env.UNIVERSAL_LINK_URL,
    sentryDns: process.env.SENTRY_DNS,
    plaidEnv: process.env.PLAID_ENV,
    eas: {
      projectId: 'myprojectid',
    },
    firebase: {
      authDomain: process.env.FIREBASE_AUTH_DOMAIN,
      measurementId: process.env.FIREBASE_MEASUREMENT_ID,
    },

    api: {
      host: process.env.API_HOST,
    },
    google: {
      expoClientId: process.env.GOOGLE_EXPO_CLIENT_ID,
      iosClientId: process.env.GOOGLE_IOS_CLIENT_ID,
      androidClientId: process.env.GOOGLE_ANDROID_CLIENT_ID,
      webClientId: process.env.GOOGLE_WEB_CLIENT_ID,
      secret: process.env.GOOGLE_SECRET,
    },
  },
  hooks: {
    postPublish: [
      {
        file: 'sentry-expo/upload-sourcemaps',
        config: {
          organization: 'liv-carbon-impact',
          project: 'liv-client-app',
          authToken: process.env.SENTRY_AUTH_TOKEN,
        },
      },
    ],
  },
});

@jakobo
Copy link
Owner

jakobo commented Sep 14, 2022

Everything looks right, and we didn't change any entry points going from 45-46. A few things I'd double check:

  1. expo-community-flipper is in your package.json and in the same dependency group as react-native-email-link. It's entirely possible EAS is cleaning up dev dependencies at a step in the build and the flipper code gets cleaned up
  2. It works with the flipper plugin commented out (to make sure it's only this plugin

You're right 😅 this is a weird one, especially since the prebuild works... meaning that locally the plugin's working just fine.

@hirbod
Copy link

hirbod commented Nov 1, 2022

Hey @jakobo,

referring to our conversation on Twitter, here is my Podfile, since you asked for it.

require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")

require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}

platform :ios, podfile_properties['ios.deploymentTarget'] || '12.4'
install! 'cocoapods',
  :deterministic_uuids => false

target 'voozme' do
  use_expo_modules!
  config = use_native_modules!

  use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']

  # Flags change depending on the env values.
  flags = get_default_flags()

  use_react_native!(
    :path => config[:reactNativePath],
# @generated begin expo-community-flipper-isprod - expo prebuild (DO NOT MODIFY) sync-e002ec08de24fbbe5b9a843ae9231b9627b8b9c4

            # https://www.npmjs.com/package/expo-community-flipper
            :production => ENV["PRODUCTION"] == "1" ? true : false,
# @generated end expo-community-flipper-isprod
    :hermes_enabled => flags[:hermes_enabled] || podfile_properties['expo.jsEngine'] == 'hermes',
    :fabric_enabled => flags[:fabric_enabled],
# @generated begin expo-community-flipper-urn - expo prebuild (DO NOT MODIFY) sync-59337f4ef2cee165bd93878dbfd00ddba4d65e67

            # https://www.npmjs.com/package/expo-community-flipper
            :flipper_configuration => ENV['FLIPPER_DISABLE'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled,
# @generated end expo-community-flipper-urn
    # An absolute path to your application root.
    :app_path => "#{Dir.pwd}/.."
  )

  # Uncomment to opt-in to using Flipper
  # Note that if you have use_frameworks! enabled, Flipper will not work
  #
  # if !ENV['CI']
  #   use_flipper!()
  # end

  post_install do |installer|
    react_native_post_install(installer)
    __apply_Xcode_12_5_M1_post_install_workaround(installer)

    # This is necessary for Xcode 14, because it signs resource bundles by default
    # when building for devices.
    installer.target_installation_results.pod_target_installation_results
      .each do |pod_name, target_installation_result|
      target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
        resource_bundle_target.build_configurations.each do |config|
          config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
        end
      end
    end
  end

  post_integrate do |installer|
    begin
      expo_patch_react_imports!(installer)
    rescue => e
      Pod::UI.warn e
    end
  end
end

My error came out of the blue, after I've upgrade 5 packages. I reverted all of them but 2, the issue does still persist. I am suspecting expo-dev-client 1.3.1. Since Expo SDK 47 is out now, I will first give this a try as well.

@hirbod
Copy link

hirbod commented Nov 1, 2022

Small update: the plugin does currently not work SDK 47

@jakobo
Copy link
Owner

jakobo commented Nov 1, 2022

Small update: the plugin does currently not work SDK 47

Yeah. #38 is tracking the remaining sdk47 changes. In sdk47, it appears the expo prebuild template is no longer coming from main. We'll also be able to formally depend on expo/config-plugins with a peer dependency on expo instead to help control versioning.

@jakobo
Copy link
Owner

jakobo commented Nov 1, 2022

My error came out of the blue, after I've upgrade 5 packages. I reverted all of them but 2, the issue does still persist. I am suspecting expo-dev-client 1.3.1. Since Expo SDK 47 is out now, I will first give this a try as well.

For SDK46, you can use the following strategies to disable Flipper in a production build, completely excising it from your Podfile.

Option 1: app.config.js (forward compatible)

The easiest solution is to switch from app.json to app.config.js which gives you access to the node's process.env. You can then omit the plugin completely based on the existence of an env var. I'm using JS here, but you can also use TypeScript directly by following the expo docs. This creates an opt-in env var for flipper.

// create a plugin configuration w/ blank options that
// is enabeld only if env is set
const expoConfigFlipper =
  process.env.FLIPPER === "1"
    ? [
        [
          "expo-community-flipper",
          {
            // config if required
          },
        ],
      ]
    : [];

/** @type {import('@expo/config-types').ExpoConfig} */
const config = {
  expo: {
    // ...
    plugins: [
      // other plugins
      ...expoConfigFlipper,
    ],
  },
};

module.exports = config;

With this configuration, when you run prebuild / build using FIPPER=1 expo prebuild / FLIPPER=1 expo build, the flipper plugin will be loaded. In all other scenarios including a production build, the plugin won't run and the lines won't be included. Going forward for SDK47, this will be the recommended pattern so that EAS users can manage an env value of their choosing and we can remove some of the ruby conditional logic used in the plugin.

Option 2 (<= SDK46) Opt-Out Build

For SDK 45/46, we do have a manual opt-out which you can try with minimal changes. This method also works for app.json. The configuration supports an ios.enabled flag which can be explicitly set to false and disable the flipper integration. The resulting podfile then mirrors the Podfile generated in a react-native bare app.

{
  "expo": {
    "plugins": [
      [
        "expo-community-flipper",
        {
          "ios": {
            "enabled": false
          }
        }
      ]
    ]
  }
}

Both of the above solutions should be viable for SDK 46, with the config.js option being the forward-looking solution for SDK47. If you make one of these changes, please also include a redacted app.json so we can see if there's a plugin conflict (for example, react-native firebase forces use_frameworks and is incompatible with Flipper.

@jakobo
Copy link
Owner

jakobo commented Nov 9, 2022

For @hirbod and others, I'm linking #42, which has a similar code smell. If you've removed the plugin completely from app.json / app.config.js and the build is still failing then we have a duplicate bug and it's likely something about how react-native looks for packages as part of autolinking in the Podfile.

@jakobo jakobo added the SDK 47 Affects plugin in Expo SDK 47 label Jan 6, 2023
@Nek-
Copy link

Nek- commented Feb 1, 2023

It looks like it's possible to make a fix for it: facebook/flipper#2414 (comment)

I'm sorry I'm new to react native and expo so I cannot make the PR.

@jakobo
Copy link
Owner

jakobo commented Feb 3, 2023

Thanks @Nek-! These changes are a bit more than I'd like to introduce to the plugin, as manually controlling Flipper's pod dependencies rarely ends well.

To make things worse, the linked comment tested on 0.127.0, and there's been 50 releases since then. :( Our expo integration (#41) will help with some of these issues because it'll be managed inside of the build-properties plugin; the same place where use_frameworks and other troublesome pod code is.

@luispuig
Copy link

Option 1: app.config.js (forward compatible)

The easiest solution is to switch from app.json to app.config.js which gives you access to the node's process.env. You can then omit the plugin completely based on the existence of an env var. I'm using JS here, but you can also use TypeScript directly by following the expo docs. This creates an opt-in env var for flipper.

// create a plugin configuration w/ blank options that
// is enabeld only if env is set
const expoConfigFlipper =
  process.env.FLIPPER === "1"
    ? [
        [
          "expo-community-flipper",
          {
            // config if required
          },
        ],
      ]
    : [];

/** @type {import('@expo/config-types').ExpoConfig} */
const config = {
  expo: {
    // ...
    plugins: [
      // other plugins
      ...expoConfigFlipper,
    ],
  },
};

module.exports = config;

Do you think that it will be compatible with the env variables in eas.json?

  "cli": {
    "version": ">= 3.0.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "env": {
        "FLIPPER": "1"
      }
    },
    "development-simulator": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": {
        "simulator": true
      },
      "env": {
        "FLIPPER": "1"
      }
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {},
    "apk": {
      "android": {
        "buildType": "apk"
      }
    }
  },
  "submit": {
    "production": {}
  }
}

@jakobo
Copy link
Owner

jakobo commented Feb 22, 2023

Do you think that it will be compatible with the env variables in eas.json?

Yes, you can use the EAS env properties to control your app.config.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigating Ongoing conversation about the issue SDK 46 Affects plugin in Expo SDK 46 SDK 47 Affects plugin in Expo SDK 47
Projects
None yet
Development

No branches or pull requests

5 participants