乐趣区

关于json:现代配置指南YAML-比-JSON-高级在哪

始终以来,前端工程中的配置大多都是 .js 文件或者 .json 文件,最常见的比方:

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

这些配置对前端十分敌对,因为都是咱们相熟的 JS 对象构造。个别动态化的配置会抉择 json 文件,而动态化的配置,波及到引入其余模块,因而会抉择 js 文件。

还有当初许多新工具同时反对多种配置,比方 Eslint,两种格局的配置任你抉择:

  • .eslintrc.json
  • .eslintrc.js

起初不晓得什么时候,忽然呈现了一种以 .yaml.yml 为后缀的配置文件。一开始认为是某个程序的专有配置,起初发现这个后缀的文件呈现的频率越来越高,甚至 Eslint 也反对了第三种格局的配置 .eslintrc.yml

既然遇到了,那就摸索它!

上面咱们从 YAML 的 呈现背景 应用场景 具体用法 高级操作 四个方面,看一下这个风行的现代化配置的神秘之处。

呈现背景

一个新工具的呈现防止不了有两个起因:

  1. 旧工具在某些场景体现吃力,须要更优的代替计划
  2. 旧工具也没什么不好,只是新工具呈现,比较而言显得它不太好

YAML 这种新工具就属于后者。其实在 yaml 呈现之前 js+json 用的也不错,也没什么特地难以解决的问题;然而 yaml 呈现当前,开始感觉它好乱呀什么货色,起初理解它后,越用越喜爱,一个字就是优雅。

很多文章说抉择 yaml 是因为 json 的各种问题,json 不适宜做配置文件,这我感觉有些夸大其词了。我更违心将 yaml 看做是 json 的降级,因为 yaml 在格局简化和体验上体现的确不错,这个得抵赖。

上面咱们比照 YAML 和 JSON,从两方面剖析:

精简了什么?

JSON 比拟繁琐的中央是它严格的格局要求。比方这个对象:

{name: 'ruims'}

在 JSON 中以下写法统统都是错的:

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

字符串的值必须 k->v 都是 "" 才行:

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

尽管是对立格局,然而应用上的确有不便当的中央。比方我在浏览器上测出了接口谬误。而后把参数拷贝到 Postman 里调试,这时就我要手动给每个属性和值加 “” 号,十分繁琐。

YAML 则是另辟蹊径,间接把字符串符号干掉了。下面对象的等同 yaml 配置如下:

name: ruims

没错,就这么简略!

除了 "" 号,yaml 感觉 {}[] 这种符号也是多余的,不如一起干掉。

于是呢,以这个对象数组为例:

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

转换成 yaml 是这样的:

names:
  - name: ruims
  - name: ruidoc

比照一下这个精简水平,有什么理由不爱它?

减少了什么?

说起减少的局部,最值得一提的,是 YAML 反对了 正文

用 JSON 写配置是不能有正文的,这就意味着咱们的配置不会有备注,配置多了会十分凌乱,这是最不人性化的中央。

当初 yaml 反对了备注,当前配置能够是这样的:

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

把这种配置丢给新共事,还怕他看不懂配了啥吗?

除正文外,还反对配置复用的相干性能,这个前面说。

应用场景

我接触的第一个 yaml 配置是 Flutter 我的项目的包管理文件 pubspec.yaml,这个文件的作用和前端我的项目中的 package.json 一样,用于寄存一些全局配置和利用依赖的包和版本。

看一下它的根本构造:

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

你看这个构造和 package.json 是不是基本一致?dependencies 下列出利用依赖和版本,dev_dependencies 下的则是开发依赖。

起初在做 CI/CD 自动化部署的时候,咱们用到了 GitHub Action。它须要多个 yaml 文件来定义不同的工作流,这个配置可比 flutter 简单的多。

其实不光 GitHub Action,其余风行的相似的构建工具如 GitLab CI/CD,circleci,全部都是齐刷刷的 yaml 配置,因而如果你的我的项目要做 CI/CD 继续集成,不懂 yaml 语法必定是不行的。

还有,接触过 Docker 的同学必定晓得 Docker Compose,它是 Docker 官网的单机编排工具,其配置文件 docker-compose.yml 也是妥妥的 yaml 格局。当初 Docker 正是如日中天的时候,应用 Docker 必然免不了编排,因而 yaml 语法早晚也要攻克。

下面说的这 3 个案例,简直都是古代最新最风行的框架 / 工具。从它们身上能够看进去,yaml 必然是下一代配置文件的规范,并且是 前端 - 后端 - 运维 的通用规范。

说了这么多,你蠢蠢欲动了吗?上面咱们具体介绍 yaml 语法。

