填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫Home

建構並執行 Angular 應用

Building and serving Angular apps

本文討論的是 Angular 專案中與建構有關的配置項。

This page discusses build-specific configuration options for Angular projects.

配置應用環境

Configuring application environments

你可以用不同的預設值來為專案定義出不同的命名配置項,比如 stageproduction

You can define different named build configurations for your project, such as stage and production, with different defaults.

每個命名配置項都可以具有某些選項的預設值,並應用於各種建構目標,比如 buildservetestAngular CLIbuildservetest 命令可以為不同的目標環境,把檔案替換成合適的版本。

Each named configuration can have defaults for any of the options that apply to the various builder targets, such as build, serve, and test. The Angular CLI build, serve, and test commands can then replace files with appropriate versions for your intended target environment.

配置針對特定環境的預設值

Configure environment-specific defaults

專案的 src/environments/ 資料夾包含基礎配置檔案 environment.ts,它提供了一個預設環境。 你可以在針對特定目標的配置檔案中,為其它環境(比如生產和預生產)覆蓋這些預設值。

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.

比如:

For example:

└──myProject/src/environments/ └──environment.ts └──environment.prod.ts └──environment.stage.ts
      
      └──myProject/src/environments/
                   └──environment.ts
                   └──environment.prod.ts
                   └──environment.stage.ts
    

基礎環境 environment.ts 包含了預設的環境設定。比如:

The base file environment.ts, contains the default environment settings. For example:

export const environment = { production: false };
      
      export const environment = {
  production: false
};
    

當沒有指定環境時,build 命令就會用它作為建構目標。 你可以新增其它變數,可以用該環境物件附加屬性的形式,也可以用獨立物件的形式。 比如:以下內容將會把一個變數新增到預設環境中:

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. For example, the following adds a default for a variable to the default environment:

export const environment = { production: false, apiUrl: 'http://my-api-url' };
      
      export const environment = {
  production: false,
  apiUrl: 'http://my-api-url'
};
    

你可以新增針對特定目標的配置檔案,比如 environment.prod.ts。 下面的程式碼會設定針對生產環境建構目標的預設值:

You can add target-specific configuration files, such as environment.prod.ts. The following sets content sets default values for the production build target:

export const environment = { production: true, apiUrl: 'http://my-prod-url' };
      
      export const environment = {
  production: true,
  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
      
      └── 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';
      
      import { environment } from './../environments/environment';
    

這會確保 buildserve 命令能找到針對特定目標的配置。

This ensures that the build and serve commands can find the configurations for specific build targets.

元件檔案(app.component.ts)中的下列程式碼可以使用該配置檔案中定義的環境變數。

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!'; }
      
      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!';
}
    

配置針對特定目標的檔案替換規則

Configure target-specific file replacements

CLI 的主配置檔案 angular.json 中的每個建構目標下都包含了一個 fileReplacements 區段。這能讓你把任何檔案替換為針對特定目標的版本。 當建構目標需要包含針對特定環境(比如生產或預生產)的程式碼或變數時,這非常有用。

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. This is useful for including target-specific code or variables in a build that targets a specific environment, such as production or staging.

預設情況下不會替換任何檔案。 你可以為特定的建構目標新增檔案替換規則。比如:

By default no files are replaced. You can add file replacements for specific build targets. For example:

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

這意味著當你建構生產配置時(用 ng build --prodng build --configuration=production),就會把 src/environments/environment.ts 檔案替換成針對特定目標的版本 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.

你還可以按需新增更多配置檔案。要想新增預生產環境,把 src/environments/environment.ts 複製為 src/environments/environment.staging.ts,然後在 angular.json 中新增 staging 配置:

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" } ] } }
      
      "configurations": {
  "production": { ... },
  "staging": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.staging.ts"
      }
    ]
  }
}
    

你還可以往目標環境中新增更多配置項。 你的建構目標支援的任何選項都可以在建構目標配置中進行覆蓋。

You can add more configuration options to this target environment as well. Any option that your build supports can be overridden in a build target configuration.

要想使用預生產環境(staging)的配置進行建構,請執行下列命令:

To build using the staging configuration, run the following command:

