Skip to content

Support redirects in devServer #906

Closed
@ceopaludetto

Description

@ceopaludetto

Description

Hi, I'm currently developing an application with repack and expo (with CNG and router), in order to make it work I had to revert some stuff that expo does, which basically is:

  • Replacing expo cli with rn cli (to support development)
  • Removing CLI_PATH and BUNDLE_COMMAND from ios and android targets (to support release)
  • Changing jsMainBundle from .expo/.virtual-metro-entry to index (in AppDelegate.mm and MainApplication.kt)
  • Added some environment variables via define plugin:
 new DefinePlugin({
  "__DEV__": JSON.stringify(mode === "development"),
  "process.env.EXPO_BASE_URL": JSON.stringify(""),
  "process.env.EXPO_OS": JSON.stringify(platform),
  "process.env.EXPO_PROJECT_ROOT": JSON.stringify(resolve(".")),
  "process.env.EXPO_ROUTER_ABS_APP_ROOT": JSON.stringify(resolve("./src/screens")),
  "process.env.EXPO_ROUTER_APP_ROOT": JSON.stringify("~/screens"),
  "process.env.EXPO_ROUTER_IMPORT_MODE": JSON.stringify("sync"),
  "process.env.NODE_ENV": JSON.stringify(mode),
})

Everything works (both debug and release builds). But recently expo added an override in ios that enforce the jsMainBundle to be .expo/.virtual-metro-entry, so in order to fix that I've patched node_modules/expo-modules-core/ios/AppDelegates/ExpoAppInstance:

diff --git a/ios/AppDelegates/ExpoAppInstance.swift b/ios/AppDelegates/ExpoAppInstance.swift
index 8dae3f001009f98ff100c162131d59a915a68e73..b1fe5b8ed69e6e4090c5d961b6990761d873ee0d 100644
--- a/ios/AppDelegates/ExpoAppInstance.swift
+++ b/ios/AppDelegates/ExpoAppInstance.swift
@@ -14,7 +14,7 @@ open class ExpoAppInstance: RCTAppDelegate {
 
   open override func bundleURL() -> URL? {
 #if DEBUG
-    return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
+    return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
 #else
     return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
 #endif

This solution works but it kinda sucks (personally I don't like to patch packages).

Suggested solution

I think that repack could support some sort of redirect in devServer, this will dramatically reduce my setup to make it work. A simple redirect from .expo/.virtual-metro-entry to index with the same query params should fix it. What you think?

Additional context

My expo configuration plugin just for reference (if anyone came across this issue):

import type { ExpoConfig } from "expo/config";

import { withAppBuildGradle, withAppDelegate, withMainApplication, withXcodeProject } from "expo/config-plugins";

export default function plugin(expo: ExpoConfig) {
  let res = expo;

  // iOS
  res = withXcodeProject(res, async (configuration) => {
    const xcodeProject = configuration.modResults;
    const bundleReactNativeCodeAndImagesBuildPhase = xcodeProject.buildPhaseObject(
      "PBXShellScriptBuildPhase",
      "Bundle React Native code and images",
    );

    if (!bundleReactNativeCodeAndImagesBuildPhase)
      return configuration;

    const script = JSON.parse(bundleReactNativeCodeAndImagesBuildPhase.shellScript);
    const patched = script
      .replace(/if \[\[ -z "\$CLI_PATH" \]\]; then[\s\S]*?fi\n?/g, `export CLI_PATH="$("$NODE_BINARY" --print "require('path').dirname(require.resolve('@react-native-community/cli/package.json')) + '/build/bin.js'")"`)
      .replace(/if \[\[ -z "\$BUNDLE_COMMAND" \]\]; then[\s\S]*?fi\n?/g, "");

    bundleReactNativeCodeAndImagesBuildPhase.shellScript = JSON.stringify(patched);
    return configuration;
  });

  res = withAppDelegate(res, async (configuration) => {
    const appDelegate = configuration.modResults.contents;
    configuration.modResults.contents = appDelegate.replace(".expo/.virtual-metro-entry", "index");

    return configuration;
  });

  // Android
  res = withMainApplication(res, async (configuration) => {
    const mainApplication = configuration.modResults.contents;
    configuration.modResults.contents = mainApplication.replace(".expo/.virtual-metro-entry", "index");

    return configuration;
  });

  res = withAppBuildGradle(res, async (config) => {
    const buildGradle = config.modResults.contents;
    const patched = buildGradle.replace(/cliFile.*/, "").replace(/bundleCommand.*/, "bundleCommand = \"bundle\"");

    config.modResults.contents = patched;
    return config;
  });

  return res;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:newNew issue, not reviewed by the team yet.type:featureProposal or idea for a new feature or enhancement.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions