99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Angular CLI構(gòu)建器

2022-07-15 11:04 更新

Angular CLI 構(gòu)建器(Builder)

很多 Angular CLI 命令都要在你的代碼上執(zhí)行一些復(fù)雜的處理,比如風(fēng)格檢查(lint)構(gòu)建或測(cè)試。這些命令會(huì)通過一個(gè)叫做建筑師(Architect)的內(nèi)部工具來運(yùn)行 CLI 構(gòu)建器,而這些構(gòu)建器會(huì)運(yùn)用一些第三方工具來完成目標(biāo)任務(wù)。

在 Angular 的版本 8 中,CLI 構(gòu)建器的 API 是穩(wěn)定的,想要通過添加或修改命令來自定義 Angular CLI 的開發(fā)人員可以使用它。比如,你可以提供一個(gè)構(gòu)建器來執(zhí)行全新的任務(wù),或者更改一個(gè)現(xiàn)有命令所使用的第三方工具。

本文檔介紹了 CLI 構(gòu)建器是如何與工作區(qū)配置文件集成的,還展示了如何創(chuàng)建你自己的構(gòu)建器。

可以在這個(gè) GitHub 倉(cāng)庫中的例子中找到代碼。

CLI 構(gòu)建器

內(nèi)部建筑師工具會(huì)把工作委托給名叫構(gòu)建器的處理器函數(shù)。處理器函數(shù)接收兩個(gè)參數(shù):一組 ?options ?輸入(JSON 對(duì)象)和一個(gè) ?context?(?BuilderContext ?對(duì)象)。

這里對(duì)關(guān)注點(diǎn)的分離和原理圖中是一樣的,它也適用于其它要接觸(touch)代碼的 CLI 命令(比如 ?ng generate?)。

  • 此 ?options ?對(duì)象是由本 CLI 的用戶提供的,而 ?context ?對(duì)象則由 CLI 構(gòu)建器的 API 提供
  • 除了上下文信息之外,此 ?context ?對(duì)象(它是 ?BuilderContext ?的實(shí)例)還允許你訪問調(diào)度方法 ?context.scheduleTarget()?。調(diào)度器會(huì)用指定的目標(biāo)配置來執(zhí)行構(gòu)建器處理函數(shù)。

這個(gè)構(gòu)建器處理函數(shù)可以是同步的(返回一個(gè)值)或異步的(返回一個(gè) Promise),也可以監(jiān)視并返回多個(gè)值(返回一個(gè) Observable)。最終返回的值全都是 ?BuilderOutput ?類型的。該對(duì)象包含一個(gè)邏輯字段 ?success ?和一個(gè)可以包含錯(cuò)誤信息的可選字段 ?error?。

Angular 提供了一些構(gòu)建器,供 CLI 命令使用,如 ?ng build? 和 ?ng test? 等。這些內(nèi)置 CLI 構(gòu)建器的默認(rèn)目標(biāo)配置可以在工作區(qū)配置文件 ?angular.json? 的 ?architect ?部分找到(并進(jìn)行自定義)??梢酝ㄟ^創(chuàng)建自己的構(gòu)建器來擴(kuò)展和自定義 Angular,你可以使用 ?ng run? CLI 命令來運(yùn)行你自己的構(gòu)建器。

構(gòu)建器的項(xiàng)目結(jié)構(gòu)

構(gòu)建器位于一個(gè) ?project ?文件夾中,該文件夾的結(jié)構(gòu)類似于 Angular 工作區(qū),包括位于頂層的全局配置文件,以及位于工作代碼所在源文件夾中的更具體的配置。比如,?myBuilder ?文件夾中可能包含如下文件。

文件

用途

src/my-builder.ts

這個(gè)構(gòu)建器定義的主要源碼。

src/my-builder.spec.ts

測(cè)試的源碼。

src/schema.json

構(gòu)建器輸入選項(xiàng)的定義。

builders.json

