MaxAst / expo-share-extension

Expo config plugin for creating iOS share extensions with a custom view.
MIT License
230 stars 8 forks source link

Share Extension won't launch after upgrading to SDK 51 #46

Closed nhuesmann closed 3 weeks ago

nhuesmann commented 2 months ago

Everything was working on SDK 50. I upgraded to SDK 51 using Expo's instructions. The app itself works fine. When I try to launch the share extension, I now get this error:

Screenshot 2024-09-19 at 11 15 55 AM

I have tried:

Note that I am in a monorepo but this has never caused issues before. I simply upgraded from SDK 50 to SDK 51, updating package versions and nothing else, and the issue started occurring.

I have tried launching the share extension on both the iOS simulator as well as my physical device, same issue occurs (debug mode and release mode fail).

Here are relevant files:

metro.config.js

// Learn more https://docs.expo.io/guides/customizing-metro
/**
 * @type {import('expo/metro-config')}
 */
// Sentry replacement
// const { getDefaultConfig } = require('expo/metro-config');
const { getSentryExpoConfig } = require('@sentry/react-native/metro');

const path = require('path');

const projectRoot = __dirname;
const workspaceRoot = path.resolve(__dirname, '../..');

// Sentry replacement
// const config = getDefaultConfig(projectRoot);
const config = getSentryExpoConfig(projectRoot);

config.watchFolders = [workspaceRoot];
config.resolver.nodeModulesPaths = [
  path.resolve(projectRoot, 'node_modules'),
  path.resolve(workspaceRoot, 'node_modules'),
];

config.transformer = { ...config.transformer, unstable_allowRequireContext: true };
// ! HAVE TO USE metro-minify-esbuild BC TERSER WAS BREAKING THE BUILD ENTIRELY!
config.transformer.minifierPath = require.resolve('metro-minify-esbuild');
config.transformer.minifierConfig = {
  drop: ['console'],
};

/**
 * Add support for share.js as a recognized extension to the Metro config.
 * This allows creating an index.share.js entry point for our iOS share extension
 */
config.transformer.getTransformOptions = () => ({
  resolver: {
    sourceExts: [...config.resolver.sourceExts, 'share.js'], // Add 'share.js' as a recognized extension
  },
});

module.exports = config;

index.share.js

// could be any component you want to use as the root component of your share extension's bundle
import { ShareExtension } from 'app/shareExtension';
import { AppRegistry } from 'react-native';

// IMPORTANT: the first argument to registerComponent, must be "shareExtension"
AppRegistry.registerComponent('shareExtension', () => ShareExtension);

index.js

// import 'expo-router/entry';

import { registerRootComponent } from 'expo';
import { ExpoRoot } from 'expo-router';

// Must be exported or Fast Refresh won't update the context
export function App() {
  const ctx = require.context('./app');
  return <ExpoRoot context={ctx} />;
}

registerRootComponent(App);

app.json expo share extension plugin entry

[
        "expo-share-extension",
        {
          "excludedPackages": [
            "expo-asset",
            "expo-av",
            "expo-build-properties",
            "expo-contacts",
            "expo-dev-client",
            "expo-device",
            "expo-font",
            "expo-linear-gradient",
            "expo-location",
            "expo-notifications",
            "expo-router",
            "expo-status-bar",
            "expo-system-ui",
            "expo-updates"
          ],
          "backgroundColor": {
            "red": 255,
            "green": 255,
            "blue": 255,
            "alpha": 0
          }
        }
      ]

package.json for the expo app

