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

Compatibility with Expo apps #8

Open
bboydflo opened this issue Aug 8, 2022 · 34 comments
Open

Compatibility with Expo apps #8

bboydflo opened this issue Aug 8, 2022 · 34 comments
Labels
Expo Expo - Isn't officially supported yet. On Hold Cannot be resolved at the moment. P4 No action needed at this time.

Comments

@bboydflo
Copy link

bboydflo commented Aug 8, 2022

hi, thanks for this package. I am trying to use it in an expo app. and I got this error: TypeError: null is not an object (evaluating 'FPStaticServer.start'

Any idea what I am doing wrong? Here is my code:

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, SafeAreaView } from "react-native";
import { WebView } from 'react-native-webview';
import StaticServer from "@dr.pogodin/react-native-static-server";
import { useEffect, useRef, useState } from 'react';

export default function App() {
  // const [uri] = useState("https://google.com");
  const server = useRef(new StaticServer(5555, "./assets", { localOnly: true, keepAlive: true })).current;
  const [uri] = useState(`http://localhost:${server.port}`);

  useEffect(() => {
    server.start().then((url) => {
      console.log("Serving at URL", url);
    });

    () => {
      // Stop the server
      server.stop();
    }
  }, []);

  return (
    <SafeAreaView style={styles.container}>
      <WebView
        style={styles.container}
        originWhitelist={["*"]}
        source={{ uri }}
        cacheEnabled={true}
        cacheMode={"LOAD_CACHE_ONLY"}
        limitsNavigationsToAppBoundDomains={true}
      />
      <StatusBar style="auto" />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

Here is some output in my logs:

TypeError: null is not an object (evaluating 'FPStaticServer.start')

This error is located at:
    in App (created by ExpoRoot)
    in ExpoRoot
    in RCTView (created by View)
    in View (created by AppContainer)
    in DevAppContainer (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:95:4 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:141:19 in handleException
at node_modules/react-native/Libraries/Core/ReactFiberErrorDialog.js:52:4 in showErrorDialog
at node_modules/react-native/Libraries/ReactNative/renderApplication.js:80:4 in renderApplication
at node_modules/react-native/Libraries/ReactNative/AppRegistry.js:119:25 in runnables.appKey.run
at node_modules/react-native/Libraries/ReactNative/AppRegistry.js:213:4 in runApplication

TypeError: null is not an object (evaluating 'FPStaticServer.start')

This error is located at:
    in App (created by ExpoRoot)
    in ExpoRoot
    in RCTView (created by View)
    in View (created by AppContainer)
    in DevAppContainer (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:95:4 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:141:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/expo/build/errors/ExpoErrorManager.js:25:19 in errorHandler
at node_modules/expo/build/errors/ExpoErrorManager.js:30:24 in <anonymous>
at node_modules/expo-error-recovery/build/ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0

And below are some expo logs:

IMG_C1EF1CFC4289-1

@birdofpreyru
Copy link
Owner

Hi @bboydflo , a quick feedback here.

  1. Which version of the library do you use, and do you have the new react-native architecture (Turbo Modules) enabled? My best guess is that you used the latest version with Turbo Modules, and it seems I really need to test it myself and fix something. It seems that at this point FPStaticServer evaluates to null in your case (instead of the native module interface), probably you can try to edit that place directly inside your node_modules and check what branch is executed, and why is it going wrong.

  2. Looking at your code,

     const server = useRef(new StaticServer(5555, "./assets", { localOnly: true, keepAlive: true })).current;

    this line is not a good idea, I believe effectively you create an instance of StaticServer (the default reference value) on each re-render of App, although only the first of them is recorded in the ref. In you current code you don't access the server instance outside the effect hook at all, so no need for the reference altogether. Otherwise, you better do:

    const serverRef = useRef();
    if (!serverRef.current) serverRef.current = new StaticServer(5555, "./assets", { localOnly: true, keepAlive: true });
    const server = serverRef.current;

@bboydflo
Copy link
Author

bboydflo commented Aug 8, 2022

Hey, thanks for your reply.

  1. I don't think I have Turbo Modules enabled as I am trying to use react native via expo.dev
  2. probably you're right 👍 I have also fixed that.

Will try to see how/if I can enable Turbo Modules with expo.

@birdofpreyru
Copy link
Owner

@bboydflo , I actually meant it should work without Turbo Modules (at least works for me), rather then with them :) Though, I haven't tried it with expo. Agh... also all my projects I use it are JS and not TS. Probably, there is some minor mistake in TS, or something particular about TS config in expo, which makes FPStaticServer null, instead of the module instance.

@bboydflo
Copy link
Author

bboydflo commented Aug 9, 2022

Could be. I realized that I also had another webpack-dev-server running in another tmux window which might have an effect on the current expo app. Will try again with a simple js project as well.

@birdofpreyru
Copy link
Owner

birdofpreyru commented Aug 10, 2022

Hey @bboydflo , I double-checked it indeed does not work in an expo app out of the box, and in my current understanding it is just expo not supporting custom react-native libraries, which rely on native code, unless you build and deploy the resulting expo app in a special way.

See Adding custom native code to Expo guide.

I don't know, whether something can be done in a RN library to make it Expo-friendly, and at this time it is beyond my interests and capacity to figure it out myself.

@birdofpreyru birdofpreyru changed the title TypeError: null is not an object (evaluating 'FPStaticServer.start' Compatibility with Expo apps Aug 10, 2022
@birdofpreyru birdofpreyru added the On Hold Cannot be resolved at the moment. label Aug 10, 2022
@bboydflo
Copy link
Author

thanks! will try it with crate react native app instead

@viljark
Copy link

viljark commented Aug 11, 2022

Hi @bboydflo and @birdofpreyru, this library can be used with Expo, but you need to use expo prebuild so that the library's native dependencies would be linked and Pods installed.

Also when using prebuild, you can use config plugins to customize your project from JavaScript without ever needing to directly modify Xcode or Android Studio projects. From my testing so far, it seems you don't need a config plugin for this library.

More info:
https://github.com/expo/fyi/blob/main/prebuilding.md
https://docs.expo.dev/workflow/customizing/
https://docs.expo.dev/development/getting-started/

birdofpreyru added a commit that referenced this issue Aug 11, 2022
@birdofpreyru birdofpreyru added the P4 No action needed at this time. label Aug 11, 2022
@QuyetAQ
Copy link

QuyetAQ commented Oct 27, 2022

image
I got the following error, can you check it for me? @birdofpreyru

@birdofpreyru
Copy link
Owner

I guess ./assets does not point to the folder you think it points to, when resolved internally. Better pass in the correct absolute path, or double check where it ends up pointing to.

@QuyetAQ
Copy link

QuyetAQ commented Oct 28, 2022

I guess ./assets does not point to the folder you think it points to, when resolved internally. Better pass in the correct absolute path, or double check where it ends up pointing to.

I put source file html in here
/android/app/src/main/assets/index.html
seems this path is not correct?

@birdofpreyru
Copy link
Owner

I think, it is not. It should be a path on the target device, and if you read README carefully, it uses react-native-fs library to figure out correct path for files there, and probably to move them to the folder the server can read.

@QuyetAQ
Copy link

QuyetAQ commented Oct 29, 2022

I think, it is not. It should be a path on the target device, and if you read README carefully, it uses react-native-fs library to figure out correct path for files there, and probably to move them to the folder the server can read.

Thank you, I'm done, however it takes a few seconds to move file & start the server

@lovetingyuan
Copy link

same problem, const FPStaticServer = global.__turboModuleProxy ? require('./NativeStaticServer').default : _reactNative.NativeModules.StaticServer; both are null.

@birdofpreyru
Copy link
Owner

Hey @lovetingyuan, have you followed what @viljark wrote (#8 (comment))?

@lovetingyuan
Copy link

Hey @lovetingyuan, have you followed what @viljark wrote (#8 (comment))?

I create a new expo project, and I run npx expo prebuild, and still get the error
微信图片_20221118223512

@viljark
Copy link

viljark commented Nov 18, 2022

@lovetingyuan have you built the expo development client after you added the package?

@lovetingyuan
Copy link

lovetingyuan commented Nov 18, 2022

should I run npm run android or eas build --profile development --platform android?

@mihkuno
Copy link

mihkuno commented Dec 30, 2022

frankly I had to re-learn vanilla react to use this lib... dev wuz efficient with expo. Also, it really needs a good example when working with webview especially the directories

@birdofpreyru
Copy link
Owner

@mihkuno it sounds like now you might be a valuable contributor to expand the Readme regarding Expo use of the lib :) improving other aspects of Readme is on my todo list.

@leandronorcio
Copy link

Screenshot_20230113_191714

I'm having exactly the same error as @lovetingyuan, I'm using the older version because I can't drop support for Android SDK <28.

@birdofpreyru
Copy link
Owner

@leandronorcio It looks like you telling it to server files from a location it has no access to.

Here is the Java code block where you hit the error (specifically on www_root = new File(this.reactContext.getFilesDir(), root); line):

    if(root != null && (root.startsWith("/") || root.startsWith("file:///"))) {
      www_root = new File(root);
      localPath = www_root.getAbsolutePath();
    } else {
      www_root = new File(this.reactContext.getFilesDir(), root);
      localPath = www_root.getAbsolutePath();
    }

i.e. it looks like you provided empty or relative root value, so it tries to resolve it from app's files directory, but fails.

@leandronorcio
Copy link

Screenshot_1673610503
@birdofpreyru that's a really fast response, it's working now. Thank you!

@birdofpreyru birdofpreyru added the Expo Expo - Isn't officially supported yet. label May 9, 2023
@the-unknown
Copy link

the-unknown commented Oct 18, 2023

Not sure if this is the same issue, but I get the following error using Expo:

 ERROR  Error: `fileDir` MUST BE a non-empty string

This error is located at:
    in App (created by withDevTools(App))
    in withDevTools(App)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes
 ERROR  Error: `fileDir` MUST BE a non-empty string

This error is located at:
    in App (created by withDevTools(App))
    in withDevTools(App)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes

Screenshot of a the error.

This is my code:

import React, { useEffect, useState, useRef } from 'react';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, SafeAreaView } from 'react-native';
import { WebView } from 'react-native-webview';
import StaticServer from "@dr.pogodin/react-native-static-server";

export default function App() {


  const serverRef = useRef();
  if (!serverRef.current) serverRef.current = new StaticServer(5555, "./assets/out", { localOnly: true, keepAlive: true });
  const server = serverRef.current;
  const [uri] = useState(`http://localhost:${server.port}`);

  useEffect(() => {
    server.start().then((url) => {
      console.log("Serving at URL", url);
    });

    () => {
      // Stop the server
      server.stop();
    }
  }, []);

  const webViewProps = {
    javaScriptEnabled: true,
    androidLayerType: 'hardware',
    originWhitelist: ['*'],
    allowFileAccess: true,
    domStorageEnabled: true,
    mixedContentMode: 'always',
    allowUniversalAccessFromFileURLs: true,
    scalesPageToFit: true,
  };

  const Header = () => (
    <View style={styles.header}>
    </View>
  );

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <StatusBar style="light" />
      <Header />
      <WebView
        style={styles.container}
        source={{ uri }}
        {...webViewProps}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  header: {
    paddingTop: 15,
    paddingBottom: 10,
    backgroundColor: "#ec3c3c"
  },
  title: {
    color: "#fff",
    fontSize: 20,
    fontWeight: "bold",
    textAlign: "center"
  },
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: 40,
  },
});

@birdofpreyru
Copy link
Owner

Server constructor() has different signature.

@evanNyew
Copy link

evanNyew commented Mar 26, 2024

Hi there,
I am having a dependency issues when trying to have a static server with Expo apps
command npx install-peerdeps @dr.pogodin/react-native-static-server@latest lead me to following

npm install @dr.pogodin/[email protected] @dr.pogodin/[email protected] react@18 [email protected] [email protected] --save

However, when I follow @viljark comment, trying to run "npx expo prebuild --platform iOS"
I got the following error when it's trying to run pod install

Fetching podspec for "hermes-engine" from "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" [Hermes] Using release tarball from URL: https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.73.6/react-native-artifacts-0.73.6-hermes-ios-debug.tar.gz [!] CocoaPods could not find compatible versions for pod "React-FabricImage": In Podfile: React-FabricImage (from ../node_modules/react-native/ReactCommon) Specs satisfying the React-FabricImage (from ../node_modules/react-native/ReactCommon) dependency were found, but they required a higher minimum deployment target.

Should I fold back to previous version like @dr.pogodin/[email protected]?

Update:
If I fold back to @dr.pogodin/[email protected] with dependency.
{ "name": "my-app", "version": "1.0.0", "main": "node_modules/expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo run:android", "ios": "expo run:ios" }, "dependencies": { "@dr.pogodin/react-native-fs": "2.21.0-alpha.1", "@dr.pogodin/react-native-static-server": "0.9.2", "@expo/ngrok": "^4.1.0", "@types/react": "~18.2.14", "buffer": "^6.0.3", "expo": "~49.0.13", "expo-crypto": "~12.4.1", "expo-secure-store": "~12.3.1", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", "react": "^18.2.0", "react-native": "0.72.10", "react-native-webview": "13.2.2", "react-native-webview-crypto": "^0.0.25", "react-native-windows": "0.72.32", "text-encoding": "^0.7.0", "typescript": "^5.1.3" }, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }

I got this error after running
**npx install-peerdeps @dr.pogodin/react-native-static-server ** &&
npx expo prebuild --platform iOS &&
expo start
Notes: it didn't throw any error at installation phase

` ERROR Error: The package '@dr.pogodin/react-native-fs' doesn't seem to be linked. Make sure:

  • You have run 'pod install'
  • You rebuilt the app after installing the package
  • You are not using Expo Go
    , js engine: hermes
    ERROR Invariant Violation: "main" has not been registered. This can happen if:
  • Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
  • A module failed to load due to an error and AppRegistry.registerComponent wasn't called., js engine: hermes`

@birdofpreyru
Copy link
Owner

@evanNyew the original error you got does not look to me related to this library, nor Expo, and it just says that the minimum deployment target (iOS version) set in your Xcode project is lower than those declared by pods you are trying to use. As of the latest RN, the deployment target should be 13.4 or higher (see this).

The latter error looks like some incompatibility between the older library version and the RN version... but might be something Expo-related, I don't know.

@jole141
Copy link

jole141 commented Apr 5, 2024

Hi, @birdofpreyru . I've created a tutorial on how to use this library with Expo. It's not strictly Expo, as you'll need to make a development build, but I don't think it should be too much of an issue. Check out my tutorial, I hope it helps you.

https://github.com/jole141/expo-examples/tree/react-native-static-server

@birdofpreyru
Copy link
Owner

Great! Thanks @jole141 , I'll refer your tutorial in README later.

@Sumansourabh14
Copy link

Hi @birdofpreyru, thanks for this package.

Could you please mention by when can you start the work on officially supporting Expo? A lot of people are trying to use this package in their Expo managed projects and in some cases, the example by @jole141 does not work.

@birdofpreyru
Copy link
Owner

Could you please mention by when can you start the work on officially supporting Expo?

As soon as somebody sponsors it 😎

@benjaminkomen
Copy link

Another data point, I got this library to work for both iOS and Android on Expo 52 using New Architecture, here is the POC: https://github.com/benjaminkomen/expo-static-server

@birdofpreyru
Copy link
Owner

Great @benjaminkomen ! Though, the repo you linked seems to be private — I see Error 404 when accessing the link.

@benjaminkomen
Copy link

Great @benjaminkomen ! Though, the repo you linked seems to be private — I see Error 404 when accessing the link.

Whoops, it is public now. One thing I noticed in my tests, is that I can host static files like images or videos, but when I tried to pick a binary file (like an APK), it did not work, there was no error message, it just refused to serve the file. Is that expected behaviour?

@birdofpreyru
Copy link
Owner

but when I tried to pick a binary file (like an APK), it did not work, there was no error message, it just refused to serve the file. Is that expected behavior?

No idea — I haven't encountered such a problem. How do you test it, isn't it the case that a browser, or some tool, just ignores attempts to fetch some binary files due to security considerations, while the server serves them fine? Anyway, I think if you enable all errorLog options in the server constructor, you should be able to figure out from the detailed logs what is going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Expo Expo - Isn't officially supported yet. On Hold Cannot be resolved at the moment. P4 No action needed at this time.
Projects
None yet
Development

No branches or pull requests