对于 “程序猿” 来说,在日常开发过程中,我们经常要与不同的开发环境打交道。在实际的项目的开发过程中,一般至少会有两个环境:开发环境和线上环境,这是很简单的情形。但对于一些项目来说,仅有两个环境是不够,除了开发环境和线上环境之外,可能还会包含测试环境和预发布环境等等。
随着前后端分离开发方式的普及,越来越多的公司采用 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 文件:
- environment.ts
export const environment = {
production: false
};
- environment.prod.ts
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 文件的注释中。
// 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 文件,并输入以下内容:
代码语言: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 命令所支持的参数:
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 环境是否生效:
代码语言:javascript复制$ 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"
}
}
},
之后,我们就可以在命令行运行以下的命令,来启用测试环境:
代码语言:javascript复制$ ng serve --configuration=test
总结
本文简单介绍了 Angular 项目中,environment.ts 和 environment.prod.ts 文件的作用和 Angular 动态切换环境的实现方式,此外后面我们还进一步介绍了如何自定义多个开发环境。掌握了本文所涉及的内容,基本上已经可以满足大多数项目的需求,对于上述的内容如果有遗漏的地方欢迎大家补充哈。