Khi tạo mới ứng dụng Angular bằng Angular CLI, mặc định Angular CLI sẽ tạo ra thư mục src/environments với 2 file là environment.ts và environment.prod.ts cho phép ta đa cấu hình environment cho ứng dụng, cả 2 file này được khai báo trong angular.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
"configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "namedChunks": false, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } }, |
Khi build ứng dụng cho một environment , Angular CLI sẽ thay thế file environment.ts bằng content của một file environment của môi trường đó, ví dụ: environment.qa.ts, environment.prod.ts.
Nhìn chung, cơ chế này khá tốt, nhưng config này là file typescript, và nó không thể chỉnh sửa bởi người triển khai, cũng như phải recompile lại ứng dụng khi có nhu cầu chỉnh sửa cấu hình. Bài viết này sẽ hướng dẫn cấu hình ứng dụng Angular bằng file json để khác phục điều đó.
Định nghĩa interface cho cấu hình
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
export interface IAppConfig { production: boolean, application: { baseUrl :string, name: string, logoUrl: string, }, oAuthConfig: { issuer: string, redirectUri: string, clientId: string, responseType: string, scope: string, }, apis: { default: { url: string, rootNamespace: string, }, }, } |
Tạo file config json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
production: false, application: { baseUrl, name: 'Loyalty', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44384', redirectUri: baseUrl, clientId: 'Loyalty_App', responseType: 'code', scope: 'offline_access openid profile role email phone Loyalty', }, apis: { default: { url: 'https://localhost:44379', rootNamespace: 'Ecommerce.Loyalty', }, }, |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
production: true, application: { baseUrl, name: 'Loyalty', logoUrl: '', }, oAuthConfig: { issuer: 'https://localhost:44384', redirectUri: baseUrl, clientId: 'Loyalty_App', responseType: 'code', scope: 'offline_access Loyalty', }, apis: { default: { url: 'https://localhost:44379', rootNamespace: 'Ecommerce.Loyalty', }, }, |
Tạo service đọc file config
Service này sẽ đọc đúng file config theo môi trường.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Injectable } from '@angular/core’; import { HttpClient } from '@angular/common/http'; import { environment } from '../environments/environment'; import { IAppConfig } from './models/app-config.model'; @Injectable({ providedIn: 'root' }) export class AppConfig { config: IAppConfig; constructor(private http: HttpClient) {} loadConfig() { return this.http .get<IAppConfig>('assets/config/config.${environment.name}.json`') .toPromise() .then(config => { this.config = config; }); } } |
Tải file config trước khi ứng dụng khởi tạo
Angular có một token tên là APP_INITIALIZER cho phép thưc thi code khi ứng dụng đã khởi tạo. Trong app module, tao sẽ sử dụng nó để gọi method loadConfig() của service. Vì method trả về là một promise, Angular sẽ trì hoãn việc khởi tạo cho đến khi promise được resolved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import { APP_INITIALIZER } from '@angular/core'; import { AppConfig } from './app.config'; export function initializeApp(appConfig: AppConfig) { return () => appConfig.loadConfig(); } @NgModule({ imports: [ , , , ], declarations: [ . . . ], providers: [ AppConfig, { provide: APP_INITIALIZER, useFactory: initializeApp, deps: [AppConfig], multi: true } ], bootstrap: [ AppComponent ] }) export class AppModule { } |
Bây giờ, để có thể lấy thống tin config, ta chỉ cần inject service AppConfig và sử dụng các thuộc tính của nó.
1 2 3 4 5 6 7 8 9 10 11 12 |
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'home'; constructor(appConfig: AppConfig) { console.log('config', configService.config); } } |