36
头图
The source of this article is the public number: Programmer successfully

For a long time, most of the configurations in front-end projects are .js files or .json files. The most common ones are:

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

These configurations are very friendly to the front end because they are all familiar JS object structures. Generally, the static configuration will select the json file, while the dynamic configuration involves the introduction of other modules, so the js file will be selected.

There are also many new tools that support multiple configurations at the same time, such as Eslint . You can choose between two formats of configuration:

  • .eslintrc.json
  • .eslintrc.js

Later, I don't know when, a configuration file with a suffix of .yaml or .yml suddenly appeared. At first I thought it was a proprietary configuration of a program, but later found that files with this suffix appeared more and more frequently, and even Eslint supported the third format configuration .eslintrc.yml .

Now that you've encountered it, explore it!

Here we YAML from the appear background , usage scenarios , specific usage , advanced operating four aspects, look at this mystery from the configuration of modern popular.

background appears

The emergence of a new tool is inevitable for two reasons:

  1. Old tools struggle in some scenarios and require better alternatives
  2. There's nothing wrong with the old tools, it's just that the new tools appear and it's not that good in comparison

The new tool, YAML, falls into the latter category. In fact, before yaml appeared, js+json was used well, and there were no particularly difficult problems to deal with; but after yaml appeared, I began to think that it was a mess. Later, after I learned about it, the more I used it, the more I liked it. One word is elegance.

Many articles say that yaml is chosen because of various problems with json, and json is not suitable for configuration files, which I think is a bit exaggerated. I prefer to regard yaml as an upgrade of json, because yaml is really good in terms of format simplification and experience, this must be admitted.

Let's compare YAML and JSON, and analyze from two aspects:

Streamlined what?

Where JSON is cumbersome is its strict format requirements. For example this object:

{
  name: 'ruims'
}

All of the following in JSON are wrong:

// key 没引号不行
{
  name: 'ruims'
}
// key 不是 "" 号不行
{
  'name': 'ruims'
}
// value 不是 "" 号不行
{
  "name": 'ruims'
}

The value of the string must be "" for k->v:

// 只能这样
{
  "name": "ruims"
}

Although it is a unified format, it is indeed inconvenient to use. For example, I detected an interface error on the browser. Then copy the parameters to Postman for debugging. At this time, I have to manually add "" to each attribute and value, which is very cumbersome.

YAML takes a different approach and directly kills the string symbols. The equivalent yaml configuration for the above object is as follows:

name: ruims

Yes, it's that simple!

In addition to "" number, yaml feels that the symbols {} and [] are redundant, so it is better to kill them together.

So, take this array of objects as an example:

{
  "names": [{ "name": "ruims" }, { "name": "ruidoc" }]
}

Converted to yaml like this:

names:
  - name: ruims
  - name: ruidoc

Contrasting this level of simplicity, what's not to love about it?

What is added?

Speaking of the added part, the most worth mentioning is that YAML supports comments.

The configuration written in JSON cannot have comments, which means that our configuration will not have comments, and the configuration will be very messy, which is the most inhumane place.

Now that yaml supports remarks, the future configuration can be like this:

# 应用名称
name: my_app
# 应用端口
port: 8080

If you throw this configuration to a new colleague, are you afraid that he won't understand what it is configured for?

In addition to annotations, it also supports configuration reuse related functions, which will be described later.

scenes to be used

The first yaml configuration I came into contact with was the package management file pubspec.yaml of the Flutter project. The function of this file is the same as that of package.json in the front-end project. It is used to store some global configuration 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

Do you think this structure is basically the same as package.json ? Application dependencies and versions are listed under dependencies , while development dependencies are listed under dev_dependencies .

Later, when doing CI/CD automated deployment, we used GitHub Action . It requires multiple yaml files to define different workflows, and this configuration is much more complicated than flutter.

In fact, not only GitHub Action, but other popular similar build tools such as GitLab CI/CD , circleci , all are yaml configurations, so if your project needs CI/CD continuous integration, you don't know yaml Grammar definitely doesn't work.

In addition, students who have been exposed to Docker must know Docker Compose, which is the official stand-alone orchestration tool of Docker, and its configuration file docker-compose.yml is also a proper yaml format. Now that Docker is in its prime, using Docker will inevitably lead to orchestration, so yaml syntax will have to be conquered sooner or later.

The three cases mentioned above are almost all the latest and most popular frameworks/tools in modern times. It can be seen from them that yaml must be the standard for the next generation of configuration files, and is a common standard for front-end-back-end-operation and maintenance .

Having said so much, are you ready to try it? Below we describe the yaml syntax in detail.

YAML syntax

Introducing the yaml syntax will compare the json interpretation for our quick understanding.

Let's take a look at a few features of yaml:

  • Case Sensitive
  • Use indentation to indicate hierarchy
  • The number of indent spaces is not mandatory, but the same level should be aligned
  • # for comments