測(cè)試配置。

package.json

依賴包。參閱 https://docs.npmjs.com/files/package.json。

tsconfig.json

TypeScript 配置文件

將此構(gòu)建器發(fā)布到 ?npm?。如果你將其發(fā)布為 ?@example/my-builder?,請(qǐng)使用以下命令安裝它。

npm install @example/my-builder

創(chuàng)建構(gòu)建器

舉個(gè)例子,讓我們創(chuàng)建一個(gè)用來復(fù)制文件的構(gòu)建器。要?jiǎng)?chuàng)建構(gòu)建器,請(qǐng)使用 CLI 構(gòu)建器函數(shù) ?createBuilder()?,并返回一個(gè) ?Promise<BuilderOutput>? 對(duì)象。

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';

interface Options extends JsonObject {
  source: string;
  destination: string;
}

export default createBuilder(copyFileBuilder);

async function copyFileBuilder(
  options: Options,
  context: BuilderContext,
): Promise<BuilderOutput> {
}

現(xiàn)在,讓我們?yōu)樗砑右恍┻壿?。下列代碼會(huì)從用戶選項(xiàng)中獲取源文件和目標(biāo)文件的路徑,并且把源文件復(fù)制到目標(biāo)文件(使用 NodeJS 內(nèi)置函數(shù)copyFile()的 Promise 版本)。如果文件操作失敗了,它會(huì)返回一個(gè)帶有底層錯(cuò)誤信息的 error 對(duì)象。

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { promises as fs } from 'fs';

interface Options extends JsonObject {
  source: string;
  destination: string;
}

export default createBuilder(copyFileBuilder);

async function copyFileBuilder(
  options: Options,
  context: BuilderContext,
): Promise<BuilderOutput> {
  try {
    await fs.copyFile(options.source, options.destination);
  } catch (err) {
    return {
      success: false,
      error: err.message,
    };
  }

  return { success: true };
}

處理輸出

默認(rèn)情況下,?copyFile()? 方法不會(huì)往標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)錯(cuò)誤中打印任何信息。如果發(fā)生了錯(cuò)誤,可能很難理解構(gòu)建器到底做了什么??梢允褂?nbsp;?Logger ?API 來記錄一些額外的信息,以提供額外的上下文。這樣還能讓構(gòu)建器本身可以在一個(gè)單獨(dú)的進(jìn)程中執(zhí)行,即使其標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤被停用了也無所謂(就像在 Electron 應(yīng)用中一樣)。

你可以從上下文中檢索一個(gè) ?Logger ?實(shí)例。

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { promises as fs } from 'fs';

interface Options extends JsonObject {
  source: string;
  destination: string;
}

export default createBuilder(copyFileBuilder);

async function copyFileBuilder(
  options: Options,
  context: BuilderContext,
): Promise<BuilderOutput> {
  try {
    await fs.copyFile(options.source, options.destination);
  } catch (err) {
    context.logger.error('Failed to copy file.');
    return {
      success: false,
      error: err.message,
    };
  }

  return { success: true };
}

進(jìn)度和狀態(tài)報(bào)告

CLI 構(gòu)建器 API 包含一些進(jìn)度報(bào)告和狀態(tài)報(bào)告工具,可以為某些函數(shù)和接口提供提示信息。

要報(bào)告進(jìn)度,請(qǐng)使用 ?context.reportProgress()? 方法,它接受一個(gè)當(dāng)前值(value)、一個(gè)(可選的)總值(total)和狀態(tài)(status)字符串作為參數(shù)??傊悼梢允侨我鈹?shù)字,比如,如果你知道有多少個(gè)文件需要處理,那么總值可能是這些文件的數(shù)量,而當(dāng)前值是已處理過的數(shù)量。除非傳入了新的字符串,否則這個(gè)狀態(tài)字符串不會(huì)改變。

你可以看看 ?tslint ?構(gòu)建器如何報(bào)告進(jìn)度的例子

