7

我有一个 Angular 9 应用程序,在其中我从资产文件夹中读取了 api url:

@Injectable()
export class ConfigService {

  private configUrl = '../../../assets/config/config.json';

  constructor(private loggerService: LoggerService) { }

  public async loadConfig(): Promise<any> {
    try {
      const response = await fetch(this.configUrl);

      if (!response.ok) {
        throw new Error(response.statusText);
      }

      return await response.json();
    } catch (err) {
      this.loggerService.error(`ConfigService 'loadConfig' threw an error on calling ${this.configUrl} : ${err.tostring()}`);
    }
  }
}

用于读取配置文件的方法在构建后配置 Angular 生产文件中进行了描述。

environment.ts

export const environment = {
  production: false,
  apiUrl: "https://localhost/api/",
};

environment.prod.ts

export const environment = {
  production: true,
  apiUrl: "https://server/api/",
};

config.json

{
  "apiUrl": "http://someTestServer/api/"
}

要复制到的不完整脚本apiUrlconfig.json

var fs = require("fs");
fs.readFile(`./src/environments/environment.${process.env.CONFIG}.ts`, 'utf8', function (err, data) {

  fs.writeFile('./src/assets/config/config.json', data, function (err) {
    if (err) throw err;
    console.log('complete');
  });
});

我的 package.json 脚本部分如下所示:

  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build-test": "CONFIG=test node update-config.js && npm run build",
    "build-prod": "CONFIG=prod node update-config.js && npm run predeploy",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "predeploy": "ng build --prod",
    "deploy": "node ftpdeploy.js"
  }

考虑到上述情况:如何config.json根据不同的环境变量在构建之前自动填充文件的内容,这样我就不需要手动将 json 文件复制并粘贴到\dist文件夹中?

更新 1:现在我可以将 enviroment.xxx.ts 的内容复制到 config.json 文件中。还有一个问题:当我从 environment.xxx.ts 复制内容时,它会将 environment.xxx.ts 的全部内容复制到 config.json 中(它还复制了我的 enviroment.xxx.ts 的导入部分)但是预期结果是将environment( export const environment) 读入对象并根据源environment对象更新 config.json。我怎样才能做到这一点?

4

2 回答 2

6

将预构建脚本更改为:

const fs = require("fs");
fs.readFile(`/src/environments/${process.env.CONFIG}.ts`, (err, content) => {
  fs.writeFile("/src/assets/config/config.json", JSON.stringify(versionObject), () => { });
});

然后从命令行(我假设npm run build是要构建的命令,否则用您的构建命令更改它):

$ CONFIG=environment npm run build

应该解决你的问题。

编辑:

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "ng build",
  // add more lines as you need like this, one for each build environment
  "build-test": "CONFIG=test node update-config.js && npm run build",
  "build-prod": "CONFIG=prod node update-config.js && npm run predeply",
  "test": "ng test",
  "lint": "ng lint",
  "e2e": "ng e2e",
  "predeploy": "ng build --prod",
  "deploy": "node ftpdeploy.js"
},

我在您的问题中注意到 a \,可能您在 Windows 下运行,请确保使用 a bash: add a file called .npmrcwith only following linescript-shell=bash

编辑:如果你想用 读取环境文件fetch并用 解析它await response.json(),该文件应该是 json 文件,而不是 ts 文件:

{
  production: true,
  apiUrl: "https://server/api/",
}

希望这可以帮助。

于 2020-06-18T13:38:03.093 回答
2

从您在更新的帖子和评论中指出的内容来看,您想要实现的目标是不可能的。

基本上,您想将一个对象 ( environment) 值复制到一个 json 文件中,但是该对象从其他对象导入它的一些值

所以你有这样的东西

某处.ts

export const constantValue = "myValue";

环境.xx.ts

import {constantValue} from "./somewhere";

export const environment = {
  production: false,
  apiUrl: "https://localhost/api/",
  otherValue: constantValue
};

问题:在构建之前,您无法访问 的值constantValue,因此您无法真正使其成为预构建脚本。

构建后,该environment对象将包含在main-es2015XXX.js. 但是,只有在您的配置中otherValue启用时,才会解析的值,如下所示:buildOptimizerangular.json

使用buildOptimizer : false,该值尚未解析,它将在运行时。所以你不能使用这些值来编写你的 json 文件。变量将environment如下所示:

const environment = {
  production: false,
  apiUrl: "https://localhost/api/",
  otherValue: _somewhere__WEBPACK_IMPORTED_MODULE_0__["constantValue"]
};

使用buildOptimizer : true,可以在构建时解析常量的值。值将如下所示

const i={production:!1,apiUrl:"https://localhost/api/",otherValue:"myValue"}

但是,其中的代码mainXXX.js被缩小/丑化了,我怀疑您是否能够解析/提取上面的配置值...

因此,要么删除所有导入(使用硬编码值)并使用 Daniele Ricci 的答案,要么手动创建您的 json 文件。

笔记

我不完全理解你这样做的原因,但我的感觉是在你的代码中你应该使用:

  • environment.ts构建后不变的值的值
  • config.json构建后可以更改的值的值
于 2020-06-25T07:40:10.630 回答