For a long time, front-end engineering configurations are mostly.js files or.json files. The most common ones are:

  • package.json
  • babel.config.js
  • webpack.config.js

These configurations are very front-end friendly because they are all familiar JS object structures. Json files are generally selected for static configurations, while js files are selected for dynamic configurations, which involve importing other modules.

Also, many new tools now support multiple configurations at the same time, such as Eslint, where you can choose between two configurations:

  • .eslintrc.json
  • .eslintrc.js

Then, out of nowhere, a configuration file with a.yaml or.yml suffix appeared. At first it was thought to be a program-specific configuration, but then files with this suffix became more frequent, and even Eslint supported a third configuration. Eslintrc.yml.

Now that you’ve found it, explore it!

Here we take a look at the mysteries of YAML, a popular modern configuration, in terms of its background, usage, usage, and advanced operations.

In the background

A new tool is inevitable for two reasons:

  1. Older tools struggle in some scenarios and require better alternatives
  2. There’s nothing wrong with the old tool, it’s just that the new tool comes along and it’s not so good by comparison, right

New tools like YAML fall into the latter category. In fact, before the advent of YAML JS + JSON is also good, there is no particularly difficult to deal with the problem; But after yamL appeared, I began to think it was so messy. After I learned about it, THE more I used it, the more I liked it. A word was elegant.

Many articles say that yamL was chosen because of the various issues with JSON, and that JSON is not suitable for configuration files, which I think is a bit of an overstatement. I prefer to think of YAML as an upgrade to JSON, because YAML does a pretty good job of formatting simplification and experience, admittedly.

Let’s compare YAML and JSON in two ways:

What has been streamlined?

What makes JSON tedious is its strict formatting requirements. For example, this object:

{
  name: 'ruims'
}
Copy the code

All of the following are incorrect in JSON:

// key cannot be quoted
{
  name: 'ruims'
}
// the key is not ""
{
  'name': 'ruims'
}
// if the value is not"
{
  "name": 'ruims'
}
Copy the code

String values k->v must be “” :

// This is the only way
{
  "name": "ruims"
}
Copy the code

Although it is a unified format, but the use does have inconvenient places. Let’s say I detect an interface error on my browser. Then I copy the parameters to Postman for debugging, and then I have to manually add “” to each attribute and value, which is very tedious.

YAML takes a different approach and does away with string symbols. The equivalent YAML configuration for the above objects is as follows:

name: ruims
Copy the code

Yes, it’s that simple!

In addition to the “” sign, Yaml thinks {} and [] symbols are redundant and should be killed together.

So, take this array of objects:

{
  "names": [{ "name": "ruims" }, { "name": "ruidoc"}}]Copy the code

The conversion to YAML looks like this:

names:
  - name: ruims
  - name: ruidoc
Copy the code

What’s not to love about this simplification?

What’s added?

Speaking of additions, the most notable is YAML’s support for annotations.

JSON configuration cannot be annotated, which means that there will be no comments on our configuration, which will be very messy, which is the most inhumane part.

Now that YAML supports remarks, the configuration could look something like this:

# app name
name: my_app
# Application port
port: 8080
Copy the code

Throw this configuration at a new colleague, and you’re afraid he won’t understand it?

In addition to annotations, configuration reuse is supported, as described later.

Usage scenarios

The first YAML configuration I came across was the package management file pubspec.yaml for the Flutter project. This file acts as a package.json file for the front-end project to store some global configurations and application dependent packages and versions.

Take a look at its basic structure:

name: flutter_demo
description: A new Flutter project.

publish_to: 'none'
version: 1.0. 0

dependencies:
  cupertino_icons: ^ 1.0.2

dev_dependencies:
  flutter_lints: ^ 1.0.0
Copy the code

Do you see the same structure as package.json? The following list lists application dependencies and versions. Dev_dependencies describes development dependencies.

We later used GitHub Action for CI/CD automation deployment. It requires multiple YAML files to define different workflows, a much more complex configuration than Flutter.

In fact, not only GitHub Action, but other popular similar build tools such as GitLab CI/CD and Circleci are all full of YAML configurations, so if you want to do CI/CD continuous integration for your project, you will not be able to understand yamL syntax.

Docker Compose is the official stand-alone editing tool of Docker, and its configuration file docker-comemage. yml is also in yamL format. Docker is now in its heyday, and the use of Docker is bound to be choreographed, so yamL syntax will have to be conquered sooner or later.

The three examples above are almost all the latest and most popular frameworks/tools in modern times. They show that YAML is bound to be the standard for the next generation of configuration files and a common standard for front-end, back-end, operations and maintenance.

With all that said, are you itching to try? Let’s take a closer look at yamL syntax.

YAML syntax

The YAML syntax will be compared to the JSON interpretation for quick understanding.

Let’s start with a few features of YAML:

  • Case sensitivity
  • Use indentation to indicate hierarchy
  • The number of indent Spaces is not mandatory, but the same level should be aligned
  • #Said annotation

The biggest difference compared to JSON is the indentation of the hierarchy, which is very similar to Python. Another enhancement is support for annotations, which is not supported by JSON by default (although TS does), which is also important for configuration files.

YAML supports the following data structures:

  • object: object in JSON
  • An array of: Array in JSON
  • scalarSimple types in JSON (strings, values, booleans, etc.)

object