ng build --configuration=staging
      
      ng build --configuration=staging
    

如果將其新增到 angular.json 的 "serve:configurations" 區段,你還可以配置 serve 命令來使用 目標建構配置:

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

配置檔案大小預算

Configuring size budgets

當應用的功能不斷增長時,其檔案大小也會同步增長。 CLI 允許你透過配置項來限制檔案大小,以確保應用的各個部分都處於你定義的大小範圍內。

As applications grow in functionality, they also grow in size. 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.

你可以在 CLI 配置檔案 angular.jsonbudgets 區段為每個所配置的環境定義這些大小範圍。

Define your size boundaries in the CLI configuration file, angular.json, in a budgets section for each configured environment.

{ ... "configurations": { "production": { ... budgets: [] } } }
      
      {
  ...
  "configurations": {
    "production": {
      ...
      budgets: []
    }
  }
}
    

你可以為整個應用指定大小範圍,也可以為特定部分。 每個條目會為一種特定的型別配置大小範圍。 用下列各式來指定大小的值:

You can specify size budgets for the entire app, and for particular parts. Each budget entry configures a budget of a given type. Specify size values in the following formats:

  • 123 或 123b:以位元組為單位的大小

    123 or 123b: Size in bytes

  • 123kb:以 kb 為單位的大小

    123kb: Size in kilobytes

  • 123mb:以 mb 為單位的大小

    123mb: Size in megabytes

  • 12%:相對於基準大小的百分比大小。(不能用作基準大小的值。)

    12%: Percentage of size relative to baseline. (Not valid for baseline values.)

如果配置了大小範圍,建構系統就會在發現應用的某個部分達到或超過了你設定的大小範圍時發出警告或報錯。

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.

每個範圍條目是一個 JSON 物件,它具有下列屬性:

Each budget entry is a JSON object with the following properties:

屬性

Property

Value

type

限制的型別。有效值為:

The type of budget. One of:

  • bundle - 特定套件的大小。

    bundle - The size of a specific bundle.

  • initial - 應用的初始大小。

    initial - The initial size of the app.

  • allScript - 所有指令碼的總大小。

    allScript - The size of all scripts.

  • all - 整個應用的總大小。

    all - The size of the entire app.

  • anyComponentStyle - 任何一個元件樣式檔案的大小。

    anyComponentStyle - This size of any one component stylesheet.

  • anyScript - 任何一個指令碼的大小。

    anyScript - The size of any one script.

  • any - 任何一個檔案的大小。

    any - The size of any file.

name

要限制的套件的名字(當 type=bundle 時)。

The name of the bundle (for type=bundle).

baseline

一個表示基準大小的絕對值,用做比例值的基數。

The baseline size for comparison.

maximumWarning

當大小超過基線的這個閾值百分比時給出警告。

The maximum threshold for warning relative to the baseline.

maximumError

當大小超過基線的這個閾值百分比時報錯。

The maximum threshold for error relative to the baseline.

minimumWarning

當大小小於基線的這個閾值百分比時給出警告。

The minimum threshold for warning relative to the baseline.

minimumError

當大小小於基線的這個閾值百分比時報錯。

The minimum threshold for error relative to the baseline.

warning

當大小達到或小於基線的這個閾值百分比時都給出警告。

The threshold for warning relative to the baseline (min & max).

error

當大小達到或小於基線的這個閾值百分比時都報錯。

The threshold for error relative to the baseline (min & max).

配置 CommonJS 依賴項

Configuring CommonJS dependencies

建議你在 Angular 應用中避免依賴 CommonJS 模組。對 CommonJS 模組的依賴會阻止打包器和壓縮器優化你的應用,這會導致更大的打包尺寸。 建議你在整個應用中都使用 ECMAScript 模組。 欲知詳情,參閱為什麼 CommonJS 會導致更大的打包尺寸

It is recommended that you avoid depending on CommonJS modules in your Angular applications. Depending on CommonJS modules can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes. Instead, it is recommended that you use ECMAScript modules in your entire application. For more information, see How CommonJS is making your bundles larger.