YAML 语法

介绍 yaml 语法会比照 json 解释,以便咱们疾速了解。

先看一下 yaml 的几个特点:

  • 大小写敏感
  • 应用缩进示意层级关系
  • 缩进空格数不强制,但雷同层级要对齐
  • # 示意正文

相比于 JSON 来说,最大的区别是用 缩进 来示意层级,这个和 Python 十分靠近。还有强化的一点是反对了正文,JSON 默认是不反对的(尽管 TS 反对),这也对配置文件十分重要。

YAML 反对以下几种数据结构:

  • 对象:json 中的对象
  • 数组:json 中的数组
  • 纯量:json 中的简略类型(字符串,数值,布尔等)

对象

先看对象,上一个 json 例子:

{
  "id": 1,
  "name": "杨胜利",
  "isman": true
}

转换成 yaml:

id: 1
name: 杨胜利
isman: true

对象是最外围的构造,key 值的示意办法是 [key]: ,留神这里 冒号前面有个空格,肯定不能少 。value 的值就是一个 纯量,且默认不须要引号。

数组

数组和对象的构造差不多,区别是在 key 前用一个 - 符号标识这个是数组项。留神这里 也有一个空格,同样也不能少。

- hello
- world

转换成 JSON 格局如下:

["hello", "world"]

理解了根本的对象和数组,咱们再来看一个简单的构造。

家喻户晓,在理论我的项目配置中很少有简略的对象或数组,大多都是对象和数组互相嵌套而成。在 js 中咱们称之为对象数组,而在 yaml 中咱们叫 复合构造

比方这样一个稍简单的 JSON:

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

转换成复合构造的 YAML:

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

若你想尝试更简单构造的转换,能够在 这个 网页中在线实际。

纯量

纯量比较简单,对应的就是 js 的根本数据类型,反对如下:

  • 字符串
  • 布尔
  • 数值
  • null
  • 工夫

比拟非凡的两个,null 用 ~ 符号示意,工夫大多用 2021-12-21 这种格局示意,如:

who: ~
date: 2019-09-10

转换成 JS 后:

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

高级操作

在 yaml 实战过程中,遇到过一些非凡场景,可能须要一些非凡的解决。

字符串过长

在 shell 中咱们常见到一些参数很多,而后特地长的命令,如果命令都写在一行的话可读性会十分差。

假如上面的是一条长命令:

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

在 linux 中能够这样解决:

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

就是在每行后加 \ 符号标识换行。然而在 YAML 中更简略,不须要加任何符号,间接换行即可:

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

YAML 默认会把换行符转换成 空格,因而转换后 JSON 如下,正是咱们须要的:

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

然而有时候,咱们的需要是 保留换行符,并不是把它转换成空格,又该怎么办呢?

这个也简略,只须要在首行加一个 | 符号:

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

转换成 JSON 变成了这样:

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

获取配置

获取配置是指,在 YAML 文件中定义的某个配置,如何在代码(JS)里获取?

比方前端在 package.json 里有一个 version 的配置项示意利用版本,咱们要在代码中获取版本,能够这么写:

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

JSON 是能够间接导入的,YAML 可就不行了,那怎么办呢?咱们分环境解析:

在浏览器中

浏览器中代码用 webapck 打包,因而加一个 loader 即可:

$ yarn add -D yaml-loader

而后配置 loader:

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

在组件中应用:

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

在 Node.js 中

Node.js 环境下没有 Webpack,因而读取 yaml 配置的办法也不一样。

首先装置一个 js-yaml 模块:

$ yarn add js-yaml

而后通过模块提供的办法获取:

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

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

配置项复用

配置项复用的意思是,对于定义过的配置,在前面的配置间接援用,而不是再写一遍,从而达到复用的目标。

YAML 中将定义的复用项称为锚点,用& 标识;援用锚点则用 * 标识。

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

compose:
  key1: *name
  key2: *env

对应的 JSON 如下:

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

然而锚点有个弊病,就是不能作为 变量 在字符串中应用。比方:

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

此时 key2 的值就是一般字符串 _my name is *name_,援用变得有效了。

其实在理论开发中,字符串中应用变量还是很常见的。比方在简单的命令中屡次应用某个门路,这个时候这个门路就应该是一个变量,在多个命令中复用。

GitHub Action 中有这样的反对,定义一个环境变量,而后在其余的中央复用:

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

这种实现形式与 webpack 中应用环境变量相似,在构建的时候将变量替换成对应的字符串。

如果本文对你有启发,请甩手一个赞 👍

如有疑难或转发,请加微信 ruidoc 分割~

退出移动版