necolas / react-native-web

Cross-platform React UI packages
https://necolas.github.io/react-native-web
MIT License
21.69k stars 1.79k forks source link

React-Native-Web. Build Error - Unable to resolve "./RCTNetworking" #2734

Open CaptainJeff opened 3 weeks ago

CaptainJeff commented 3 weeks ago

Is there an existing issue for this?

Describe the issue

When I'm trying to build the project I run into the error

Unable to resolve "./RCTNetworking" from "node_modules/react-native/Libraries/Network/XMLHttpRequest.js"

Seems like the issue is node_modules/react-native/Libraries/Network directory has an RCTNetworking.android.js and RCTNetworking.ios.js but the metro.config.js can't find a corresponding file for web.

I have a dependency that makes my API requests with axios (that i access from my npm module / not directly from my app components/stores.

I've tried mocking out the RCTNetworking but can't seem to get anything to work. It will either not make the request or will fail with the same import error.

For instance if I do

if (moduleName.endsWith("RCTNetworking")) {
      return {
        filePath: require.resolve("identity-obj-proxy"),
        type: "sourceFile"
      }
    }

It hides the error on build but I can't make HTTP calls and gives me the following error when I try to make an API request

TypeError: Cannot read properties of undefined (reading 'default')
    at XMLHttpRequest.send (XMLHttpRequest.js:527:7)
    at dispatchXhrRequest (xhr.js:195:13)
    at tryCallTwo (core.js:45:5)
    at doResolve (core.js:200:13)
    at new Promise (core.js:66:3)
    at xhr (xhr.js:15:10)
    at ThrottlingAdapter.<anonymous> (adapter.js:186:40)
    at Generator.next (<anonymous>)
    at adapter.js:8:71
    at tryCallTwo (core.js:45:5)
    at Axios.request (Axios.js:45:41)

Expected behavior

Would expect to compile and be able to make API requests.

Steps to reproduce

1) npx expo start --web -c

"react-native": "0.74.2", "expo": "^51.0.0"

Test case

N/A

Additional comments

No response

CaptainJeff commented 6 days ago

Here is some more information

When i run npx expo start --web -c i'm able to resolve this by updating my metro.config.js

/**
 * Metro configuration
 * 
 *
 * u/type {import('metro-config').MetroConfig}
 */
const { getDefaultConfig } = require("expo/metro-config")
const { mergeConfig } = require("@react-native/metro-config")
const path = require("path")

const defaultConfig = getDefaultConfig(__dirname)

const {
  resolver: { sourceExts, assetExts }
} = defaultConfig

const config = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: true,
        inlineRequires: true
      }
    }),
    babelTransformerPath: require.resolve("react-native-svg-transformer/expo")
  },
  resolver: {
    assetExts: [...assetExts.filter((ext) => ext !== "svg"), "ttf", "otf"],
    sourceExts: [...sourceExts, "svg"],
    extraNodeModules: {
      "react-native": path.resolve(__dirname, "node_modules/react-native-web"),
      stream: require.resolve("stream-browserify"),
      buffer: require.resolve("buffer"),
      process: require.resolve("process/browser")
    }
  }
}

config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (platform === "web") {
    if (moduleName.endsWith("RCTNetworking")) {
      return {
        filePath: require.resolve("identity-obj-proxy"),
        type: "sourceFile"
      }
    }

    if (moduleName.endsWith("./RCTAlertManager")) {
      return {
        filePath: require.resolve("identity-obj-proxy"),
        type: "sourceFile"
      }
    }

  }

  return context.resolveRequest(context, moduleName, platform)
}

module.exports = mergeConfig(defaultConfig, config)

https://facebook.github.io/metro/docs/configuration And including global.XMLHttpRequest = global?.originalXMLHttpRequest || global.XMLHttpRequest in my index.js file.

But when i bundle and serve the app npx expo export -p web && npx serve dist --single it doesn't work.

I get various issues.

For example

index-fae72be5f22c92931a109296bd504de0.js:5417 TypeError: Cannot read properties of undefined (reading 'node') which comes from the identify-obj-proxy dependency. But if I fix that then i get

TypeError: r(...).default.addListener is not a function which comes from node_modules/react-native/Libraries/Network/XMLHttpRequest.js

    if (this.readyState !== this.OPENED) {
      throw new Error('Request has not been opened');
    }
    if (this._sent) {
      throw new Error('Request has already been sent');
    }
    this._sent = true;
    const incrementalEvents =
      this._incrementalEvents || !!this.onreadystatechange || !!this.onprogress;

    this._subscriptions.push(
      RCTNetworking.addListener('didSendNetworkData', args =>
        this.__didUploadProgress(...args),
      ),
    );
    this._subscriptions.push(
      RCTNetworking.addListener('didReceiveNetworkResponse', args =>
        this.__didReceiveResponse(...args),
      ),
    );
    this._subscriptions.push(
      RCTNetworking.addListener('didReceiveNetworkData', args =>
        this.__didReceiveData(...args),
      ),
    );

I feel like I've tried everything. If anyone has any tips for this it would be super appreciated!