forked from NationalBankBelgium/stark
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(stark-build): add support for environment variables at runtime (…
…importing environment.ts file) and at compilation time (using webpack Define plugin) ISSUES CLOSED: #50
- Loading branch information
1 parent
d93d64b
commit 4de2a24
Showing
43 changed files
with
431 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,212 @@ | ||
# Environments support | ||
|
||
## Environment.ts | ||
Stark provides 2 different ways to get environment information depending on your needs: | ||
|
||
In the `src/environments/model.ts` is provided the Environment interface as follows | ||
- at runtime by importing the environment.ts file | ||
- at compilation time by checking the global environment variables set by Webpack | ||
|
||
``` | ||
... | ||
export interface Environment { | ||
## Environment information at runtime (environment.ts) | ||
|
||
Stark provides the `StarkEnvironment` interface which describes which information you can get from the current environment. | ||
Such environment interface is defined as follows: | ||
|
||
```typescript | ||
import { NgModuleRef } from "@angular/core"; | ||
|
||
export interface StarkEnvironment { | ||
/** | ||
* Whether the current environment is production | ||
*/ | ||
production: boolean; | ||
/** | ||
* Whether the current environment has Hot Module Replacement enabled | ||
*/ | ||
hmr: boolean; | ||
... | ||
/** | ||
* Array of providers to be included in this environment | ||
*/ | ||
ENV_PROVIDERS: any[]; | ||
/** | ||
* Function to modify/decorate the NgModule Instance created by Angular for a given platform. | ||
* Useful to enable/disable some Angular specifics such as the debug tools. | ||
*/ | ||
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any>; | ||
} | ||
``` | ||
|
||
In your project, the files to define the different environments will be located in `src/environments`: | ||
|
||
```txt | ||
| | ||
+---src | ||
| | | ||
| +---environments # configuration variables for each environment | ||
| | | # | ||
| | | environment.e2e.prod.ts # e2e tests configuration | ||
| | | environment.hmr.ts # development with HMR (Hot Module Replacement) configuration | ||
| | | environment.prod.ts # production configuration | ||
| | \ environment.ts # development configuration | ||
| | | ||
| \ ... | ||
| | ||
\ ... | ||
``` | ||
|
||
`production`, which is a boolean, will specify is your application runs under a production environment, | ||
while `hmr` will indicate if it runs under a Hot Module Replacement environment. | ||
Then in each file, an `environment` constant of type `StarkEnvironment` should be exported providing the values needed for each environment: | ||
|
||
This interface will then be defined by default in `src/environments/environment.ts`: | ||
```typescript | ||
import { NgModuleRef } from "@angular/core"; | ||
import { StarkEnvironment } from "@nationalbankbelgium/stark-core"; | ||
|
||
``` | ||
... | ||
export const environment: Environment = { | ||
production: false, | ||
hmr: false, | ||
showDevModule: true, | ||
... | ||
export const environment: StarkEnvironment = { | ||
production: false, | ||
hmr: false, | ||
ENV_PROVIDERS: [], | ||
|
||
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any> { | ||
... | ||
} | ||
} | ||
``` | ||
|
||
## How to find out which environment is your application is currently using? | ||
### How to get environment variables in your application? | ||
|
||
All you have to do is to import the environment.ts constant anywhere you want in your application: | ||
All you have to do is to import the `environment.ts` constant anywhere you want in your application. | ||
|
||
``` | ||
**You should always import from `environments/environment` because Webpack will internally replace such file with the right environment file as defined in the `fileReplacements` option in the `angular.json` file.** | ||
|
||
This way, you will be able to programmatically read the different environment variables you need. | ||
For example, you can determine on which environment your app is currently running with this simple check: | ||
|
||
```typescript | ||
// the environment file should always be imported from this path | ||
import { environment } from "environments/environment"; | ||
|
||
// if true, your app is running in production environment | ||
if (environment.production) { | ||
/* the code in this block will be executed only in production */ | ||
} | ||
``` | ||
|
||
This way, you will be able to programmatically determine which environment is used in your app | ||
with simple checks, as follows: | ||
### How to add a new environment? | ||
|
||
``` | ||
environment.production | ||
// if the output of this line is true, we are in production environment. | ||
// Otherwise, we are in hmr environment. | ||
``` | ||
First, create your new environment.ts file in the `src/environments` folder. | ||
|
||
Then, make sure your new environment implements the `StarkEnvironment` interface. For example, the `environment.dummy-env.ts` file: | ||
|
||
```typescript | ||
import { NgModuleRef } from "@angular/core"; | ||
import { disableDebugTools } from "@angular/platform-browser"; | ||
import { StarkEnvironment } from "@nationalbankbelgium/stark-core"; | ||
|
||
export const environment: StarkEnvironment = { | ||
production: false, | ||
hmr: false, | ||
ENV_PROVIDERS: [], | ||
|
||
## How to add a new environment ? | ||
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any> { | ||
/* do something here */ | ||
} | ||
}; | ||
``` | ||
|
||
First, create you new Ts file in the `src/environments` folder. | ||
Finally, define the file replacement of your new environment in the `angular.json` file so that Webpack can replace the default file `environments/environment` with your new file: | ||
|
||
```json | ||
{ | ||
... | ||
"dummyEnv": { | ||
"fileReplacements": [ | ||
{ | ||
"replace": "src/environments/environment.ts", | ||
"with": "src/environments/environment.dummy-env.ts" | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
|
||
Then, make sure your new environment extends the `src/environments/model.ts` interface. | ||
### How to add more properties to the environment file? | ||
|
||
Finally, define the options and file replacement of your new environment in the `angular.json` file. | ||
In case you want to add more properties, you should first create your own interface which should extend the `StarkEnvironment` interface. | ||
For example: | ||
|
||
For exemple, the environment.dummyEnv.ts file: | ||
```typescript | ||
import { StarkEnvironment } from "@nationalbankbelgium/stark-core"; | ||
|
||
export interface YourOwnEnvironment extends StarkEnvironment { | ||
someProperty: any; | ||
} | ||
``` | ||
import { enableProdMode, NgModuleRef } from "@angular/core"; | ||
import { disableDebugTools } from "@angular/platform-browser"; | ||
import { Environment } from "./model"; | ||
|
||
enableProdMode(); | ||
Then adapt the different environment files to add the new properties: | ||
|
||
export const environment: Environment = { | ||
```typescript | ||
import { NgModuleRef } from "@angular/core"; | ||
import { disableDebugTools } from "@angular/platform-browser"; | ||
import { StarkEnvironment } from "@nationalbankbelgium/stark-core"; | ||
|
||
export const environment: StarkEnvironment = { | ||
production: false, | ||
hmr: false, | ||
ENV_PROVIDERS: [], | ||
someProperty: "some value", // your new property | ||
|
||
decorateModuleRef(modRef: NgModuleRef<any>): NgModuleRef<any> { | ||
disableDebugTools(); | ||
return modRef; | ||
}, | ||
ENV_PROVIDERS: [] | ||
} | ||
/* do something here */ | ||
} | ||
}; | ||
``` | ||
|
||
And in the angular.json file: | ||
## Environment information at compilation time (Webpack global variables) | ||
|
||
Thanks to the Webpack [DefinePlugin](https://webpack.js.org/plugins/define-plugin), Stark provides some global variables that are available at compilation time, which means that you can | ||
implement some checks in your code and this will be analyzed when your application bundle is being built by Webpack. | ||
|
||
The global variables available at compilation time are the following: | ||
|
||
- `ENV` which indicates the current environment: `"development"` or `"production"` | ||
- `HMR` which indicates whether the Hot Module Replacement support is enabled (true/false). | ||
|
||
### How to get target environment at compilation time? | ||
|
||
Since Webpack defines the environment variables as global, you can use them everywhere in your code like this: | ||
|
||
```typescript | ||
if (ENV === "development") { | ||
/* the code inside this block will be executed only in development */ | ||
} | ||
``` | ||
|
||
To avoid Typescript compilation issues regarding these global variables, make sure that you include the typings from the stark-build package in your app `tsconfig.json`: | ||
|
||
```json | ||
{ | ||
"extends": "./node_modules/@nationalbankbelgium/stark-build/tsconfig.json", | ||
"compilerOptions": { | ||
... | ||
"typeRoots": [ | ||
"./node_modules/@types", | ||
"./node_modules/@nationalbankbelgium/stark-build/typings" // typings from stark-build | ||
], | ||
... | ||
}, | ||
... | ||
} | ||
``` | ||
"dummyEnv" : { | ||
"fileReplacements": [ | ||
{ | ||
"replace": "src/environments/environment.ts", | ||
"with": "src/environments/environment.dummyEnv.ts" | ||
} | ||
] | ||
} | ||
|
||
### Why do you need the target environment at compilation time? | ||
|
||
Sometimes you might need to add some logic or import some files only when your application is running in development or production. | ||
|
||
**In this case, when Webpack builds your application, the final bundle will contain also that code and/or imports that will only be used on a specific environment. | ||
For example, the specific code related to development will never be executed in production and yet it will be included in your production build which will increase the size of your bundle.** | ||
|
||
This is when knowing the target environment at compilation time is useful. You can put the logic inside an if block and then such code will be tree-shaken by Webpack as it will recognize it as dead code: | ||
|
||
```typescript | ||
// this check is translated to "if (false)" in case the ENV is "production" allowing Webpack to identify it as dead code and so remove it | ||
if (ENV === "development") { | ||
/* the code inside this block will only be included in development */ | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.