Angular 環(huán)境配置

來(lái)源 | https://segmentfault.com/a/1190000040531172
如何使用環(huán)境配置
// environment.tsexport const environment = {production: false,apiBaseUrl: `https://test.asdf.com/`};
對(duì)于生產(chǎn)環(huán)境可以為:
// environment.prod.tsexport const environment = {production: true,apiBaseUrl: `https://api.asdf.com/`};
當(dāng)然,對(duì)于開(kāi)發(fā)人員而言,無(wú)須如何去辨別它們,只需要在 src 目錄的任意位置引用 apiBaseUrl 變量即可,就像這樣:
import { environment } from 'src/environments/environment';console.log(`${environment.apiBaseUrl}`);
當(dāng)通過(guò) ng s 開(kāi)發(fā)模式時(shí)自動(dòng)使用 environment.ts,反之 ng b 會(huì)使用 environment.prod.ts 來(lái)替代。
事實(shí)上,不管 ng s 還是 ng b 兩種模式,本質(zhì)上都可以利用 -c 參數(shù)來(lái)互換,例如:
// ng s -c development -> environment.ts// ng s -c production -> environment.prod.ts
雖然 Angular 在創(chuàng)建時(shí)只產(chǎn)生兩種環(huán)境,倘若需要針對(duì) CI 單獨(dú)做一些額外的環(huán)境配置,只需要在 angular.json 文件配置的 architect/build/configurations 下新增一個(gè)新的節(jié)點(diǎn),例如:
// angular.json"architect": {"build": {"configurations": {// 新增 ci 節(jié)點(diǎn)"ci": {"fileReplacements": [{"replace": "src/environments/environment.ts","with": "src/environments/environment.ci.ts"}]}}},// 如果希望 ng s 也生效,則以下也是必須的"serve": {"configurations": {"ci": {"browserTarget": "test:build:ci" // 注意 test 是項(xiàng)目名}}}}
然后在 src/environments 目錄下,新增 environment.ci.ts 文件:
// environment.ci.tsexport const environment = {production: false,apiBaseUrl: `https://ci.asdf.com/`};
最后,可以使用 ng b -c ci 命令,所有 apiBaseUrl 都將使用 https://ci.asdf.com/ 來(lái)替代了。
index.html 配置
不同環(huán)境使用不同的 index.html,比如說(shuō)希望生產(chǎn)環(huán)境下多增加一些 Google Analytics 統(tǒng)計(jì)代或IM之類(lèi)的,可能你也很希望在開(kāi)發(fā)環(huán)境下不希望加載這些讓開(kāi)發(fā)變慢的東西吧。
跟 environments 做法類(lèi)似,只需要在 angular.json 增加一點(diǎn)配置即可:
// angular.json"architect": {"build": {"configurations": {"production": {"index": {"input": "src/index.prod.html","output": "index.html"}}}}}
同樣,需要在 src 下新增一個(gè) index.prod.html 文件;當(dāng)使用 ng b 時(shí)會(huì)采用 index.prod.html 作為 index.html 的內(nèi)容。
優(yōu)化Tree-Shake
Angular 環(huán)境配置不光能替換配置;同時(shí),根據(jù)這種文件替換形式,來(lái)幫助我們更友好的進(jìn)行 Tree-Shake 動(dòng)作,而且非常徹底。
那么什么情況下會(huì)遇到呢?例如不希望在開(kāi)發(fā)環(huán)境下加載某個(gè)模塊,以 NG-ALAIN 提供的 Mock功能 為例,并不希望在生產(chǎn)環(huán)境下依然加載它。
正常我們第一想到的是使用 environment.production 來(lái)區(qū)分環(huán)境進(jìn)行動(dòng)態(tài)加載,假設(shè)只希望開(kāi)發(fā)環(huán)境下加載 NG-ZORRO 的按鈕模塊:
import { NzButtonModule } from 'ng-zorro-antd/button';const moduels: Array<Type<any>> = [];if (environment.production) {moduels.push(NzButtonModule);}({imports: [BrowserModule, ...moduels],declarations: [AppComponent],bootstrap: [AppComponent],})export class AppModule {}
即便代碼層面已經(jīng)很明確不需要 NzButtonModule 模塊,但對(duì)于編譯而言依然需要先加載編譯,再到 Tree-Shake 環(huán)節(jié)剔除它;但它依然會(huì)有一點(diǎn)狗皮膏藥似的,還會(huì)包含一點(diǎn)點(diǎn)并不需要的代碼在上面,這取決于目標(biāo)模塊是依賴關(guān)系。
因此,要想讓它真正從我們文件中消失,最直接的辦法就是讓它不需要加載編譯。這有兩種方式可以做到:
粗暴
細(xì)心的讀者可能早已發(fā)現(xiàn)為什么這種配置的替換是用 fileReplacements 來(lái)描述,沒(méi)錯(cuò),誠(chéng)如 fileReplacements 意思,本質(zhì)上就是文件的替換;并且這里還是一個(gè)數(shù)組,意味者允許加入更多的替換,但這類(lèi)必須是符合 TypeScript 程序的文件類(lèi)型。
因此,可以直接替換某個(gè) .ts 文件,比如粗暴的把 app.module.ts 分為 app.module.prod.ts ,同時(shí)修改 angular.json 的配置:
"fileReplacements": [{"replace": "src/environments/environment.ts","with": "src/environments/environment.prod.ts"},{"replace": "src/app/app.module.ts","with": "src/app/app.module.prod.ts"}]
溫和
另一種方式是,將模塊的導(dǎo)入放到 environment.ts 文件當(dāng)中,例如:
// environment.tsimport { NzButtonModule } from 'ng-zorro-antd/button';export const environment = {production: false,apiBaseUrl: `https://test.asdf.com/`,modules: [NzButtonModule],};
最后,再將 modules 數(shù)組導(dǎo)入到根模塊下。
// app/app.module.tsimport { environment } from 'src/environments/environment';@NgModule({imports: [BrowserModule, ...environment.modules],declarations: [AppComponent],bootstrap: [AppComponent],})export class AppModule {}
結(jié)論
本篇只是 Angular 的一個(gè)簡(jiǎn)單運(yùn)用,利用 Angular Cli 提供的文件替換能力,可以幫助我們解決不同環(huán)境下使用不同參數(shù)、模塊、文件等。
總之,也算是側(cè)面的說(shuō)明 Angular Cli 的可塑性也還是很強(qiáng)的。
學(xué)習(xí)更多技能
請(qǐng)點(diǎn)擊下方公眾號(hào)
![]()

