玩转 Angular 环境变量

2019-11-05 16:15:25 浏览数 (1)

对于 “程序猿” 来说,在日常开发过程中,我们经常要与不同的开发环境打交道。在实际的项目的开发过程中,一般至少会有两个环境:开发环境和线上环境,这是很简单的情形。但对于一些项目来说,仅有两个环境是不够,除了开发环境和线上环境之外,可能还会包含测试环境和预发布环境等等。

随着前后端分离开发方式的普及,越来越多的公司采用 Angular、React 和 Vue 等前端的 MV* 框架来开发 SPA 应用程序。因此对于前端开发者来说,需要不同的开发环境,其实主要是因为不同的环境对应不同的 API 接口地址。作为一个 Angular 的忠实粉丝,我们来介绍一下在 Angular 项目开发中,如何玩转 Angular 环境变量。

environment.ts 和 environment.prod.ts

在 Angular CLI 发布后,越来越多的开发者都是使用 Angular CLI 来创建新的项目:

代码语言:javascript复制
$ ng new PROJECT-NAME

在执行上述命令后,在项目根目录的 src/environments 目录下会自动生成两个文件:environment.ts 和 environment.prod.ts 文件:

  1. environment.ts
代码语言:javascript复制
export const environment = {
  production: false
};
  1. environment.prod.ts
代码语言:javascript复制
export const environment = {
  production: true
};

对于上面提到的需求,即不同环境使用不同的 API 接口地址,我们可以在不同的文件中设置不同的 API 接口地址,比如:

代码语言:javascript复制
// environment.ts
export const environment = {
  production: false,
  baseUrl: "https://dev.semlinker.com"
};

// environment.prod.ts
export const environment = {
  production: true,
  baseUrl: "https://prod.semlinker.com"  
};

Angular CLI 除了自动生成上述两个文件之外,还会自动生成其它的文件,其中就包含 Angular 应用程序的入口文件 —— main.ts:

代码语言:javascript复制
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));

在上面代码中我们从 ./environments 目录下导入 environment.ts 文件,然后根据 environment.production 属性的值,来决定是否启用 Prod 模式。那么现在问题来了,Angular 是怎么实现自动切换不同的开发环境呢?其实答案早已经公布在 src/environments 目录下 environment.ts 文件的注释中。

代码语言:javascript复制
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

通过上面的注释,我们知道在执行 ng build ---prod 命令,进行项目构建的时候,会执行文件替换操作。而相应的文件替换规则,在 angular.json 文件中定义:

代码语言:javascript复制
 "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
           //...
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
            }
          }
        }
}

此时我们已经知道 environment.ts 和 environment.prod.ts 文件的作用和 Angular 动态切换环境的实现方式。下面我们来介绍一下,如何处理两个以上的环境变量。假设因为项目需要,我们需要增加一个测试环境。

自定义环境

首先我们先来新建一个 environment.test.ts 文件,并输入以下内容:

代码语言:javascript复制
// environment.test.ts
export const environment = {
  production: false,
  baseUrl: "https://test.semlinker.com"
};

然后打开项目中的 angular.json 文件,定位到 configurations 字段,具体路径为:projects -> appname -> architect -> build -> configurations,默认情况下只包含 “production” 属性:

代码语言:javascript复制
"configurations": {
   "production": {
      "fileReplacements": [
         {
           "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.prod.ts"
          }
        ],
        // ...
    }
 }

下面我们复制一下 “production” 对象,然后把 “production” 属性名更改为 “test”,具体如下:

代码语言:javascript复制
"test": {
   "fileReplacements": [
      {
         "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.prod.ts" 
      }
    ],
    "optimization": true,
    "outputHashing": "all",
    "sourceMap": false,
    "extractCss": true,
    "namedChunks": false,
    "aot": true,
    "extractLicenses": true,
    "vendorChunk": false,
    "buildOptimizer": true
}

此时,我们已经成功一半了,接着我们还需要把 with 的属性值更新为 “environment.test.ts”。其实如果只是执行简单的替换文件操作,我们可以简单的进行配置,比如重新创建一个 mock 环境:

代码语言:javascript复制
"mock": {
   "fileReplacements": [
      {
         "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.mock.ts"
      }
    ]
}

最后我们来测试一下,还记得在发布正式版本时,我们通过以下命令进行项目构建:

代码语言:javascript复制
$ ng build --prod

那么有的同学,可能想到对于构建测试环境的包,是不是只要运行:

代码语言:javascript复制
$ ng build --test

想象中很完美,但实际上并不是这样,ng build 命令并不支持 --test 参数,感兴趣的同学可以运行 ng build --help 命令查看 ng build 命令所支持的参数:

代码语言:javascript复制
usage: ng build <project> [options]
options:
  --aot
    Build using Ahead of Time compilation.
  --base-href
    Base url for the application being built.
  --build-optimizer
    Enables @angular-devkit/build-optimizer optimizations when using the 'aot' option.
  --configuration (-c)
    Specify the configuration to use.
    Enable and define the file watching poll time period in milliseconds.
  --prod
    Flag to set configuration to "prod".
  --source-map
    Output sourcemaps.
  --stats-json
    Generates a 'stats.json' file which can be analyzed using tools such as: #webpack-bundle-analyzer' or https: //webpack.github.io/analyse.

其实 ng build 命令支持很多的参数,上面我们只是列出了常用的几个。可能有的同学已经注意到了 --configuration 这个参数,通常参数说明,我们知道这个参数用于指定构建时所使用的配置文件。没错,要达到我们预期的结果,就要利用该参数。不过在最终测试前,我们先来更新一下 main.ts 文件,增加一条输出日志:

代码语言:javascript复制
console.log(environment.baseUrl);

最后现在我们再来验证一下我们新创建的 test 环境是否生效:

代码语言:javascript复制
$ ng build --configuration=test

上述命令成功运行之后,就会在根目录下生成 dist 目录,并且在该目录下也会创建一个 PROJECT-NAME 目录。如果你本地已经安装了 python,可以进入该目录,然后在命令行执行:

代码语言:javascript复制
$ python -m SimpleHTTPServer

最后我们在浏览器中访问 http://localhost:8000/ 地址,接着打开控制台,你将会看到以下输出信息:

代码语言:javascript复制
https://test.semlinker.com

其实如果验证的话,可以不用那么麻烦,我们可以使用 ng serve 命令,因为该命令也支持 --configuration 属性。不过与 ng build 命令一样,我们也需要配置一下 angular.json 文件:

代码语言:javascript复制
"serve": {
   "builder": "@angular-devkit/build-angular:dev-server",
   "options": {
      "browserTarget": "angular-storybook-demo:build"
    },
   "configurations": {
      "production": {
         "browserTarget": "angular-storybook-demo:build:production"
       },
       "test": {
          "browserTarget": "angular-storybook-demo:build:test"
        }
       }
},

之后,我们就可以在命令行运行以下的命令,来启用测试环境:

代码语言:javascript复制
$ ng serve --configuration=test

总结

本文简单介绍了 Angular 项目中,environment.ts 和 environment.prod.ts 文件的作用和 Angular 动态切换环境的实现方式,此外后面我们还进一步介绍了如何自定义多个开发环境。掌握了本文所涉及的内容,基本上已经可以满足大多数项目的需求,对于上述的内容如果有遗漏的地方欢迎大家补充哈。

0 人点赞