使用环境变量为ng serve设置proxy.config.js属性

4

标题已经很明确了。我有一个proxy.conf.js文件,在ng serve时被使用,我只想从环境ts文件或json文件中获取目标url,或者现在我并不关心,我只想有一个地方来存储URL,并分别提供给其他地方使用......

所以environment.congif.ts(它没有包含任何配置,只是一个用于存储设置对象的文件,当前提供给environment.dev.ts并且无法提供给proxy.conf.js);

export const environment = {
    production: false,
    apiUrl: 'http://localhost:12345'
};

然后是proxy.conf.js文件;
var settings = require('./src/environments/environment.config');

const PROXY_CONFIG = [{
    "/restapi/*": {
      "target": settings.environment.apiUrl,
      "secure": false,
      "changeOrigin": true,
      "logLevel": "debug"
    }
}]

module.exports = PROXY_CONFIG

我显然不理解其中的某些原因(特别是由于intellisense已经完美地填写了文件和属性的路径),但在ng serve上会出现错误;

Cannot find module './src/environments/environment.config'
Error: Cannot find module './src/environments/environment.config'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
........

我的问题是,为什么不能这样解决?我只想用一个文件设置目标URL,并从environment.config.ts提供所需的位置。
补充说明:environment.*.ts文件位于/src/environments中,与任何默认安装一样。proxy.conf.js与其他默认文件(如package.json或angular.json)位于项目根目录中。路径都是正确的,Intellisense甚至会自动填充值,但由于某种原因,在导入来自环境的const对象时,proxy.conf.js无法正常工作(在构建时,虽然像我说的那样,Intellisense可以完美地找到所有内容)。因此,正如标题所传达的那样,我唯一遇到的问题就是从环境ts文件中将URL读入到代理js文件中,以便我只需维护一个文件来管理apiurl。

你的问题似乎很奇怪。但我真的想知道,你是否有特定目的更改了默认的environment.ts文件名为environment.dev.ts?我不确定是否是因为这个原因,但在angular.json中提到,在生产构建期间,该文件将被environment.prod.ts替换。这个错误不应该存在,因为该命令在生产构建期间执行,但仍然尝试使用默认的environment.ts来查看错误是否仍然存在。当然,这两个文件仅用于设置生产和开发配置。 - sndpkpr
你尝试使用 environment.dev.js 作为环境吗?我不认为 webpack-server 愿意转译 TypeScript。 - lossleader
@Sandeep。 environment.ts会被构建的配置所替换。例如 ng build --prod就会用environment.prod.ts替换environment.ts,我在里面有一个完全独立的文件,并未包含在任何构建配置中,它是专门用来存储dev配置(没有--prod标志的所有内容),我试图使用它来提供proxy.conf.js和environment.dev.ts的设置,environment.dev.ts可以很好地导入它的设置,问题在于proxy.conf.js的要求。 :/ - Chris W.
@lossleader,是的,它可以很好地导入到environment.dev.ts中,请参见上一条评论以获取更多细节。由于某种原因,在proxy.conf.js中的require似乎无法读取包含设置的对象,这可能是es6与commonjs语法的无知所致?此时我还不确定。 - Chris W.
1
@Sandeep,require 只需要在 .js 文件中使用,任何 .ts 文件都能很好地处理来自另一个 ts 文件的导入。 - Chris W.
显示剩余9条评论
4个回答

1

嗨,Chris,如果你需要配置代理,你需要创建一个名为 proxyconfig.json 的自定义文件,并将其放置在应用程序目录中,该目录将不在应用程序的 src 文件夹中。

1- 在配置代理文件之前,模拟需要从此端点获取一些数据

this.http.get('http://locahost:3000/api/v1/people')
  

2- proxyconfig.json 将包含以下 JSON 内容

{
  "/api/*": { // 
    "target": "http://localhost:3000", // the target url for backend endpoint
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  }
}

3- 您需要在您的package.json文件中做出一些更改

   "scripts": {
      "start": "ng serve -- --proxy-config ../../proxyconfig.json",
      ...
   }
} 

4- 您的服务中的终端节点应更改为

this.http.get('/api/v1/people')
  

5- 运行 ng serve 命令,代理将会成功工作。

希望这能帮到您 :))