Compared to JSON, the biggest difference is that indents are used to represent levels, which is very close to Python. Another enhancement is that comments are supported, JSON is not supported by default (although TS supports it), which is also very important for configuration files.

YAML supports the following data structures:

  • object: object in json
  • array: array in json
  • : simple types in json (string, numeric, boolean, etc.)

object

First look at the object, the previous json example:

{
  "id": 1,
  "name": "杨成功",
  "isman": true
}

Convert to yaml:

id: 1
name: 杨成功
isman: true

The object is the core structure. The key value is represented by [key]: . Note that there is a space after the colon in 162438d35c8536, and must not be . The value of value is a scalar, and no quotes are required by default.

array

The structures of arrays and objects are similar, the difference is that a - symbol is used before the key to indicate that this is an array item. Note that also has a space , which cannot be less.

- hello
- world

Convert to JSON format as follows:

["hello", "world"]

Knowing the basic objects and arrays, let's look at a complex structure.

As we all know, there are few simple objects or arrays in the actual project configuration, and most of them 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, a slightly complex JSON like this:

{
  "name": "杨成功",
  "isman": true,
  "age": 25,
  "tag": ["阳光", "帅气"],
  "address": [
    { "c": "北京", "a": "海淀区" },
    { "c": "天津", "a": "滨海新区" }
  ]
}

YAML converted to composite structure:

name: 杨成功
isman: true
age: 25
tag:
  - 阳光
  - 帅气
address:
  - c: 北京
    a: 海淀区
  - c: 天津
    a: 滨海新区

If you want to try the conversion of more complex structures, you can practice online in the webpage .

scalar

Scalar is relatively simple, and corresponds to the basic data type of js. The support is as follows:

  • string
  • boolean
  • Numerical value
  • null
  • time

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

who: ~
date: 2019-09-10

After converting to JS:

{
  who: null,
  date: new Date('2019-09-10')
}

Advanced Operations

In the actual combat process of yaml, some special scenarios have been encountered, which may require some special processing.

String is too long

In the shell, we often see some commands with a lot of parameters, and then very long commands. If the commands are written in one line, the readability will be very poor.

Suppose the following is a long command:

$ docker run --name my-nginx -d nginx

In linux it can be done like this:

$ docker run \
 --name my-nginx \
 -d nginx

It is to add \ symbol after each line to mark the line break. However, it is simpler in YAML, no need to add any symbols, just wrap the line:

cmd: docker run
  --name my-nginx
  -d nginx

YAML will convert newlines to spaces by default, so the converted JSON is as follows, which is exactly what we need:

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

However, sometimes, our requirement is that retains the newline character , instead of converting it to a space, what should we do?

This is also simple, just add a | symbol to the first line:

cmd: |
  docker run
  --name my-nginx
  -d nginx

Converting to JSON becomes this:

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

get configuration

Obtaining the configuration refers to how to obtain a configuration defined in the YAML file in the code (JS)?

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

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

JSON can be imported directly, but YAML cannot. So what should we do? We analyze by environment:

in browser

The code in the browser is packaged with webapck, so add a loader:

$ yarn add -D yaml-loader

Then configure the loader:

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

Use in component:

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

in Node.js

There is no Webpack in the Node.js environment, so the way to read the yaml configuration is also different.

First install a js-yaml module:

$ yarn add js-yaml

Then get it through the method 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)

Configuration item reuse

Configuration item reuse means that for the defined configuration, it is directly referenced in the subsequent configuration instead of writing it again, so as to achieve the purpose of reuse.

The multiplexed item defined in YAML is called the anchor point, which is identified with & ; the reference anchor point is identified with * .

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

compose:
  key1: *name
  key2: *env

The corresponding JSON is as follows:

{
  "name": "my_config",
  "env": { "version": 1 },
  "compose": { "key1": "my_config", "key2": { "version": 1 } }
}

But the anchor point has the disadvantage that it cannot be used as a variable in a string. for example:

name: &name my_config
compose:
  key1: *name
  key2: my name is *name

At this time, the value of key2 is the ordinary string _my name is *name_, and the reference becomes invalid.

In fact, in actual development, it is still very common to use variables in strings. For example, if a certain path is used multiple times in a complex command, this path should be a variable and reused in multiple commands.

GitHub Action has support for this, define an environment variable and reuse it elsewhere:

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

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

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

i want to learn more

In order to better protect the originality, I will first publish the following articles on the WeChat public front-end . This official account only does original work, with at least one high-quality article per week, and the direction is front-end engineering and architecture, front-end boundary exploration at the BFF layer, and practice and thinking such as integrated development and delivery.

In addition, I also set up a WeChat group to provide exchanges and learning for students who are interested in this direction. In the group, there are big factory bosses, Nuggets lv6 gods, and more students who want to study this direction. Let's communicate and share learning together~

If you are also interested and want to learn more, please add me on WeChat ruidoc to pull you into the group~


杨成功
3.9k 声望12k 粉丝

分享小厂可落地的前端工程与架构