专栏首页全栈修仙之路玩转 Angular 环境变量

玩转 Angular 环境变量

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

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

environment.ts 和 environment.prod.ts

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

$ ng new PROJECT-NAME

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

  1. environment.ts
export const environment = {
  production: false
};
  1. environment.prod.ts
export const environment = {
  production: true
};

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

// 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:

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 文件的注释中。

// 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 文件中定义:

 "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 文件,并输入以下内容:

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

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

"configurations": {
   "production": {
      "fileReplacements": [
         {
           "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.prod.ts"
          }
        ],
        // ...
    }
 }

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

"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 环境:

"mock": {
   "fileReplacements": [
      {
         "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.mock.ts"
      }
    ]
}

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

$ ng build --prod

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

$ ng build --test

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

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 文件,增加一条输出日志:

console.log(environment.baseUrl);

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

$ ng build --configuration=test

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

$ python -m SimpleHTTPServer

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

https://test.semlinker.com

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

"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"
        }
       }
},

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

$ ng serve --configuration=test

总结

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Nest系列教程之入门篇

    Nest 用于构建高效且可扩展的服务器端应用程序的渐进式 Node.js 框架,深受 Angular 的启发。

    阿宝哥
  • 了不起的 Deno 入门篇

    Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验。Deno 含有以下功能亮点:

    阿宝哥
  • TypeScript 非空断言

    使用这种方案,问题是解决了。但有没有更简单的方式呢?答案是有的,就是使用 TypeScript 2.0 提供的非空断言操作符:

    阿宝哥
  • 姜德峰:中国智慧城市能力体系建设思考

    回顾2017,中国智慧城市在网络强国、数字中国及大数据等发展战略实施过程中稳步前行。展望2018,静心思考,希望为我国智慧城市能力体系建设贡献力量。 当前,随着...

    企鹅号小编
  • ORACLE 11gR2 DG(Physical Standby)日常维护

    1.3.2 备库切换到open状态,启用Real-time query A physical standby database instance cannot...

    Alfred Zhao
  • Airflow Dag可视化管理编辑工具Airflow Console

    Airflow Console: https://github.com/Ryan-Miao/airflow-console

    Ryan-Miao
  • K8s集群中的Windows节点,这样搭建快速搞定!

    K8s 1.14版增加了对windows节点的生产级支持,从1.9就有了对windows的实验性支持,灵雀云在多个客户环境有过实践,去除平台相关的内容后整理成文...

    灵雀云
  • HTTP知识点总结

    最近互联网这个圈子不是很太平,继阿里缩招降薪,导致很多同学“被拥抱变化”之后,百度也宣布暂时停止社招了。于是有人疾呼“Winter is coming”,有人跟...

    Sheepy
  • Python第二十三课:递归斐波那契

    斐波那契(fibonacci) 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fib...

    红芽
  • 数据库层如何扩展?

    这样看来,似乎只要加几个数据库,共同分担来自应用层的流量就完成了从单库到多库的扩展:

    ayqy贾杰

扫码关注云+社区

领取腾讯云代金券