{
  "name": "expo-app",
  "version": "1.0.0",
  "main": "index.js",
  "private": true,
  "scripts": {
    ...
  },
  "dependencies": {
    "@babel/runtime": "^7.18.9",
    "@benable/ui": "0.0.1",
    "@fullstory/babel-plugin-annotate-react": "^2.3.0",
    "@fullstory/react-native": "^1.4.2",
    "@gorhom/portal": "^1.0.14",
    "@intercom/intercom-react-native": "^7.2.1",
    "@react-native-async-storage/async-storage": "1.23.1",
    "@react-native-google-signin/google-signin": "^11.0.0",
    "@react-native-masked-view/masked-view": "0.3.1",
    "@react-navigation/elements": "^1.3.22",
    "@react-navigation/native": "^6.1.6",
    "@react-navigation/native-stack": "^6.10.0",
    "@sentry/react-native": "~5.22.0",
    "@shopify/flash-list": "1.7.1",
    "app": "0.0.1",
    "babel-plugin-module-resolver": "^4.1.0",
    "expo": "^51.0.0",
    "expo-apple-authentication": "~6.4.2",
    "expo-application": "~5.9.1",
    "expo-asset": "~10.0.10",
    "expo-av": "~14.0.7",
    "expo-blur": "~13.0.2",
    "expo-build-properties": "~0.12.5",
    "expo-clipboard": "~6.0.3",
    "expo-constants": "~16.0.2",
    "expo-contacts": "~13.0.5",
    "expo-dev-client": "~4.0.26",
    "expo-device": "~6.0.2",
    "expo-font": "~12.0.10",
    "expo-haptics": "~13.0.1",
    "expo-image": "~1.12.15",
    "expo-image-picker": "~15.0.7",
    "expo-linear-gradient": "~13.0.2",
    "expo-linking": "~6.3.1",
    "expo-location": "~17.0.1",
    "expo-notifications": "~0.28.17",
    "expo-router": "~3.5.23",
    "expo-secure-store": "~13.0.2",
    "expo-share-extension": "^1.10.4",
    "expo-splash-screen": "~0.27.5",
    "expo-status-bar": "~1.12.1",
    "expo-system-ui": "~3.0.7",
    "expo-updates": "~0.25.24",
    "expo-web-browser": "~13.0.3",
    "mixpanel-react-native": "^3.0.2",
    "promise": "^8.3.0",
    "qs": "^6.13.0",
    "react": "~18.2.0",
    "react-dom": "~18.2.0",
    "react-native": "0.74.5",
    "react-native-draggable-flatlist": "^4.0.1",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-pager-view": "6.3.0",
    "react-native-reanimated": "~3.10.1",
    "react-native-reanimated-carousel": "^3.5.1",
    "react-native-safe-area-context": "4.10.5",
    "react-native-screens": "3.31.1",
    "react-native-shared-group-preferences": "^1.1.24",
    "react-native-svg": "15.2.0",
    "react-native-tab-view": "^3.5.2",
    "react-native-toast-message": "^2.2.0",
    "react-native-uuid": "^2.0.1",
    "react-native-view-shot": "3.8.0",
    "react-native-web": "~0.19.6",
    "react-native-webview": "13.8.6",
    "react-native-youtube-iframe": "^2.3.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@tamagui/babel-plugin": "1.100.0",
    "babel-plugin-transform-inline-environment-variables": "^0.4.4",
    "esbuild": "^0.20.2",
    "metro-minify-esbuild": "^0.2.0",
    "typescript": "~5.3.3"
  }
}
MaxAst commented 2 months ago

it should work fine, I'm using it with v51. Have you done a npx expo prebuild --platform ios --clean?

MaxAst commented 2 months ago

@nhuesmann any luck?

nhuesmann commented 1 month ago

@MaxAst so sorry I didn't see your reply until now, and thanks so much for your reply. I was able to get it working, but it still doesn't totally make sense why. I had a config file that both the app and share extension use, and that config file imported the expo-updates library. What is strange is that this wasn't causing any issues for the share extension when running on SDK 50. However, in SDK 51, if I changed things around and got rid of all expo-updates related imports, the share extension runs again. Nothing changed in my code, and I do run a clean prebuild before every build I create. So I think there's a potential solution if I rework some code to not have any shared expo-updates imports, but it's just still a little confusing why this would only be a problem on SDK 51.

MaxAst commented 1 month ago

The pod for expo-updates is automatically removed by expo-share-extension, because the setup for enabling EAS updates would have been a lot of work. So I guess it makes sense that JS that depends on expo-updates would fail when run in the share extension

MaxAst commented 1 month ago

relevant section in the repo: https://github.com/MaxAst/expo-share-extension/blob/main/plugin/src/withPodfile.ts#L39-L43

MaxAst commented 3 weeks ago

will close this for now, lmk if you need further help with this