在我們的例子中,這種復(fù)制操作或者已完成或者正在執(zhí)行,所以不需要進(jìn)度報(bào)告,但是可以報(bào)告狀態(tài),以便調(diào)用此構(gòu)建器的父構(gòu)建器知道發(fā)生了什么??梢杂?nbsp;?context.reportStatus()? 方法生成一個(gè)任意長(zhǎng)度的狀態(tài)字符串。

注意:
無法保證長(zhǎng)字符串會(huì)完全顯示出來,可以裁剪它以適應(yīng)界面顯示。

傳入一個(gè)空字符串可以移除狀態(tài)。

import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { promises as fs } from 'fs';

interface Options extends JsonObject {
  source: string;
  destination: string;
}

export default createBuilder(copyFileBuilder);

async function copyFileBuilder(
  options: Options,
  context: BuilderContext,
): Promise<BuilderOutput> {
  context.reportStatus(`Copying ${options.source} to ${options.destination}.`);
  try {
    await fs.copyFile(options.source, options.destination);
  } catch (err) {
    context.logger.error('Failed to copy file.');
    return {
      success: false,
      error: err.message,
    };
  }

  context.reportStatus('Done.');
  return { success: true };
}

構(gòu)建器的輸入

你可以通過 CLI 命令間接調(diào)用一個(gè)構(gòu)建器,也可以直接用 Angular CLI 的 ?ng run? 命令來調(diào)用它。無論哪種情況,你都必須提供所需的輸入,但是可以用特定目標(biāo)中預(yù)配置的值作為其默認(rèn)值,然后指定一個(gè)預(yù)定義的、指定的配置進(jìn)行覆蓋,最后在命令行中進(jìn)一步覆蓋這些選項(xiàng)的值。

對(duì)輸入的驗(yàn)證

你可以在該構(gòu)建器的相關(guān) JSON 模式中定義構(gòu)建器都有哪些輸入。建筑師工具會(huì)把解析后的輸入值收集到一個(gè) ?options ?對(duì)象中,并在將其傳給構(gòu)建器函數(shù)之前先根據(jù)這個(gè)模式驗(yàn)證它們的類型。(Schematics 庫也對(duì)用戶輸入做了同樣的驗(yàn)證)。

對(duì)于這個(gè)范例構(gòu)建器,你希望 ?options ?的值是帶有兩個(gè)鍵的 ?JsonObject?:一個(gè)是 ?source?,一個(gè)是 ?destination?,它們都是字符串。

你可以提供如下模式來對(duì)這些值的類型進(jìn)行驗(yàn)證。

{
  "$schema": "http://json-schema.org/schema",
  "type": "object",
  "properties": {
    "source": {
      "type": "string"
    },
    "destination": {
      "type": "string"
    }
  }
}

這是一個(gè)非常簡(jiǎn)單的例子,但這種模式驗(yàn)證也可以非常強(qiáng)大。欲知詳情,參閱 JSON 模式網(wǎng)站。

要把構(gòu)建器的實(shí)現(xiàn)與它的模式和名稱關(guān)聯(lián)起來,你需要?jiǎng)?chuàng)建一個(gè)構(gòu)建器定義文件,可以在 ?package.json? 中指向該文件。

創(chuàng)建一個(gè)名為 ?builders.json? 文件,它看起來像這樣。

{
  "builders": {
    "copy": {
      "implementation": "./dist/my-builder.js",
      "schema": "./src/schema.json",
      "description": "Copies a file."
    }
  }
}

在 ?package.json? 文件中,添加一個(gè) ?builders ?鍵,告訴建筑師工具可以在哪里找到這個(gè)構(gòu)建器定義文件。

{
  "name": "@example/copy-file",
  "version": "1.0.0",
  "description": "Builder for copying files",
  "builders": "builders.json",
  "dependencies": {
    "@angular-devkit/architect": "~0.1200.0",
    "@angular-devkit/core": "^12.0.0"
  }
}