如果 Angular CLI 檢測到你的瀏覽器端應用依賴了 CommonJS 模組,就會發出警告。 要禁用這些警告,你可以把這些 CommonJS 模組的名字新增到 angular.json 檔案的 build 區的 allowedCommonJsDependencies 選項中。

The Angular CLI outputs warnings if it detects that your browser application depends on CommonJS modules. To disable these warnings, you can add the CommonJS module name to allowedCommonJsDependencies option in the build options located in angular.json file.

"build": { "builder": "@angular-devkit/build-angular:browser", "options": { "allowedCommonJsDependencies": [ "lodash" ] ... } ... },
      
      "build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
     "allowedCommonJsDependencies": [
        "lodash"
     ]
     ...
   }
   ...
},
    

配置瀏覽器相容性

Configuring browser compatibility

CLI 使用 Autoprefixer 來確保對不同瀏覽器及其版本的相容性。 你會發現當你要從建構中針對特定的目標瀏覽器或排除指定的瀏覽器版本時,這是很有必要的。

The CLI uses Autoprefixer to ensure compatibility with different browser and browser versions. You may find it necessary to target specific browsers or exclude certain browser versions from your build.

在內部 Autoprefixer 依賴一個名叫 Browserslist 的函式庫來指出需要為哪些瀏覽器加字首。 Browserlist 會在 package.jsonbrowserlist 屬性中或一個名叫 .browserslistrc 的配置檔案中來配置這些選項。 當 Autoprefixer 為你的 CSS 加字首時,就會查閱 Browserlist 的配置。

Internally, Autoprefixer relies on a library called 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.

  • 你可以為 package.json 新增 browserslist 屬性來告訴 Autoprefixer,要針對哪些瀏覽器:

    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" ]
          
          "browserslist": [
      "> 1%",
      "last 2 versions"
    ]
        
  • 或者你也可以在專案目錄下新增一個新檔案 .browserslistrc,用於指定你要支援哪些瀏覽器:

    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
          
          ### Supported Browsers
    > 1%
    last 2 versions
        

參閱 browserslist 的程式碼函式庫以得到如何指定瀏覽器及其版本的更多例子。

See the browserslist repo for more examples of how to target specific browsers and versions.

使用 Lighthouse 做向後相容

Backward compatibility with Lighthouse

如果你要製作漸進式應用,並使用 Lighthouse 來對該專案進行評分,請為 package.json 新增如下的 browserslist 條目,以消除老版本的 flexbox 字首:

If you want to produce a progressive web app and are using Lighthouse to grade the project, add the following browserslist entry to your package.json file, in order to eliminate the old flexbox prefixes:

"browserslist": [ "last 2 versions", "not ie <= 10", "not ie_mob <= 10" ]
      
      "browserslist": [
  "last 2 versions",
  "not ie <= 10",
  "not ie_mob <= 10"
]
    

CSS 網格 (Grid) 佈局的向後相容

Backward compatibility with CSS grid

Autoprefixer 預設支援 CSS 網格佈局,但在 Angular 8 及更高版本中,它預設處於禁用狀態。

CSS grid layout support in Autoprefixer, which was previously on by default, is off by default in Angular 8 and higher.

要在 IE10/11 中使用 CSS 網格佈局,必須使用 autoplace 選項顯式啟用它。 為此,請將以下內容新增到全域性樣式檔案的頂部(或用在特定的 css 選擇器範圍內):

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 */
      
      /* autoprefixer grid: autoplace */
    

or

/* autoprefixer grid: no-autoplace */
      
      /* autoprefixer grid: no-autoplace */
    

欲知詳情,參閱 Autoprefixer 文件

For more information, see Autoprefixer documentation.

代理到後端伺服器

Proxying to a backend server

你可以使用 webpack 開發伺服器中的代理支援來把特定的 URL 轉發給後端伺服器,只要傳入 --proxy-config 選項就可以了。 比如,要把所有到 http://localhost:4200/api 的呼叫都轉給執行在 http://localhost:3000/api 上的伺服器,可採取如下步驟。

