2018-08-31 17:31:17 -04:00
# Building and serving Angular apps
2018-10-04 15:44:24 -04:00
This page discusses build-specific configuration options for Angular projects.
2018-08-31 17:31:17 -04:00
{@a app-environments}
## Configuring application environments
2019-06-17 12:43:13 -04:00
You can define different named build configurations for your project, such as *stage* and *production* , with different defaults.
2018-08-31 17:31:17 -04:00
2019-08-12 15:19:39 -04:00
Each named configuration can have defaults for any of the options that apply to the various [builder targets ](guide/glossary#target ), such as `build` , `serve` , and `test` . The [Angular CLI ](cli ) `build` , `serve` , and `test` commands can then replace files with appropriate versions for your intended target environment.
2018-08-31 17:31:17 -04:00
### Configure environment-specific defaults
2019-06-17 12:43:13 -04:00
A project's `src/environments/` folder contains the base configuration file, `environment.ts` , which provides a default environment.
You can add override defaults for additional environments, such as production and staging, in target-specific configuration files.
2018-08-31 17:31:17 -04:00
For example:
```
└──myProject/src/environments/
└──environment.ts
└──environment.prod.ts
└──environment.stage.ts
```
The base file `environment.ts` , contains the default environment settings. For example:
2018-10-26 00:49:27 -04:00
```
2018-08-31 17:31:17 -04:00
export const environment = {
production: false
};
2018-10-26 00:49:27 -04:00
```
2018-08-31 17:31:17 -04:00
2019-06-17 12:43:13 -04:00
The `build` command uses this as the build target when no environment is specified.
You can add further variables, either as additional properties on the environment object, or as separate objects.
2018-08-31 17:31:17 -04:00
For example, the following adds a default for a variable to the default environment:
```
export const environment = {
production: false,
apiUrl: 'http://my-api-url'
};
```
2019-06-17 12:43:13 -04:00
You can add target-specific configuration files, such as `environment.prod.ts` .
2018-08-31 17:31:17 -04:00
The following sets content sets default values for the production build target:
```
export const environment = {
2018-12-05 06:18:56 -05:00
production: true,
2018-08-31 17:31:17 -04:00
apiUrl: 'http://my-prod-url'
};
```
### Using environment-specific variables in your app
The following application structure configures build targets for production and staging environments:
```
└── src
└── app
├── app.component.html
└── app.component.ts
└── environments
├── environment.prod.ts
├── environment.staging.ts
└── environment.ts
```
To use the environment configurations you have defined, your components must import the original environments file:
```
import { environment } from './../environments/environment';
```
This ensures that the build and serve commands can find the configurations for specific build targets.
The following code in the component file (`app.component.ts`) uses an environment variable defined in the configuration files.
```
import { Component } from '@angular/core';
import { environment } from './../environments/environment';
@Component ({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor() {
console.log(environment.production); // Logs false for default environment
}
title = 'app works!';
}
```
{@a file-replacement}
## Configure target-specific file replacements
2019-06-17 12:43:13 -04:00
The main CLI configuration file, `angular.json` , contains a `fileReplacements` section in the configuration for each build target, which allows you to replace any file with a target-specific version of that file.
2018-08-31 17:31:17 -04:00
This is useful for including target-specific code or variables in a build that targets a specific environment, such as production or staging.
2019-06-17 12:43:13 -04:00
By default no files are replaced.
You can add file replacements for specific build targets.
2018-08-31 17:31:17 -04:00
For example:
```
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
...
```
This means that when you build your production configuration (using `ng build --prod` or `ng build --configuration=production` ), the `src/environments/environment.ts` file is replaced with the target-specific version of the file, `src/environments/environment.prod.ts` .
You can add additional configurations as required. To add a staging environment, create a copy of `src/environments/environment.ts` called `src/environments/environment.staging.ts` , then add a `staging` configuration to `angular.json` :
```
"configurations": {
"production": { ... },
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
}
]
}
}
```
2019-06-17 12:43:13 -04:00
You can add more configuration options to this target environment as well.
2018-08-31 17:31:17 -04:00
Any option that your build supports can be overridden in a build target configuration.
2018-10-26 00:49:27 -04:00
To build using the staging configuration, run the following command:
< code-example language = "sh" class = "code-shell" >
ng build --configuration=staging
< / code-example >
2018-08-31 17:31:17 -04:00
You can also configure the `serve` command to use the targeted build configuration if you add it to the "serve:configurations" section of `angular.json` :
```
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-project-name:build"
},
"configurations": {
"production": {
"browserTarget": "your-project-name:build:production"
},
"staging": {
"browserTarget": "your-project-name:build:staging"
}
}
},
```
{@a size-budgets}
2019-08-12 15:19:39 -04:00
{@a configure-size-budgets}
2018-08-31 17:31:17 -04:00
2019-08-12 15:19:39 -04:00
## Configuring size budgets
2018-08-31 17:31:17 -04:00
2019-06-17 12:43:13 -04:00
As applications grow in functionality, they also grow in size.
2018-08-31 17:31:17 -04:00
The CLI allows you to set size thresholds in your configuration to ensure that parts of your application stay within size boundaries that you define.
2019-06-17 12:43:13 -04:00
Define your size boundaries in the CLI configuration file, `angular.json` , in a `budgets` section for each [configured environment ](#app-environments ).
2018-08-31 17:31:17 -04:00
```
{
...
"configurations": {
"production": {
...
budgets: []
}
}
}
```
2019-06-17 12:43:13 -04:00
You can specify size budgets for the entire app, and for particular parts.
Each budget entry configures a budget of a given type.
2018-08-31 17:31:17 -04:00
Specify size values in the following formats:
* 123 or 123b: Size in bytes
* 123kb: Size in kilobytes
* 123mb: Size in megabytes
* 12%: Percentage of size relative to baseline. (Not valid for baseline values.)
2019-04-08 11:03:49 -04:00
When you configure a budget, the build system warns or reports an error when a given part of the app reaches or exceeds a boundary size that you set.
2018-08-31 17:31:17 -04:00
Each budget entry is a JSON object with the following properties:
< table >
< tr >
< th > Property< / th >
< th > Value< / th >
< / tr >
< tr >
< td > type< / td >
2019-08-02 02:51:59 -04:00
< td >
The type of budget. One of:
* `bundle` - The size of a specific bundle.
* `initial` - The initial size of the app.
* `allScript` - The size of all scripts.
* `all` - The size of the entire app.
* `anyComponentStyle` - This size of any one component stylesheet.
* `anyScript` - The size of any one script.
* `any` - The size of any file.
2019-06-17 12:43:13 -04:00
2018-08-31 17:31:17 -04:00
< / td >
< / tr >
< tr >
< td > name< / td >
< td >
2019-06-17 12:43:13 -04:00
2018-08-31 17:31:17 -04:00
The name of the bundle (for `type=bundle` ).
2019-06-17 12:43:13 -04:00
2018-08-31 17:31:17 -04:00
< / td >
< / tr >
< tr >
< td > baseline< / td >
2018-12-26 04:13:45 -05:00
< td > The baseline size for comparison.< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > maximumWarning< / td >
2018-12-26 04:13:45 -05:00
< td > The maximum threshold for warning relative to the baseline.< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > maximumError< / td >
2018-12-26 04:13:45 -05:00
< td > The maximum threshold for error relative to the baseline.< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > minimumWarning< / td >
2018-12-26 04:13:45 -05:00
< td > The minimum threshold for warning relative to the baseline.< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > minimumError< / td >
2018-12-26 04:13:45 -05:00
< td > The minimum threshold for error relative to the baseline.< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > warning< / td >
2018-12-26 04:13:45 -05:00
< td > The threshold for warning relative to the baseline (min & max).< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< tr >
< td > error< / td >
2018-12-26 04:13:45 -05:00
< td > The threshold for error relative to the baseline (min & max).< / td >
2018-08-31 17:31:17 -04:00
< / tr >
< / table >
{@a browser-compat}
## Configuring browser compatibility
2019-06-17 12:43:13 -04:00
The CLI uses [Autoprefixer ](https://github.com/postcss/autoprefixer ) to ensure compatibility with different browser and browser versions.
2018-08-31 17:31:17 -04:00
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
2019-06-17 12:43:13 -04:00
Internally, Autoprefixer relies on a library called [Browserslist ](https://github.com/browserslist/browserslist ) to figure out which browsers to support with prefixing.
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc` .
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
2018-08-31 17:31:17 -04:00
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json` :
```
"browserslist": [
"> 1%",
"last 2 versions"
]
```
* Alternatively, you can add a new file, `.browserslistrc` , to the project directory, that specifies browsers you want to support:
```
### Supported Browsers
> 1%
last 2 versions
```
2018-10-18 02:25:06 -04:00
See the [browserslist repo ](https://github.com/browserslist/browserslist ) for more examples of how to target specific browsers and versions.
2018-08-31 17:31:17 -04:00
2019-08-12 15:19:39 -04:00
### Backward compatibility with Lighthouse
2018-08-31 17:31:17 -04:00
2019-08-12 15:19:39 -04:00
If you want to produce a progressive web app and are using [Lighthouse ](https://developers.google.com/web/tools/lighthouse/ ) to grade the project, add the following `browserslist` entry to your `package.json` file, in order to eliminate the [old flexbox ](https://developers.google.com/web/tools/lighthouse/audits/old-flexbox ) prefixes:
2018-08-31 17:31:17 -04:00
```
"browserslist": [
"last 2 versions",
"not ie < = 10",
"not ie_mob < = 10"
]
```
2019-08-12 15:19:39 -04:00
### Backward compatibility with CSS grid
CSS grid layout support in Autoprefixer, which was previously on by default, is off by default in Angular 8 and higher.
To use CSS grid with IE10/11, you must explicitly enable it using the `autoplace` option.
To do this, add the following to the top of the global styles file (or within a specific css selector scope):
```
/* autoprefixer grid: autoplace /
```
or
```
/ autoprefixer grid: no-autoplace */
```
For more information, see [Autoprefixer documentation ](https://autoprefixer.github.io/ ).
2018-08-31 17:31:17 -04:00
{@a proxy}
## Proxying to a backend server
You can use the [proxying support ](https://webpack.js.org/configuration/dev-server/#devserver-proxy ) in the `webpack` dev server to divert certain URLs to a backend server, by passing a file to the `--proxy-config` build option.
2018-10-17 08:57:37 -04:00
For example, to divert all calls for `http://localhost:4200/api` to a server running on `http://localhost:3000/api` , take the following steps.
2018-08-31 17:31:17 -04:00
2019-04-24 17:33:27 -04:00
1. Create a file `proxy.conf.json` in the projects `src/` folder, in the same directory as `package.json` .
2018-08-31 17:31:17 -04:00
1. Add the following content to the new proxy file:
```
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
```
1. In the CLI configuration file, `angular.json` , add the `proxyConfig` option to the `serve` target:
```
...
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
},
...
```
2019-06-17 12:43:13 -04:00
1. To run the dev server with this proxy configuration, call `ng serve` .
2018-08-31 17:31:17 -04:00
2019-06-17 12:43:13 -04:00
You can edit the proxy configuration file to add configuration options; some examples are given below.
2018-08-31 17:31:17 -04:00
For a description of all options, see [webpack DevServer documentation ](https://webpack.js.org/configuration/dev-server/#devserver-proxy ).
Note that if you edit the proxy configuration file, you must relaunch the `ng serve` process to make your changes effective.
### Rewrite the URL path
2019-06-17 12:43:13 -04:00
The `pathRewrite` proxy configuration option lets you rewrite the URL path at run time.
2018-08-31 17:31:17 -04:00
For example, you can specify the following `pathRewrite` value to the proxy configuration to remove "api" from the end of a path.
```
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"pathRewrite": {
"^/api": ""
}
}
}
```
If you need to access a backend that is not on `localhost` , set the `changeOrigin` option as well. For example:
```
{
"/api": {
"target": "http://npmjs.org",
"secure": false,
"pathRewrite": {
"^/api": ""
},
"changeOrigin": true
}
}
```
To help determine whether your proxy is working as intended, set the `logLevel` option. For example:
```
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"pathRewrite": {
"^/api": ""
},
"logLevel": "debug"
}
}
```
Proxy log levels are `info` (the default), `debug` , `warn` , `error` , and `silent` .
### Proxy multiple entries
You can proxy multiple entries to the same target by defining the configuration in JavaScript.
Set the proxy configuration file to `proxy.conf.js` (instead of `proxy.conf.json` ), and specify configuration files as in the following example.
```
const PROXY_CONFIG = [
{
context: [
"/my",
"/many",
"/endpoints",
"/i",
"/need",
"/to",
"/proxy"
],
target: "http://localhost:3000",
secure: false
}
]
module.exports = PROXY_CONFIG;
```
In the CLI configuration file, `angular.json` , point to the JavaScript proxy configuration file:
```
...
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.js"
},
...
```
### Bypass the proxy
If you need to optionally bypass the proxy, or dynamically change the request before it's sent, add the bypass option, as shown in this JavaScript example.
```
const PROXY_CONFIG = {
"/api/proxy": {
"target": "http://localhost:3000",
"secure": false,
"bypass": function (req, res, proxyOptions) {
if (req.headers.accept.indexOf("html") !== -1) {
console.log("Skipping proxy for browser request.");
return "/index.html";
}
req.headers["X-Custom-Header"] = "yes";
}
}
}
module.exports = PROXY_CONFIG;
```
### Using corporate proxy
2019-06-17 12:43:13 -04:00
If you work behind a corporate proxy, the backend cannot directly proxy calls to any URL outside your local network.
2018-08-31 17:31:17 -04:00
In this case, you can configure the backend proxy to redirect calls through your corporate proxy using an agent:
< code-example language = "none" class = "code-shell" >
npm install --save-dev https-proxy-agent
< / code-example >
When you define an environment variable `http_proxy` or `HTTP_PROXY` , an agent is automatically added to pass calls through your corporate proxy when running `npm start` .
Use the following content in the JavaScript configuration file.
```
var HttpsProxyAgent = require('https-proxy-agent');
var proxyConfig = [{
context: '/api',
target: 'http://your-remote-server.com:3000',
secure: false
}];
function setupForCorporateProxy(proxyConfig) {
var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
if (proxyServer) {
var agent = new HttpsProxyAgent(proxyServer);
console.log('Using corporate proxy server: ' + proxyServer);
proxyConfig.forEach(function(entry) {
entry.agent = agent;
});
}
return proxyConfig;
}
module.exports = setupForCorporateProxy(proxyConfig);
```