現(xiàn)在,這個(gè)構(gòu)建器的正式名字是 ?@example/copy-file:copy?。第一部分是包名(使用 node 方案進(jìn)行解析),第二部分是構(gòu)建器名稱(使用 ?builders.json? 文件進(jìn)行解析)。

使用某個(gè) ?options ?是非常簡(jiǎn)單的。在上一節(jié),你就曾用過 ?options.source? 和 ?options.destination?。

context.reportStatus(`Copying ${options.source} to ${options.destination}.`);
try {
  await fs.copyFile(options.source, options.destination);
} catch (err) {
  context.logger.error('Failed to copy file.');
  return {
    success: false,
    error: err.message,
  };
}

context.reportStatus('Done.');
return { success: true };

目標(biāo)配置

構(gòu)建器必須有一個(gè)已定義的目標(biāo),此目標(biāo)會(huì)把構(gòu)建器與特定的輸入配置和項(xiàng)目關(guān)聯(lián)起來。

目標(biāo)是在 CLI 配置文件 ?angular.json? 中定義的。目標(biāo)用于指定要使用的構(gòu)建器、默認(rèn)的選項(xiàng)配置,以及指定的備用配置。建筑師工具使用目標(biāo)定義來為一次特定的執(zhí)行解析輸入選項(xiàng)。

?angular.json? 文件中為每個(gè)項(xiàng)目都有一節(jié)配置,每個(gè)項(xiàng)目的 ?architect ?部分都會(huì)為 CLI 命令(比如 ?build?、?test ?和 ?lint?)配置構(gòu)建器目標(biāo)。默認(rèn)情況下,?build ?命令會(huì)運(yùn)行 ?@angular-devkit/build-angular:browser? 構(gòu)建器來執(zhí)行 ?build ?任務(wù),并傳入 ?angular.json? 中為 ?build ?目標(biāo)指定的默認(rèn)選項(xiàng)值。