Let’s start with an object. Here’s a json example:

{
  "id": 1."name": "Yang Chenggong"."isman": true
}
Copy the code

Convert to YAML:

id: 1
name: Yang Chenggong
isman: true
Copy the code

[key] [key] [key] [key] [key] [key] [key] [key] [key] [key] The value of value is a scalar and does not need quotes by default.

An array of

An array is similar to an object except that it uses a – symbol before the key to indicate that it is an array item. Notice that there is a space here as well, which is also important.

- hello
- world
Copy the code

Convert to JSON format as follows:

["hello"."world"]
Copy the code

Now that you know the basics of objects and arrays, let’s look at a more complex structure.

As we all know, there are very few simple objects or arrays in real project configuration. Most are nested objects and arrays. In JS we call it an array of objects, and in YAML we call it a composite structure.

For example, here is a slightly more complex JSON:

{
  "name": "Yang Chenggong"."isman": true."age": 25."tag": ["The sun"."Handsome"]."address": [{"c": "Beijing"."a": Haidian District },
    { "c": "Tianjin"."a": "Binhai New Area"}}]Copy the code

YAML converted to composite structure:

name: Yang Chenggong
isman: true
age: 25
tag:
  - The sun
  - handsome
address:
  - c: Beijing
    a: Haidian district,
  - c: tianjin
    a: Binhai new area
Copy the code

If you want to try a more complex structure, you can do it online on this page.

scalar

Scalar is relatively simple, corresponding to the basic js data type, support as follows:

  • string
  • Boolean
  • The numerical
  • null
  • time

For the two special ones, null is represented by ~ symbol, and the time is mostly represented by the format of 2021-12-21, as follows:

who: ~
date: 2019-09-10
Copy the code

After converting to JS:

{
  who: null.date: new Date('2019-09-10')}Copy the code

Advanced operation

During the actual yamL operation, some special scenarios may require special treatment.

String too long

In shell, we often see some very long commands with many parameters. If the commands are written on one line, the readability will be very poor.

Suppose the following command is a long one:

$ docker run --name my-nginx -d nginx
Copy the code

In Linux you can do this:

$docker run \ --name my-nginx \ -d nginx
Copy the code

A \ symbol is added after each line to indicate a newline. In YAML, however, it’s much simpler. You don’t need to add any symbols, just wrap:

cmd: docker run
  --name my-nginx
  -d nginx
Copy the code

YAML converts newlines to Spaces by default, so the resulting JSON looks like this, which is exactly what we need:

{ "cmd": "docker run --name my-nginx -d nginx" }
Copy the code

What if, however, we need to preserve the newline character instead of converting it to a space?

This is simple, only need to first add a | symbol:

cmd: | docker run --name my-nginx -d nginxCopy the code

Converting to JSON looks like this:

{ "cmd": "docker run\n--name my-nginx\n-d nginx" }
Copy the code

Access to the configuration

Getting a configuration is a configuration defined in a YAML file. How to get it in code (JS)?

For example, the front-end has a version configuration item in package.json to indicate the version of the application, and we need to obtain the version in the code, we can write:

import pack from './package.json'
console.log(pack.version)
Copy the code

JSON can be imported directly, but YAML can’t. We are divided into the environment analysis:

In the browser

The browser code is packaged with Webapck, so add a loader:

$ yarn add -D yaml-loader
Copy the code

Then configure loader:

// webpack.config.js
module.exports = {
  module: {
    rules: [{test: /\.ya? ml$/,
        type: 'json'.// Required by Webpack v4
        use: 'yaml-loader'}}}]Copy the code

Use in components:

import pack from './package.yaml'
console.log(pack.version)
Copy the code

In the Node. Js

Node.js does not have Webpack, so the yamL configuration is read differently.

First install a JS-YAML module:

$ yarn add js-yaml
Copy the code

We then get it from the methods provided by the module:

const yaml = require('js-yaml')
const fs = require('fs')

const doc = yaml.load(fs.readFileSync('./package.yaml'.'utf8'))
console.log(doc.version)
Copy the code

Configuration item reuse

Configuration item reuse means that the defined configuration is directly referenced in subsequent configurations instead of being written again for reuse.

YAML defines reusable items as anchors, identified by &; Reference anchors are identified with *.

name: &name my_config
env: &env
  version: 1.0

compose:
  key1: *name
  key2: *env
Copy the code

The corresponding JSON is as follows:

{
  "name": "my_config"."env": { "version": 1 },
  "compose": { "key1": "my_config"."key2": { "version": 1}}}Copy the code

But the downside of anchors is that they can’t be used as variables in strings. Such as:

name: &name my_config
compose:
  key1: *name
  key2: my name is *name
Copy the code

The value of key2 is the plain string my name is *name, and the reference becomes invalid.

In practice, it is quite common to use variables in strings. For example, if a path is used multiple times in a complex command, the path should be a variable that can be reused across multiple commands.

GitHub actions have support for defining an environment variable and then reusing it elsewhere:

env:
  NAME: test
describe: This app is called ${NAME}
Copy the code

This implementation is similar to using environment variables in WebPack, replacing them with the corresponding strings at build time.

My column

This article was first published in the front end DevOps column of Nuggets. This column will output front-end engineering and architecture articles for a long time. After practice and consideration, the quality is guaranteed as always.

If this article inspires you, please give a thumbs up to 👍