NodeJS React boilerplate -在运行时更改API url

bmp9r5qi  于 2023-05-28  发布在  Node.js
关注(0)|答案(2)|浏览(676)

我使用react-boilerplate作为我的项目的基础。
我目前在webpack.base.babel.js中定义我的API URL如下:

new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV),
        PIZZA_API_URL: JSON.stringify('https://some-ip:8081')
      },
    }),

但是,这仅在构建时拾取。
在create-react-app中,可以使用REACT_APP_PIZZA_URL。任何以REACT_APP* 开头的内容都可以在运行时开始时设置。
所以我可以做:

docker run -e "REACT_APP_DB_HOST=HELLOWORLD" -d -p3000:3000 pizza-supplier-ui:test

你如何用react-boilerplate做同样的事情?
谢谢你

8zzbczxx

8zzbczxx1#

你说得对,你的React应用程序消耗的环境变量实际上是在构建时注入的,因此不允许真正的动态配置。
为了解决这个问题,你需要意识到,为了实现你想要的内容,提供给你的客户端(组成你的React应用程序)的静态文件的内容需要在运行时是可更改的。
你可以通过不同的方式来实现这一点,但它总是会导致你必须操作一些文件或创建一个文件(通过在运行时使用你想要的env var来操作它),并在做出这些更改后提供这些文件。有两种方法我可以想到这样做:
最简单的方法是利用<script/>标记加载到HTML文件中的顺序(查看this StackOverflow answer以了解更多信息)。您希望导入一个JavaScript文件,该文件将从您的服务器提供。您的服务器将在运行时动态创建此文件,具体取决于服务器读取的环境变量。因此,在HTML的<head> ... </head>部分,添加一个脚本标记,如:<script src=%PUBLIC_URL%/apiConfig.js并引用这个“transient”JS文件。
现在,您需要在服务器上配置一个GET请求Map,以便当它收到<base-url>/apiConfig.js的GET请求时,它返回一个JavaScript文件。在Sping Boot 项目中,您可以拥有一个类,例如:

@RestController
@CrossOrigin
public class ApiController {
    String apiURL = System.getenv("apiUrl");
    
    @GetMapping(value = "/apiConfig.js", produces = "application/javascript")
    String getApiConfig() {
    String body = "window._apiconfig_ = {API_URL: \"" + apiURL + "\"};";
    return body;
    }  
}

最后,在你的React代码中,你需要引用全局窗口对象,这是你的API_URL应该存在的地方。我会使用以下引用:window?._apiconfig_?.API_URL这个变量现在有了Java控制器在运行时读取的环境变量。
这个方法受到了this online tutorial的强烈启发,请查看稍微不同的方法。
此外-这为某人打开了一扇门,可以将代码注入到您的JavaScript中,因此就安全性而言,这是一个非常糟糕的主意......如果这是一个问题,不要这样做。
第二种方法将是创建虚拟串,即CHANGE_THIS_API_URL_AT_RUNTIME,并在运行时配置您的服务器,以便它读取环境变量,扫描您的静态文件,并将虚拟字符串替换为环境变量(即您动态想要设置的API URL)。
这两种解决方案都非常笨拙,引入了安全问题,并且会降低性能。在我提出的第一种方法中,会有一个对JavaScript文件的阻塞获取,该文件是在服务器上生成的-您可以让服务器缓存此响应,这将从服务器端加快速度,但用户仍然会执行该请求。

2jcobegt

2jcobegt2#

好的--这是我自己的问题的答案,经过几个小时的研究和试错。
对于生产构建,webpack会编译你的js文件并将它们打包到build/目录中。
被引用为${process.env.API_URL}/api/query/findPizzaById/的API URL被烘焙到build/目录中的编译后的js文件中。
因此,此命令:

docker run -e "API_URL=HELLOWORLD" -d -p3000:3000 pizza-supplier-ui:test

完全没有效果。然而,它会将API_URL注册为正在运行的docker镜像上的环境变量。这里的问题是API_URL是在BUILD TIME定义的,使用的是运行构建的环境变量FROM。
如果有人在这个问题上挣扎并有解决方案,我将感谢您的启发!
谢谢

相关问题