{
  "myApp": {
    …
    "architect": {
      "build": {
        "builder": "@angular-devkit/build-angular:browser",
        "options": {
          "outputPath": "dist/myApp",
          "index": "src/index.html",
          …
        },
        "configurations": {
          "production": {
            "fileReplacements": [
              {
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.prod.ts"
              }
            ],
            "optimization": true,
            "outputHashing": "all",
            …
          }
        }
      },
      …

該命令會(huì)給構(gòu)建器傳遞 options 節(jié)中指定的一組默認(rèn)選項(xiàng)。如果你傳入了 --configuration=production 標(biāo)志,它就會(huì)使用 production 備用配置中指定的值進(jìn)行覆蓋??梢栽诿钚兄袉为?dú)指定其它選項(xiàng)進(jìn)行覆蓋,還可以為 build 目標(biāo)添加更多備用配置,以定義其它環(huán)境,比如 stage 或 qa。

目標(biāo)字符串

通用的 ?ng run? CLI 命令將以下格式的目標(biāo)字符串作為其第一個(gè)參數(shù)。

project:target[:configuration]

詳情

項(xiàng)目(project)

與此目標(biāo)關(guān)聯(lián)的 Angular CLI 項(xiàng)目的名稱。

目標(biāo)

angular.json 文件 architect 下的指定構(gòu)建器配置。

配置(configuration)

(可選)用于覆蓋指定目標(biāo)的具體配置名稱,如 angular.json 文件中的定義。

如果你的構(gòu)建器調(diào)用另一個(gè)構(gòu)建器,它可能需要讀取一個(gè)傳入的目標(biāo)字符串。可以使用 ?@angular-devkit/architect? 中的工具函數(shù) ?targetFromTargetString()? 把這個(gè)字符串解析成一個(gè)對(duì)象。

調(diào)度并運(yùn)行

建筑師會(huì)異步運(yùn)行構(gòu)建器。要調(diào)用某個(gè)構(gòu)建器,就要在所有配置解析完成之后安排一個(gè)要運(yùn)行的任務(wù)。

在調(diào)度器返回 ?BuilderRun ?控件對(duì)象之前,不會(huì)執(zhí)行該構(gòu)建器函數(shù)。CLI 通常會(huì)通過調(diào)用 ?context.scheduleTarget()? 函數(shù)來調(diào)度任務(wù),然后使用 ?angular.json? 文件中的目標(biāo)定義來解析輸入選項(xiàng)。

建筑師會(huì)接受默認(rèn)的選項(xiàng)對(duì)象來解析指定目標(biāo)的輸入選項(xiàng),然后覆蓋所用配置中的值(如果有的話),然后再?gòu)膫鹘o ?context.scheduleTarget()? 的覆蓋對(duì)象中覆蓋這些值。對(duì)于 Angular CLI,覆蓋對(duì)象是從命令行參數(shù)中構(gòu)建的。

建筑師會(huì)根據(jù)構(gòu)建器的模式對(duì)生成的選項(xiàng)值進(jìn)行驗(yàn)證。如果輸入有效,建筑師會(huì)創(chuàng)建上下文并執(zhí)行該構(gòu)建器。

你還可以通過調(diào)用 ?context.scheduleBuilder()? 從另一個(gè)構(gòu)建器或測(cè)試中調(diào)用某個(gè)構(gòu)建器。你可以直接把 ?options ?對(duì)象傳給該方法,并且這些選項(xiàng)值會(huì)根據(jù)這個(gè)構(gòu)建器的模式進(jìn)行驗(yàn)證,而無需進(jìn)一步調(diào)整。
只有 ?context.scheduleTarget()? 方法來解析這些配置和并通過 ?angular.json? 文件進(jìn)行覆蓋。

默認(rèn)建筑師配置

讓我們創(chuàng)建一個(gè)簡(jiǎn)單的 ?angular.json? 文件,它會(huì)把目標(biāo)配置放到上下文中。

你可以把這個(gè)構(gòu)建器發(fā)布到 npm,并使用如下命令來安裝它:

npm install @example/copy-file

如果用 ?ng new builder-test? 創(chuàng)建一個(gè)新項(xiàng)目,那么生成的 ?angular.json? 文件就是這樣的,它只有默認(rèn)的構(gòu)建器參數(shù)。

{
  // …
  "projects": {
    // …
    "builder-test": {
      // …
      "architect": {
        // …
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            // … more options…
            "outputPath": "dist/builder-test",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json"
          },
          "configurations": {
            "production": {
              // … more options…
              "optimization": true,
              "aot": true,
              "buildOptimizer": true
            }
          }
        }
      }
    }
  }
  // …
}

添加一個(gè)目標(biāo)

添加一個(gè)新的目標(biāo),來運(yùn)行我們的構(gòu)建器以復(fù)制文件。該目標(biāo)告訴構(gòu)建器,復(fù)制 ?package.json? 文件。

你需要更新 ?angular.json? 文件,把這個(gè)構(gòu)建器的目標(biāo)添加到新項(xiàng)目的 ?architect ?部分。

  • 我們會(huì)為項(xiàng)目的 ?architect ?對(duì)象添加一個(gè)新的目標(biāo)小節(jié)
  • 名為 ?copy-package? 的目標(biāo)使用了我們的構(gòu)建器,它發(fā)布到了 ?@example/copy-file?。
  • 這個(gè)配置對(duì)象為我們定義的兩個(gè)輸入提供了默認(rèn)值:?source?(你要復(fù)制的現(xiàn)有文件)和 ?destination?(你要復(fù)制到的路徑)
  • 這些配置鍵都是可選的,但我們先不展開
{
  "projects": {
    "builder-test": {
      "architect": {
        "copy-package": {
          "builder": "@example/copy-file:copy",
          "options": {
            "source": "package.json",
            "destination": "package-copy.json"
          }
        },
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/builder-test",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json"
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "aot": true,
              "buildOptimizer": true
            }
          }
        }
      }
    }
  }
}

