сценарий предварительной сборки для обновления config.json на основе переменной среды
У меня есть приложение angular 9, в котором я читаю URL-адрес api из папки ресурсов:
@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/"
}
Неполный скрипт для копированияapiUrl
к config.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
) в объект и обновите config.json в соответствии с источником environment
объект. Как я могу этого добиться?
2 ответа
Изменение сценария предварительной сборки как:
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"
},
Я заметил \
в вашем вопросе, вероятно, вы работаете под Windows, обязательно используйте bash
: добавить файл с именем .npmrc
только со следующей строкой script-shell=bash
Изменить: если вы хотите прочитать файл среды с помощьюfetch
и проанализируйте его с помощью await response.json()
, файл должен быть файлом json, а не файлом ts:
{
production: true,
apiUrl: "https://server/api/",
}
Надеюсь это поможет.
Судя по тому, что вы указали в своих обновленных сообщениях и комментариях, то, чего вы хотите достичь, невозможно.
По сути, вы хотите скопировать объект (environment
) значение в файл json, но этот объект импортирует некоторые из своих значений из другого источника.
Итак, у вас есть что-то вроде этого
где-то.
export const constantValue = "myValue";
environment.xx.ts
import {constantValue} from "./somewhere";
export const environment = {
production: false,
apiUrl: "https://localhost/api/",
otherValue: constantValue
};
Проблема: перед сборкой вы не можете получить доступ к значению дляconstantValue
, поэтому вы не можете сделать его заранее подготовленным скриптом.
После сборки environment
объект будет включен в main-es2015XXX.js
. Однако значение дляotherValue
будет разрешено только если вы включили buildOptimizer
в вашем angular.json
config, как показано ниже:
С 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
минимизировано / искажено, и я сомневаюсь, что вы сможете проанализировать / извлечь указанное выше значение конфигурации...
Поэтому либо удалите весь импорт (используйте жестко закодированные значения) и используйте ответ Даниэля Риччи, либо вручную создайте свои файлы json.
Запись
Я не полностью понял вашу причину этого, но мне кажется, что в вашем коде вы должны использовать:
- ценности из
environment.ts
для значений, которые не меняются после сборки - ценности из
config.json
для значений, которые могут измениться после сборки