---
url: /zh/build/simplify-configuration.md
description: 介绍如何利用 YAML 锚点、别名和对象合并语法，以及 include 文件引用机制来简化和复用 .cnb.yml 流水线配置文件。
---
## YAML 高级语法

由于 `.cnb.yml` 采用 YAML 格式，可利用 YAML 的锚点 `&`、别名 `*` 和合并语法 `<<` 来精简配置、减少重复。

以下示例使用锚点和别名简化配置，展示基础用法和拆分复用：

```yaml title=".cnb.yml"
# 定义流水线锚点并在多事件中复用
.pipeline: &pipeline
  docker:
    image: node:22
  stages:
    - name: install
      script: npm install
    - name: test
      script: npm test

main:
  pull_request:
    - <<: *pipeline
  push:
    - <<: *pipeline
```

单文件内重复较多时，可拆分 stages 为独立锚点：

```yaml title=".cnb.yml"
.stages: &stages
  - name: install
    script: npm install
  - name: test
    script: npm test

.pipeline: &pipeline
  docker:
    image: node:22
  stages: *stages

main:
  pull_request:
    - <<: *pipeline
  push:
    - <<: *pipeline
```

:::tip

以上是 `YAML` 自带特性，仅在解析单个 YAML 文件时有效，不能跨文件使用。

此外，锚点会降低可读性：多个分支引用时阅读者需反复跳转才能看清完整配置。
当流水线超过 3 次引用同一锚点时，建议改用 [include](#include) 跨文件复用，
或抽取为独立模板文件，使每个文件独立可读。

:::

## 文件引用

为复用流水线配置，云原生构建提供了以下特性：

* [include](./grammar.md#include)：可以跨文件引用流水线模板。
* [imports](./grammar.md#pipeline-imports)：可以跨文件引用变量。
* [optionsFrom](./grammar.md#job-optionsfrom)：可以跨文件引用内置任务参数。
* [settingsFrom](./grammar.md#job-settingsfrom)：可以跨文件引用插件任务参数。

详细文件引用说明见 [文件引用](./file-reference.md)

## 变量引用

YAML 锚点和别名无法跨文件复用，云原生构建通过以下特性解决该问题：

### reference（扩展标签）

YAML 标准不支持跨文件引用。云原生构建通过扩展的 `!reference` 标签
实现按属性路径引用值的功能，可与 [include](#include) 配合使用，
实现跨文件配置复用。

:::tip 注意

1. `!reference` 支持嵌套引用，最多 10 层。
2. 合并配置时，同名的顶层变量会被覆盖，不会深度合并。
3. 解析顺序：先加载并合并所有 `include` 的文件与主文件 `.cnb.yml`，
   **然后**再解析 `!reference` 标签。
   合并过程基于原始文本，不感知引用解析后的值。
   :::

#### 示例 {#reference-example}

```yaml title="a.yml"
.val1:
  echo1: echo hello
.val2:
  friends:
    - one:
        name: tom
        say: !reference [.val1, echo1] # 引用本文件内的值
```

```yaml title=".cnb.yml"
include:
  - ./a.yml # 引入 a.yml

.val3:
  size: 100

main:
  push:
    - stages:
        - name: echo hello
          # 跨文件引用 a.yml 中的值
          script: !reference [.val2, friends, "0", say]
        - name: echo size
          env:
            # 引用本文件 .cnb.yml 中的值
            SIZE: !reference [".val3", "size"]
          script: echo my size ${SIZE}
```

**解析后的等效配置：**

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: echo hello
          script: echo hello # 解析后的值
        - name: echo size
          env:
            SIZE: 100 # 解析后的值
          script: echo my size ${SIZE}
```

#### 进阶示例：复用整条流水线

```yaml title=".cnb.yml"
.common-pipeline:
  - stages:
      - name: echo
        script: echo hello

main:
  push: !reference [.common-pipeline] # 引用整条流水线
test:
  push: !reference [.common-pipeline] # 引用整条流水线
```

**解析后的等效配置：**

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: echo
          script: echo hello
test:
  push:
    - stages:
        - name: echo
          script: echo hello
```

#### VSCode 配置

在 VSCode 中编写带 `!reference` 标签的 YAML 文件时，需配置以下内容以避免语法报错：

在 `settings.json` 中添加：

```json
{
  "yaml.customTags": ["!reference sequence"]
}
```

:::tip

为避免系统根据 schema 将顶层变量名误识别为分支名而产生错误提示，
建议用点号 (`.`) 开头来命名用于 `reference` 的顶层变量（例如 `.var`）。
:::