運(yùn)行這個(gè)構(gòu)建器

要想使用這個(gè)新目標(biāo)的默認(rèn)配置運(yùn)行我們的構(gòu)建器,請(qǐng)使用以下 CLI 命令。

ng run builder-test:copy-package

這將把 ?package.json? 文件復(fù)制成 ?package-copy.json?。

你可以使用命令行參數(shù)來覆蓋已配置的默認(rèn)值。比如,要改用其它 ?destination ?值運(yùn)行,請(qǐng)使用以下 CLI 命令。

ng run builder-test:copy-package --destination=package-other.json

這將把此文件復(fù)制為 ?package-other.json? 而不再是 ?package-copy.json?。因?yàn)槲覀儧]有覆蓋 source 選項(xiàng),所以它仍然會(huì)從 ?package.json? 文件復(fù)制(提供給該目標(biāo)的默認(rèn)值)。

測(cè)試一個(gè)構(gòu)建器

對(duì)構(gòu)建器進(jìn)行集成測(cè)試,以便你可以使用建筑師的調(diào)度器來創(chuàng)建一個(gè)上下文,就像這個(gè)例子中一樣。

  • 在構(gòu)建器的源碼目錄下,你創(chuàng)建了一個(gè)新的測(cè)試文件 ?my-builder.spec.ts?。該代碼創(chuàng)建了 ?JsonSchemaRegistry?(用于模式驗(yàn)證)、?TestingArchitectHost?(對(duì) ?ArchitectHost ?的內(nèi)存實(shí)現(xiàn))和 ?Architect ?的新實(shí)例。
  • 我們緊挨著這個(gè)構(gòu)建器的 ?package.json? 文件添加了一個(gè) ?builders.json? 文件,并修改了 ?package.json? 文件以指向它。

下面是運(yùn)行此復(fù)制文件構(gòu)建器的測(cè)試范例。該測(cè)試使用該構(gòu)建器來復(fù)制 ?package.json? 文件,并驗(yàn)證復(fù)制后的文件內(nèi)容與源文件相同。

import { Architect } from '@angular-devkit/architect';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
import { schema } from '@angular-devkit/core';
import { promises as fs } from 'fs';

describe('Copy File Builder', () => {
  let architect: Architect;
  let architectHost: TestingArchitectHost;

  beforeEach(async () => {
    const registry = new schema.CoreSchemaRegistry();
    registry.addPostTransform(schema.transforms.addUndefinedDefaults);

    // TestingArchitectHost() takes workspace and current directories.
    // Since we don't use those, both are the same in this case.
    architectHost = new TestingArchitectHost(__dirname, __dirname);
    architect = new Architect(architectHost, registry);

    // This will either take a Node package name, or a path to the directory
    // for the package.json file.
    await architectHost.addBuilderFromPackage('..');
  });

  it('can copy files', async () => {
    // A "run" can have multiple outputs, and contains progress information.
    const run = await architect.scheduleBuilder('@example/copy-file:copy', {
      source: 'package.json',
      destination: 'package-copy.json',
    });

    // The "result" member (of type BuilderOutput) is the next output.
    const output = await run.result;

    // Stop the builder from running. This stops Architect from keeping
    // the builder-associated states in memory, since builders keep waiting
    // to be scheduled.
    await run.stop();

    // Expect that the copied file is the same as its source.
    const sourceContent = await fs.readFile('package.json', 'utf8');
    const destinationContent = await fs.readFile('package-copy.json', 'utf8');
    expect(destinationContent).toBe(sourceContent);
  });
});

在你的倉(cāng)庫中運(yùn)行這個(gè)測(cè)試時(shí),需要使用 ts-node 包。你可以把 ?index.spec.ts? 重命名為 ?index.spec.js? 來回避它。

