【发布时间】:2019-07-30 09:13:42
【问题描述】:
我正在开发一个需要在不同服务器上运行的 Angular 7 项目。我需要从环境文件中读取服务器 URL 并且不能设置为静态变量。
我尝试读取 JSON 文件,但在我 ng build 项目后,它会将 JSON 的内容复制为 main.js 中的静态值
是否可以在构建项目后动态读取 JSON 文件?就像从 env.json 中读取一样,我可以在构建项目后放置
【问题讨论】:
标签: angular
我正在开发一个需要在不同服务器上运行的 Angular 7 项目。我需要从环境文件中读取服务器 URL 并且不能设置为静态变量。
我尝试读取 JSON 文件,但在我 ng build 项目后,它会将 JSON 的内容复制为 main.js 中的静态值
是否可以在构建项目后动态读取 JSON 文件?就像从 env.json 中读取一样,我可以在构建项目后放置
【问题讨论】:
标签: angular
我在 assets 文件夹中创建了一个 setting.json 文件,在 ng build 之后我转到 setting.json 更改后端 url。
export class SettingService {
constructor(private http: HttpClient) {
}
public getJSON(file): Observable<any> {
return this.http.get("./assets/configs/" + file + ".json");
}
public getSetting(){
// use setting here
}
}
在 app 文件夹中,我添加文件夹 configs/setting.json
setting.json 中的内容
{
"baseUrl": "http://localhost:52555"
}
在应用模块中添加APP_INITIALIZER
{
provide: APP_INITIALIZER,
useFactory: (setting: SettingService) => function() {return setting.getSetting()},
deps: [SettingService],
multi: true
}
【讨论】:
在 Hien Ngyuen 的回答的帮助下,我做到了:
添加了以下服务:
config.service.ts
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { HttpService } from './http.service';
import { ConstantService } from './constant.service';
@Injectable({
providedIn: 'root'
})
export class ConfigService {
constructor(
private httpService: HttpService,
private constantService: ConstantService
) { }
/*
* Load configuration from env.json
*/
loadConfig(): Observable<any> {
let url = './assets/env.json';
let requestObject = {
API_URL: url,
REQUEST_METHOD: this.constantService.REQUEST_METHOD_GET
};
return this.httpService.sendRequest(requestObject).pipe(map(this.extractData));
}
/*
* Extract data from response
*/
private extractData(res: Response) {
let body = res;
return body || {};
}
}
http.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ConstantService } from './constant.service';
const httpOptions = {
withCredentials: true,
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(
private httpClient: HttpClient,
private constantService: ConstantService
) { }
sendRequest(requestData) {
if (requestData.REQUEST_METHOD == this.constantService.REQUEST_METHOD_GET) {
return this.httpClient.get(url, httpOptions);
} else if (requestData.REQUEST_METHOD == this.constantService.REQUEST_METHOD_POST) {
return this.httpClient.post(url, requestData.BODY, httpOptions);
} else if (requestData.REQUEST_METHOD == this.constantService.REQUEST_METHOD_PUT) {
return this.httpClient.put(url, requestData.BODY, httpOptions);
} else if (requestData.REQUEST_METHOD == this.constantService.REQUEST_METHOD_DELETE) {
return this.httpClient.delete(url, httpOptions);
}
}
}
接下来,在 ng build 之后,我添加了 assets\env.json,我能够更改和读取 env.json 中的值。
【讨论】:
不,我认为您必须在代码中维护一个 .json 文件,并根据您的根 url 从中动态选择。 您还可以根据请求发起的 ip 或域每次向服务器发送返回 base_url 的调用。
{
'server-one': 'abc.com',
'server-two': 'abc1.com',
}
【讨论】:
据我了解,您想使用 JSON 文件模拟后端请求?对我来说,最好的方法是使用拦截器,它会拦截 url。
@Injectable()
export class MockResponseInterceptor implements HttpInterceptor {
constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// ignore "production" and requests to other ressources
if (environment.production || !req.url.startsWith(environment.backendBaseUrl)) {
return next.handle(req);
}
const modifiedUrl: string = this.mockUrl(req.url);
const modifiedRequest = req.clone({ url: modifiedUrl });
return next.handle(modifiedRequest);
}
mockUrl(url: string): string {
// any kind of modification or replacement etc. goes here
// you want to return the path to the JSON file here
}
}
【讨论】: