简体   繁体   English

如何在每个环境的 React 应用程序中拥有 Nx 环境变量?

[英]How to have Nx environment variables in React app per environment?

Context语境

I have a three projects inside my Nx workspace, two applications which are react apps (both of them have shared logic, however they are intended for different platforms web and microsoft teams and must be separated) and a library which contains logic for an api client, which both of the applications use.我的 Nx 工作区内有三个项目,两个应用程序是 React 应用程序(它们都有共享逻辑,但是它们适用于不同的平台 web 和 Microsoft 团队,必须分开)和一个包含 api 客户端逻辑的库,这两个应用程序都使用。

The api client project requires the variable base URL which is environment specific. api 客户端项目需要特定于环境的变量基数 URL。

I can define environment variables and introduce file replacements in the build process for.ts files (eg environment.ts is replaced with environment.production.ts, when configuration is production), however I do not want to reference this file (environment.ts) in the api client project so as not to introduce two way dependencies.我可以定义环境变量并在 .ts 文件的构建过程中引入文件替换(例如,当配置为生产时,environment.ts 被 environment.production.ts 替换),但是我不想引用这个文件(environment.ts ) 在 api 客户端项目中,以免引入两种方式的依赖关系。

What have I tried我试过什么

From the api project I was not able to extract the logic which depends on the URL variable as this is tied to some code generation which is changeable.从 api 项目中,我无法提取依赖于 URL 变量的逻辑,因为这与一些可变的代码生成有关。

I succeeded in providing this variable by using.env file in the root of the application project, the variable is in the format NX_MY_URL, and could be accessed with process.env.NX_MY_URL.我通过在应用程序项目的根目录中使用 .env 文件成功地提供了这个变量,该变量的格式为 NX_MY_URL,并且可以通过 process.env.NX_MY_URL 访问。

However I was not able to change this variable when changing the build configuration (eg development, test, production).但是,在更改构建配置(例如开发、测试、生产)时,我无法更改此变量。 I have tried adding a fileReplacements task such as我尝试添加一个 fileReplacements 任务,例如

"configurations": {
        "development": {
          "fileReplacements": [
            {
              "replace": "apps/ra-web/src/environments/environment.ts",
              "with": "apps/ra-web/src/environments/environment.development.ts" //<----- This works fine
            },
            {
              "replace": "apps/ra-web/.env",
              "with": "apps/ra-web/.development.env" //<----- This does not work, .env values remain
            }
          ],

Question

How can.env files be replaced based on Nx target's configuration?如何根据 Nx 目标的配置替换 .env 文件?

Why the mentioned approach does not work?为什么提到的方法不起作用?

The reason of why the fileReplacements approach is not working is because those replacements are meant for the building process, which is the bundler the one in charge (webpack or vite, etc). fileReplacements方法不起作用的原因是因为这些替换是用于构建过程的,这是负责的捆绑器(webpack 或 vite 等)。 That file content replacement is actually working, yet it doesn't happen at file system level but at memory level (for the bundling process).该文件内容替换实际上是有效的,但它不会发生在文件系统级别,而是发生在 memory 级别(用于捆绑过程)。 As your application code does not "import" that.env file (and you should not directly depend on it), then those file replacements make no difference in the build output.由于您的应用程序代码不“导入”that.env 文件(并且您不应该直接依赖它),因此这些文件替换对构建 output 没有影响。

On the other side, Nx is in charge of reading the .env file (at file-system level) and loading the data as environment variables so that when the bundling process starts, those are available.另一方面,Nx 负责读取.env文件(在文件系统级别)并将数据加载为环境变量,以便在捆绑过程开始时可用。 This a completely separate process than the fileReplacements done by the bundler.这是一个与fileReplacements完成的文件替换完全不同的过程。

How to achieve what you are looking for?如何实现你正在寻找的东西?

If you think about projects in libs as shareable/re-usable code, then you can imagine those are external dependencies added to your apps (or other libs).如果您将libs中的项目视为可共享/可重复使用的代码,那么您可以想象这些是添加到您的应用程序(或其他库)的外部依赖项。 As those dependencies are external, they should rely on their implementor to get the data needed for them to work.由于这些依赖项是外部的,因此它们应该依赖于它们的实现者来获取它们工作所需的数据。

Having the above in mind, your lib public API (the main index.ts file) should be parametrized to receive that base URL that will depend on each application.考虑到上述情况,您的 lib public API(主index.ts文件)应该被参数化以接收将取决于每个应用程序的基数 URL。 With that you can keep working with the environment.ts file replacements, get the value in the app and pass it down to the lib .有了它,您可以继续使用environment.ts文件替换,获取app中的值并将其传递给lib

Example:例子:

// app's main.tsx
import { environment } from './environments/environment';
import { apiClient } from '@myorg/api-client';

apiClient.init({ baseUrl: environment.baseUrl });

// api-client's index.ts
export { apiClient } from './lib/api-client';

// api-client's api-client.ts

export const apiClient = {
   init: ({ baseUrl }) => { ... }
};

If you still need to work with the .env file (not trying to replace it), just the the env vars in the environment.ts as work with it as mentioned above.如果您仍然需要使用.env文件(而不是尝试替换它),只需使用 environment.ts 中的environment.ts变量,就像上面提到的那样使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM