为跨 Android、IOS 和 Web 的 expo 应用程序统一 localhost dev api 服务器访问?

Posted

技术标签:

【中文标题】为跨 Android、IOS 和 Web 的 expo 应用程序统一 localhost dev api 服务器访问?【英文标题】:Unifying localhost dev api server access for expo app across Android, IOS, and web? 【发布时间】:2020-08-17 13:01:36 【问题描述】:

我正在为 Expo 上的几个学生设置一个简单的 React Native 学习应用程序,该应用程序还与学生正在学习编码的 API 服务器通信。

学生的 API 服务器通过node server.js 运行,并在学生机器上的localhost:3000 上提供服务。与世博无关。

我希望学生能够通过expo start --androidexpo start --iosexpo start --web 中的任何一个在运行其 API 服务器的同一台机器上运行他们的应用程序。每个学生都在家中使用不同的家庭 wifi 网络,不一定知道 IP 地址或网络的来龙去脉。

当使用expo start --web 时,我们会遇到 CORS 异常,除非我们使用自定义的webpack.config.js 解决方法(首先通过https://docs.expo.io/guides/customizing-webpack/ 创建webpack.config.js,然后将其放入webpack.config.js):

const createExpoWebpackConfigAsync = require('@expo/webpack-config');

module.exports = async function(env, argv) 
  const config = await createExpoWebpackConfigAsync(env, argv);
  if (config.mode === 'development') 
    config.devServer.proxy = 
      '/**': 
        target: 
          host: 'localhost',
          protocol: 'http:',
          port: 3000,
        ,
        secure: false,
        changeOrigin: true,
        logLevel: 'info',
      ,
    ;
  
  return config;
;

这很好,因为我们可以在不知道学生的 IP 地址的情况下对 ./end/point 进行 api 调用,并且 expo-cli 启动的 webpack devServer 有效地代理到学生的开发机器上的 http://localhost:3000/end/point

同时,对于 iOS 和 Android,我发现了这个 sn-p:

import Constants from "expo-constants";
const  manifest  = Constants;
const SERVER_URL = "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000`)+"/";

然后在使用fetch()时使用SERVER_URL

但是,我们缺少一个统一的解决方案,它与我们所处的环境(web、ios 或 android)无关。 webpack 代理仅在使用 expo web 客户端时才出现并工作(expo-cli 不会为 ios 或 android 启动 webpack),并且第二个选项 (A) 在 web 和 ( B) 无论如何都会触发 CORS 异常。

我怎样才能优雅地编写一段代码,或者以其他方式为学生设置项目,以便(A)他们不需要知道他们的开发机器的 IP 地址,或者这意味着什么,以及(B)它无论它们是在 web、android 还是 ios expo 客户端中都可以工作?

【问题讨论】:

【参考方案1】:

不喜欢这个作为答案,希望知道的人更好地指出,但这是我最终使用的似乎有效的方法,至少在开发中:

// Some chatter that Contants.manifest needs to come from a different package?
import Constants from "expo-constants";
const  manifest  = Constants;

const SERVER_URL = (() => 
  // TODO - put a "prod" api server somewhere

  // Android / IOS - no CORS issue.
  if (!!manifest.debuggerHost) 
    return "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000/`);
   
  // Expo Web client, making use of webpack.config.js (see original question) for devServer proxy.
  else 
    return "./";
  
)();

...
fetch(SERVER_URL + 'some_endpoint/').then(...)

【讨论】:

以上是关于为跨 Android、IOS 和 Web 的 expo 应用程序统一 localhost dev api 服务器访问?的主要内容,如果未能解决你的问题,请参考以下文章

Android ios嵌套web页面

跨域????如何解决

无法从 Flutter Web 读取 Firestore 中的数据(适用于 iOS 和 android)

如何在 React Native 中实现 Google 地图以在 Web、Android 和 iOS 上运行?

如何为 ios、android 和 web 添加不同分辨率的图像?

Flutter:在 web 、android 和 ios 中使用相同的应用程序