You can use the proxying support in the webpack dev server to divert certain URLs to a backend server, by passing a file to the --proxy-config build option. For example, to divert all calls for http://localhost:4200/api to a server running on http://localhost:3000/api, take the following steps.

  1. 在專案的 src/ 目錄下建立一個 proxy.conf.json 檔案。

    Create a file proxy.conf.json in your project's src/ folder.

  2. 往這個新的代理配置檔案中新增如下內容:

    Add the following content to the new proxy file:

    { "/api": { "target": "http://localhost:3000", "secure": false } }
          
          {
      "/api": {
        "target": "http://localhost:3000",
        "secure": false
      }
    }
        
  3. 在 CLI 配置檔案 angular.json 中為 serve 目標新增 proxyConfig 選項:

    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" }, ...
          
          ...
    "architect": {
      "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        "options": {
          "browserTarget": "your-application-name:build",
          "proxyConfig": "src/proxy.conf.json"
        },
    ...
        
  4. 要使用這個代理選項啟動開發伺服器,請執行 ng serve 命令。

    To run the dev server with this proxy configuration, call ng serve.

你可以編輯這個代理配置檔案,以新增配置項,例子如下。 要檢視所有選項的詳細說明,參閱 webpack DevServer 文件

You can edit the proxy configuration file to add configuration options; some examples are given below. For a description of all options, see webpack DevServer documentation.

注意,如果你編輯了這個代理配置檔案,就必須重啟 ng serve,來讓你的修改生效。

Note that if you edit the proxy configuration file, you must relaunch the ng serve process to make your changes effective.

重寫 URL 路徑

Rewrite the URL path

pathRewrite 代理配置項能讓你在執行時重寫 URL 路徑。 比如,你可以在代理配置中指定如下的 pathRewrite 值,以移除路徑末尾的 "api" 部分。

The pathRewrite proxy configuration option lets you rewrite the URL path at run time. 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": "" } } }
      
      {
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    }
  }
}
    

如果你要訪問的後端不在 localhost 上,還要設定 changeOrigin 選項。比如:

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 } }
      
      {
  "/api": {
    "target": "http://npmjs.org",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    },
    "changeOrigin": true
  }
}
    

要想了解你的代理是否在如預期般工作,可以設定 logLevel 選項。比如:

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" } }
      
      {
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    },
    "logLevel": "debug"
  }
}
    

代理的有效日誌級別是 info(預設值)、debugwarnerrorsilent

Proxy log levels are info (the default), debug, warn, error, and silent.

代理多個條目

Proxy multiple entries

透過用 JavaScript 定義此配置,你還可以把多個條目代理到同一個目標。

You can proxy multiple entries to the same target by defining the configuration in JavaScript.

將代理配置檔案設定為 proxy.conf.js(代替 proxy.conf.json),並指定如下例子中的配置檔案。

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;
      
      const PROXY_CONFIG = [
    {
        context: [
            "/my",
            "/many",
            "/endpoints",
            "/i",
            "/need",
            "/to",
            "/proxy"
        ],
        target: "http://localhost:3000",
        secure: false
    }
]

module.exports = PROXY_CONFIG;
    

在 CLI 配置檔案 angular.json 中,指向 JavaScript 配置檔案:

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" }, ...
      
      ...
"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.js"
    },
...
    

繞過代理

Bypass the proxy

如果你需要根據情況繞過此代理,或在發出請求前先動態修改一下,可以新增 bypass 選項,就像下例的 JavaScript 所示。

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;
      
      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

如果你在某個公司代理之後,此後端就無法直接代理到區域網之外的任何 URL。 這種情況下,你可以把這個後端代理配置為,藉助 agent 透過你的公司代理轉發此呼叫:

If you work behind a corporate proxy, the backend cannot directly proxy calls to any URL outside your local network. In this case, you can configure the backend proxy to redirect calls through your corporate proxy using an agent:

npm install --save-dev https-proxy-agent
      
      npm install --save-dev https-proxy-agent
    

如果你定義了環境變數 http_proxyHTTP_PROXY,當執行 npm start 時,就會自動新增一個 agent 來透過你的企業代理轉發網路呼叫。

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.

請在 JavaScript 配置檔案中使用如下內容。

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);
      
      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);