監(jiān)視(watch)模式

建筑師希望構(gòu)建器運(yùn)行一次(默認(rèn)情況下)并返回。這種行為與那些需要監(jiān)視文件更改的構(gòu)建器(比如 Webpack)并不完全兼容。建筑師可以支持監(jiān)視模式,但要注意一些問題。

  • 要在監(jiān)視模式下使用,構(gòu)建器處理函數(shù)應(yīng)返回一個(gè) Observable。建筑師會(huì)訂閱這個(gè) Observable,直到這個(gè) Observable 完成(complete)為止。此外,如果使用相同的參數(shù)再次調(diào)度這個(gè)構(gòu)建器,建筑師還能復(fù)用這個(gè) Observable。
  • 這個(gè)構(gòu)建器應(yīng)該總是在每次執(zhí)行后發(fā)出一個(gè) ?BuilderOutput ?對(duì)象。一旦它被執(zhí)行,就會(huì)進(jìn)入一個(gè)由外部事件觸發(fā)的監(jiān)視模式。如果一個(gè)事件導(dǎo)致它重啟,那么此構(gòu)建器應(yīng)該執(zhí)行 ?context.reportRunning()? 函數(shù)來告訴建筑師再次運(yùn)行它。如果調(diào)度器還計(jì)劃了另一次運(yùn)行,就會(huì)阻止建筑師停掉這個(gè)構(gòu)建器。

當(dāng)你的構(gòu)建器通過調(diào)用 ?BuilderRun.stop()? 來退出監(jiān)視模式時(shí),建筑師會(huì)從構(gòu)建器的 Observable 中取消訂閱,并調(diào)用構(gòu)建器的退出邏輯進(jìn)行清理。(這種行為也允許停止和清理運(yùn)行時(shí)間過長(zhǎng)的構(gòu)建。)

一般來說,如果你的構(gòu)建器正在監(jiān)視一個(gè)外部事件,你應(yīng)該把你的運(yùn)行分成三個(gè)階段。

階段

詳情

運(yùn)行

比如 webpack 編譯。這會(huì)在 webpack 完成并且你的構(gòu)建器發(fā)出 BuilderOutput 對(duì)象時(shí)結(jié)束。

監(jiān)視

在兩次運(yùn)行之間監(jiān)視外部事件流。比如,webpack 會(huì)監(jiān)視文件系統(tǒng)是否發(fā)生了任何變化。這會(huì)在 webpack 重啟構(gòu)建時(shí)結(jié)束,并調(diào)用 context.reportRunning()。這樣就會(huì)再回到第 1 步。

完成

任務(wù)完全完成(比如,webpack 應(yīng)運(yùn)行多次),或者構(gòu)建器停止運(yùn)行(使用 BuilderRun.stop())。你的退出邏輯被調(diào)用了,建筑師也從你的構(gòu)建器的 Observable 中取消了訂閱。

總結(jié)

CLI 構(gòu)建器 API 提供了一種通過構(gòu)建器執(zhí)行自定義邏輯,以改變 Angular CLI 行為的新方式。

  • 構(gòu)建器既可以是同步的,也可以是異步的,它可以只執(zhí)行一次也可以監(jiān)視外部事件,還可以調(diào)度其它構(gòu)建器或目標(biāo)
  • 構(gòu)建器在 ?angular.json? 配置文件中指定了選項(xiàng)的默認(rèn)值,它可以被目標(biāo)的備用配置覆蓋,還可以進(jìn)一步被命令行標(biāo)志所覆蓋
  • 建議你使用集成測(cè)試來測(cè)試建筑師的構(gòu)建器。還可以用單元測(cè)試來驗(yàn)證這個(gè)構(gòu)建器的執(zhí)行邏輯。
  • 如果你的構(gòu)建器返回一個(gè) Observable,你應(yīng)該在那個(gè) Observable 的退出邏輯中進(jìn)行清理


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)