1
你好!是的,如果我在proxy.conf.js文件中直接输入URL,代理就可以正常运行。但是我想让它从环境设置(src/environments/environment.ts)中读取URL,因为我已经配置了根据环境替换它。例如,environment.dev.ts已经显示了代理URL,我想将该值读取(require)到proxy.conf.js中,这样只需要更新一个文件中的url:port,就可以提供所有需要它的内容。不过还是谢谢你的帮助! - Chris W.
@ChrisW,你可以将配置放在JSON文件中。然后按照描述使用http.get获取它。接下来,你可以根据环境使用相应的值(在Angular中有一种方法可以知道当前运行的环境)。 - Sergey

1
所以这里的问题实际上是typescript的版本和其缺乏import vs require支持。如果您使用类似v3的任何版本,您将不会遇到相同的问题。感谢您的关注!

0

你可以用类似的方式来实现 https://stackblitz.com/edit/angular-2uz6n8

我是通过将两个环境变量放在同一个文件中来实现的。


为什么不使用预定义的环境变量呢? 您可以在environment.tsenvironment.prod.ts中轻松添加一些属性,并通过import { environment } from './environment';访问这些属性,然后只需在代码中使用envoronment.ANY_KEY_YOU_WANT,相应的环境文件将会被使用。


环境文件都正常工作,我目前已经设置好并正确工作各种配置。问题出在proxy.conf.js文件中,我试图从environment*.ts文件中导入设置,但感谢你的尝试帮助:) - Chris W.
@ChrisW. 你确定必须精确导入 .js 文件吗?这并不是真正可配置的。如果你想要导入 environment 并使用它的变量,最好使用 import { environment } from '...'。看起来你已经结合了不同的模块方法,因此导致错误,因为 export const NAME 需要 import { NAME } from '' - Sergey

-1

内存转译(我的解决方案)

这里没有“好”的解决方案,因为 Angular 希望环境文件是 TypeScript,代理配置是 JavaScript(或 JSON)。你可以通过几种方式来弥合这个差距。我的方法是在内存中转译环境文件 - 它们通常很小、简单且封闭,而且你已经安装了 TypeScript。这是我的 src/proxy.conf.js 的顶部,在实际使用 environment 的值之前:

/*
 * Based on reference here:
 * https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#a-simple-transform-function
 *
 * Loads, transpiles, and executes a Typescript module.
 * This is very simple, literally just enough for an environment.ts file.
 */
function load_ts(filename) {
    const fs = require('fs');
    const ts = require('typescript');

    // Load and transpile to JS
    let ts_code = fs.readFileSync(filename, 'utf-8');
    let js_code = ts.transpileModule(ts_code, {
        compilerOptions: { module: ts.ModuleKind.CommonJS }
    }).outputText;

    // Execute JS. We need 'exports' to exist, or this breaks.
    let exports = {};
    return eval(js_code);
}

const environment = load_ts('./src/environments/environment.ts');

// ...

这样做有一些优点,可以在需要时运行,与ng serve无缝衔接(假设您在angular.json中指向它),并且对工作流程的影响很小。这也意味着,如果您需要将代理配置设置为JavaScript而不是JSON(用于JS独有的功能),那么思考起来就非常简单。但是,这假定您的environment.ts文件不会做任何过于激动人心或聪明的事情-通常是一个公平的假设,但如果您在environment.ts中进行导入,则可能需要不同的方法。


外带编译(另一种选择)

如果您将命令包装在npm run ...中,而不是直接使用ng serve,则可以选择在运行ng serve之前编写并编译TypeScript代理配置:

/*   src/proxy.conf.ts   */
import * as environment from './environments/environment';
  
export = {
    '/api': {
        target: (<any>environment).api_server || 'http://example.com',
        changeOrigin: true,
        logLevel: "debug",
        // ...
    }
}

在你的 package.json 文件中(只包含相关部分)...

{
  "scripts": {
    "start": "npm run proxy-config && ng serve",
    "proxy-config": "tsc --types node --module commonjs src/proxy.conf.ts"
  }
}

当然,你需要将你的angular配置指向生成的文件src/proxy.conf.js

这种方法有一些讨厌的特点(会生成src/environments/environment.js,启动速度较慢,除非你包装命令否则不会运行,容易出错),但可能是可用的最灵活的选项。

一个非常相似的变体(只转换src/environments/environment.js,手写src/proxy.conf.js与JS导入类似)具有类似的优点,但留给读者作为练习。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接