天天看點

Angular 環境配置

Angular 環境配置

如何使用環境配置

在實際開發中,總是需要針對不同的環境設定不同的參數,Angular 提供了一種應用環境機制,當使用 ng new 建構一個新項目時預設會在 src/environments 目錄下針對開發環境與生産環境(environment.prod.ts)的配置項。

絕大多數情況下,我們生産環境的後端請求位址與開發環境是不一樣,是以可以分别為其定義不同的域,例如:

// environment.ts
export const environment = {
  production: false,
  apiBaseUrl: `https://test.asdf.com/`
};      

對于生産環境可以為:

// environment.prod.ts
export const environment = {
  production: true,
  apiBaseUrl: `https://api.asdf.com/`
};      

當然,對于開發人員而言,無須如何去辨識它們,隻需要在 src 目錄的任意位置引用 apiBaseUrl 變量即可,就像這樣:

import { environment } from 'src/environments/environment';


console.log(`${environment.apiBaseUrl}`);      

當通過 ng s 開發模式時自動使用 environment.ts,反之 ng b 會使用 environment.prod.ts 來替代。

事實上,不管 ng s 還是 ng b 兩種模式,本質上都可以利用 -c 參數來互換,例如:

// ng s -c development  -> environment.ts
// ng s -c production   -> environment.prod.ts      

雖然 Angular 在建立時隻産生兩種環境,倘若需要針對 CI 單獨做一些額外的環境配置,隻需要在 angular.json 檔案配置的 architect/build/configurations 下新增一個新的節點,例如:

// angular.json


"architect": {
  "build": {
    "configurations": {
      // 新增 ci 節點
      "ci": {
        "fileReplacements": [{
          "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.ci.ts"
        }]
      }
    }
  },
  // 如果希望 ng s 也生效,則以下也是必須的
  "serve": {
    "configurations": {
      "ci": {
        "browserTarget": "test:build:ci" // 注意 test 是項目名
      }
    }
  }
}      

然後在 src/environments 目錄下,新增 environment.ci.ts 檔案:

// environment.ci.ts
export const environment = {
  production: false,
  apiBaseUrl: `https://ci.asdf.com/`
};      

最後,可以使用 ng b -c ci 指令,所有 apiBaseUrl 都将使用 https://ci.asdf.com/ 來替代了。

index.html 配置

不同環境使用不同的 index.html,比如說希望生産環境下多增加一些 Google Analytics 統計代或IM之類的,可能你也很希望在開發環境下不希望加載這些讓開發變慢的東西吧。

跟 environments 做法類似,隻需要在 angular.json 增加一點配置即可:​

// angular.json


"architect": {
  "build": {
    "configurations": {
      "production": {
        "index": {
          "input": "src/index.prod.html",
          "output": "index.html"
        }
      }
    }
  }
}      

同樣,需要在 src 下新增一個 index.prod.html 檔案;當使用 ng b 時會采用 index.prod.html 作為 index.html 的内容。

優化Tree-Shake

Angular 環境配置不光能替換配置;同時,根據這種檔案替換形式,來幫助我們更友好的進行 Tree-Shake 動作,而且非常徹底。

那麼什麼情況下會遇到呢?例如不希望在開發環境下加載某個子產品,以 NG-ALAIN 提供的 Mock功能 為例,并不希望在生産環境下依然加載它。

正常我們第一想到的是使用 environment.production 來區分環境進行動态加載,假設隻希望開發環境下加載 NG-ZORRO 的按鈕子產品:

import { NzButtonModule } from 'ng-zorro-antd/button';


const moduels: Array<Type<any>> = [];
if (environment.production) {
  moduels.push(NzButtonModule);
}


@NgModule({
  imports: [BrowserModule, ...moduels],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}      

即便代碼層面已經很明确不需要 NzButtonModule 子產品,但對于編譯而言依然需要先加載編譯,再到 Tree-Shake 環節剔除它;但它依然會有一點狗皮膏藥似的,還會包含一點點并不需要的代碼在上面,這取決于目标子產品是依賴關系。

是以,要想讓它真正從我們檔案中消失,最直接的辦法就是讓它不需要加載編譯。這有兩種方式可以做到:

粗暴

細心的讀者可能早已發現為什麼這種配置的替換是用 fileReplacements 來描述,沒錯,誠如 fileReplacements 意思,本質上就是檔案的替換;并且這裡還是一個數組,意味者允許加入更多的替換,但這類必須是符合 TypeScript 程式的檔案類型。

是以,可以直接替換某個 .ts 檔案,比如粗暴的把 app.module.ts 分為 app.module.prod.ts ,同時修改 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"
  }
]      

溫和

另一種方式是,将子產品的導入放到 environment.ts 檔案當中,例如:

// environment.ts


import { NzButtonModule } from 'ng-zorro-antd/button';


export const environment = {
  production: false,
  apiBaseUrl: `https://test.asdf.com/`,
  modules: [NzButtonModule],
};      

最後,再将 modules 數組導入到根子產品下。

// app/app.module.ts


import { environment } from 'src/environments/environment';


@NgModule({
  imports: [BrowserModule, ...environment.modules],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule {}      

結論

本篇隻是 Angular 的一個簡單運用,利用 Angular Cli 提供的檔案替換能力,可以幫助我們解決不同環境下使用不同參數、子產品、檔案等。

總之,也算是側面的說明 Angular Cli 的可塑性也還是很強的。

學習更多技能

請點選下方公衆号