likes
comments
collection
share

NutUI-React 底层架构工具升级之巧用 Shell 脚本

作者站长头像
站长
· 阅读数 6

NutUI 是一款京东风格的移动端组件库。NutUI 目前支持 Vue 和 React 技术栈,支持 Taro 多端适配。本次架构升级主要介绍 NutUI-React 在 npm 到 pnpm 的升级迁移、巧用 Shell 脚本和构建工具 Vite2 升级到 Vite4 的过程中所经历的踩坑之旅。作为此系列的第二篇文章,希望大家可以学会并熟练使用 Shell 脚本。

GitHub:NutUI-VueNutUI-React

欢迎使用、共建!

一、前言

首先在介绍 Shell 脚本之前,我们一定要先了解清楚 Shell 是什么,在开发平时的项目中引用 Shell 可以帮助我们解决什么问题,是否可以给我们带来开发效率的提升,以及作为前端工程师要学习并学会使用 Shell 是否具有价值?

好,带着这些疑问,我会在后面的文章内容中逐一给大家解惑。废话不多说,发车啦~

二、Shell 基本概念

1. Shell 是什么?

我们先看一个比较官方的介绍:

  • Shell 可以是一个程序,提供一个与用户对话的环境。是计算机提供给用户与其他程序进行交互的接口

  • Shell 是一个命令解释器,当你输入命令后,由 Shell 进行解释后交给操作系统内核(OS Kernel)进行处理

刚接触 Shell 的家人们估计看完后虎躯一震,这是啥意思啊?没关系,我来把它说的通俗一点:大家就可以把 Shell 当做是一个壳,或者可以理解成一个”核桃壳“,里面包裹的“核桃仁”就是操作系统内核

NutUI-React 底层架构工具升级之巧用 Shell 脚本

Shell 本质上就可以理解为是操作系统内核提供的一个接口,比如咱平时用的控制台就是一个命令行的 Shell。说白了,Shell 就是人机互动的一种方式,使用操作系统的用户和计算机硬件交互的一种方式。

我们再来看一张图,很清晰的表示了Shell与内核、操作系统之间的关系:

NutUI-React 底层架构工具升级之巧用 Shell 脚本

怎么样,有没有一种很通透的感觉~

2. Shell 的种类

下面是一些历史上比较流行的 Shell 种类,大家简单看一下了解即可:

  • Bourne Shell (sh):由 Stephen Bourne 在 1977 年开发,是 Unix 的默认 Shell,也是很多其他 Shell 的基础。它是一种较为基础的 Shell,不支持交互式界面、命令行编辑等高级功能。
  • C Shell (csh):由 Bill Joy 开发,类似于 C 语言的语法,支持命令行编辑、命令别名等高级功能。
  • Korn Shell (ksh):由 David Korn 开发,是 Bourne Shell 的扩展,同时继承了 C Shell 的一些优秀特性,支持命令行编辑、命令别名、作业控制等功能。
  • Bourne-Again Shell (bash):由 Brian Fox 和 Chet Ramey 开发,是 Bourne Shell 的升级版,兼容 Bourne Shell,并添加了许多新功能,如命令补全、命令历史、自动提示等。
  • Z Shell (zsh):由 Paul Falstad 开发,是 Bourne Shell 的扩展版本,支持命令补全、模式匹配、参数替换等高级功能,同时也可以兼容 Bourne Shell 和 Bash。
  • Fish Shell (fish):由 Gustav “Goose” Norstrom 开发,它的设计目标是简单易用,具有友好的交互式界面和自动提示功能,支持命令补全、模式匹配、命令历史等高级功能。

除了上述几种 Shell 外,还有许多其他的 Shell,如 tcsh、ash、dash等。每种 Shell 都有其独特的特点和用途,在不同的环境下选用合适的 Shell 可以提高工作效率和命令行使用体验。

这里我们用到的Shell 种类大多数都是 bash,也是目前大多数 Linux 发行版以及 MacOS 操作系统的默认 Shell。

Bash 使用了一种与图形界面(GUI)完全相反的方案:通过纯文本的控制台进行控制,它的主要交互方式通过键盘输入文本,文字反馈来实现人机交互。

NutUI-React 底层架构工具升级之巧用 Shell 脚本

很多人估计会说了,界面这么丑,是不是 Bash 马上就要过时了呀!No,no,no...恰恰相反 Bash 在开发领域应用反倒越来越广泛。正因为其最大的优势就是简单易用,虽然它的显示效果不如 GUI,但一旦熟练后其操作效率远远大于 GUI!

3. Shell 的优势

这里我也是总结了几条使用 Shell 脚本编写代码的优势:

  • 自动化:使用 Shell 脚本可以自动化执行一系列命令,自动完成一些繁琐的工作,比如打包、压缩、部署等。
  • 快速:使用 Shell 脚本可以快速地执行一些操作,避免了手动输入命令的繁琐过程。
  • 可扩展:使用 Shell 脚本可以根据实际需求编写不同的脚本,从而扩展功能和应用场景。
  • 可重复性:使用 Shell 脚本可以确保执行过程中不会出现失误,从而保证执行结果的一致性和可重复性。
  • 跨平台:Shell 脚本可以在各种操作系统中运行,比如 Linux、Unix、MacOS 等,从而提高了代码的可移植性和兼容性。

综上所述,使用 Shell 脚本可以帮助我们提高工作效率、降低出错率、扩展功能和应用场景,从而提升代码的质量和可维护性。

4. Shell 的例子

为了让家人们对后文项目中稍复杂的 Shell 脚本可以有一个更好的理解,这里我先给大家举一个简单的小例子,先练练手~

编写一个 Shell 脚本名字为 hello.sh,脚本输出内容为 hello world :

#!/bin/bash

# 执行的命令主体
echo "hello world"

#!/bin/bash 就是指定脚本要使用的 Shell 类型为 Bash ,echo 就可以理解为前端控制台中的 console.log。

怎么样,easy 不,我们也可以定义一个变量再输出,像下面这样:

#!/bin/bash

# 执行的命令主体
message="Hello World" # message 为变量名
echo $message  # 打印message变量

好滴,Shell 的一些基础语法,我就不在这一一介绍了,推荐大家先进入这个网站 shellscript.readthedocs.io/zh_CN/lates… 简单扫一眼,了解下 Shell 的基本使用。

后面实战开发就要正式开始啦~

三、前端工程 NutUI-React 巧用 Shell 脚本实践

1. 要解决什么问题?

平时我们在发布 NutUI-React 组件库版本的时候,都需要发布一个 CHANGELOG.md,为了让开发者和用户可以了解项目的演化历史,并知道每个版本都带来了哪些变化。

同时,用户也可以通过查看 CHANGELOG.md 来了解项目的新特性和功能,以及已知的问题和待解决的问题。

NutUI-React 底层架构工具升级之巧用 Shell 脚本

这些迭代的新特性和功能的文案,难道需要我们根据提交pr的记录自己一条条的手敲么?或者一个个手动 ctrl c + ctrl v 么?那就真的妥妥的 ctrl c/ctrl v 高级开发工程师了。

那有没有什么比较智能化的脚本,可以自动抓取开发者提交 pr 的记录,并将记录自动生成如上图格式的文案呢?

2. CHANGELOG 自动化 shell 脚本

当然有咯~,下面就是一段用 Shell 编写的一段自动化的脚本。

这里我们以 NutUI-React 最新发布的 v1.5.1 版本为例,执行方法:./gitlog.sh 2023/4/13 1.5.1

这是一个gitlog.sh的bash脚本文件

#!/bin/bash

# 提取 某个时间之后的提交信息
latestPublishedDate="$1"
log=$(git log --since="$latestPublishedDate" --pretty=format:%s\ @%an)

## Feat 和 Fix 转小写,句号转空
log=$(echo "$log" | sed 's/feat/feat/i;s/fix/fix/i;s/。//')

# 提交信息进行不区分大小写的排序
log=$(echo "$log" | sort -f)

# 增加 emoji
log=$(echo "$log" | sed 's/^feat/* :sparkles: feat/i;s/^fix/* :bug: fix/i;s/^chore/* 🔨 chore/i;s/^docs/* 📖 docs/i')

# 获取当前日期和迭代版本
version="$2"
today=$(date "+%Y-%m-%d")
todayChangeLog=$(echo -e "# v$version\n\`$today\`\n\n$log")

# 输出结果追加到CHANGELOG.md文件顶部
oldChangeLog=$(cat ./CHANGELOG.md)
echo -e "$todayChangeLog\n\n\n$oldChangeLog" > ./CHANGELOG.md

输出的结果在./CHANGELOG.md文件中:

# v1.5.1
`2023-04-19`


* :bug: fix: 修改 inputnumber 微信小程序的带小数点的键盘 (#907) @junjun666
* :bug: fix: 修复 uploader 组件编译xhr报错的问题 (#916) @junjun666
* 🔨 chore: 开发编译兼容 taro 3.6.5版本 (#911) @junjun666

估计很多人看到这就滑走了,这么一大串代码是啥子,表示看不懂......别急家人们哈,咱逐行一步步分析,保证大家完全 get 到~

四、自动化 Shell 脚本逐行分析

1. 提取某个时间之后的提交信息

# 提取某个时间之后的提交信息
latestPublishedDate="$1"
log=$(git log --since="$latestPublishedDate" --pretty=format:%s\ @%an)

当我们调用脚本文件时,比如上面的 ./gitlog.sh 2023/4/13 1.5.1,2023/4/13 就是参数 1,1.5.1 就是参数 2。

那么对应的在 Shell 脚本中就可以通过以下变量获取参数:

  • $1 第一个参数
  • $2 第二个参数
  • $N 第N个参数

所以 latestPublishedDate="$1" 就代表把 2023/4/13 这个参数赋值给 latestPublishedDate 这个变量

好滴,我们来看第二行,就可以理解成如下的输出方式:

git log --since=2023/4/13 --pretty=format:%s\ @%an

我们把这句命令来拆解一下:

  • git log:这是 Git 命令的基本部分,用于查看提交历史。log 子命令会显示提交的详细信息,例如作者、日期、提交消息等。

  • --since="2023/4/13":此选项用于过滤提交历史,只显示指定日期之后的提交。在这里,它将只显示 2023年4月13日 之后的提交。

  • --pretty=format:%s\ @%an:这部分是一个高级选项,用于自定义日志输出的格式。--pretty=format: 之后的内容用于定义格式字符串。

    • %s:这是一个占位符,表示提交消息的简短描述(通常是一行)。
    • \ :这是一个空格,用于在提交消息和作者名之间插入空格。
    • @:这是一个普通字符,它将在输出中显示为“@”。
    • %an:这是一个占位符,表示提交作者的名字。

最后我们把 log 这个变量输出一下,看看输出的结果是什么。

echo "$log"

NutUI-React 底层架构工具升级之巧用 Shell 脚本

2. Feat 和 Fix 转小写,句号转空

## Feat 和 Fix 转小写,句号转空
log=$(echo "$log" | sed 's/feat/feat/i;s/fix/fix/i;s/。//')

这一句怎么理解呢?有些用户在提交信息时肯定有不规范的地方,比如 Feat 大写啦,Fix 大写啦,或者带句号啊等等

首先 sed 是什么呢?就是类似流编辑器,对标准输出或文件逐行进行处理。

我们可以先看一个比较基础的例子:

  • s/parent/child -- 将行内第一个 parent 替换为 child
  • s/parent/child/g -- 将行内全部的 parent 替换为 child
  • s/parent/child/2g --同一行,只替换从第二个开始到剩下所有的
  • s/parent/child/ig -- 将行内 parent 全部替换为 child ,忽略大小写

这个时候再回头看我们的语句:

sed 's/feat/feat/i;s/fix/fix/i;s/。//'
  • s/feat/feat/i:将输入文本中的"feat"(大小写不敏感,因为使用了i标记)替换为"feat"。这个表达式实际上没有改变文本内容,只是确保了"feat"的大小写一致。
  • s/fix/fix/i:将输入文本中的"fix"(大小写不敏感,因为使用了i标记)替换为"fix"。这个表达式同样没有改变文本内容,只是确保了"fix"的大小写一致。
  • s/。//:从输入文本中删除所有的"。"字符。这个表达式用于去除全角句号。

总结一下就是:这条命令的作用是将$log变量中的文本进行处理,将"feat"和"fix"统一为小写,并删除所有的全角句号"。",然后将处理后的文本重新赋值给$log变量。

3. 提交信息进行不区分大小写的排序

# 提交信息进行不区分大小写的排序
log=$(echo "$log" | sort -f)

sort 就很好理解啦,就是排序嘛,-f选项表示“忽略大小写”。

这里再补充一个知识点:|: 管道符号,它表示将前一个命令的输出作为下一个命令的输入。在这个例子中,我们将echo "$log"的输出传递给sort -f命令。

我们再把log这个变量输出一下,会发现此时已经把之前的输出结果进行了一个排序。

NutUI-React 底层架构工具升级之巧用 Shell 脚本

4. 增加emoji

log=$(echo "$log" | sed 's/^feat/* :sparkles: feat/i;s/^fix/* :bug: fix/i;s/^chore/* 🔨 chore/i;s/^docs/* 📖 docs/i')

大家现在再来看这句命令,是不是一下就清晰多咯~简单理解就是通过 sed 流将输出文本进行一个文案 emoji 替换

替换结果详见下图:

NutUI-React 底层架构工具升级之巧用 Shell 脚本

5. 获取当前日期和迭代版本

version="$2"
today=$(date "+%Y-%m-%d")
todayChangeLog=$(echo -e "# v$version\n\`$today\`\n\n$log")

上文我们讲过,$2 就代表执行命令的第二个参数,因为我们执行的命令是 ./gitlog.sh 2023/4/13 1.5.1,所以这里的 version 变量就是 1.5.1

再看第二行,作用是为了获取当前日期。date 命令是 Unix/Linux 系统中的命令,用于显示或设置系统的日期和时间。后面的"+%Y-%m-%d"是 date 命令的一个参数,用于指定输出格式。其中,%Y 表示四位数的年份,%m 表示两位数的月份,%d 表示两位数的日期。因此,该格式表示输出的日期将以 "年-月-日" 的形式展示,例如 "2023-04-21"。所以这里的 today 变量是"2023-04-21"。

于是第三行的命令就可以进行一个变量名的替换:

-e 参数使得 echo 可以解析转义字符。如果不添加 -e 则会原样输出,添加了 -e 输出则会换行

todayChangeLog=$(echo -e "# v1.5.1\n\`2023-04-21\`\n\n$log")

这个时候我们再来看一下 todayChangeLog 变量输出的结果:

NutUI-React 底层架构工具升级之巧用 Shell 脚本

6. 输出结果追加到 CHANGELOG.md 文件顶部

oldChangeLog=$(cat ./CHANGELOG.md)
echo -e "$todayChangeLog\n\n\n$oldChangeLog" > ./CHANGELOG.md

cat 很好理解就是读取 ./CHANGELOG.md 文件内容赋值给 oldChangeLog 变量嘛,然后 todayChangeLog 变量和 oldChangeLog 变量进行拼接整合,最后一起追加到 ./CHANGELOG.md 文件中,最后我们在 ./CHANGELOG.md 就可以看到我们的输出结果。

NutUI-React 底层架构工具升级之巧用 Shell 脚本

最后我们就可以将本地 CHANGELOG.md 文件的输出结果,直接整体粘贴到我们的 GitHub 的 releases 中发布就好啦~方便又高效

NutUI-React 底层架构工具升级之巧用 Shell 脚本

五、小结

通过本文,我们了解了 Shell 脚本如何在前端工程组件库中的应用,并且通过 Shell 脚本提高了我们的开发效率。

这个时候再回到文章一开始提出的疑问,作为前端工程师需要学习 Shell么,学习 Shell 的意义与价值又在哪里呢?

👉想象一下,你在开发一个网页项目,突然遇到了一个棘手的问题。你如鱼得水地使用各种前端技术,但却被一些重复性和繁琐的任务拖延。这时候,掌握 Shell 脚本编写技能,就能轻松帮你解决问题!

🌟那前端工程师学习 Shell 脚本的意义与价值又在哪里呢?

  1. 自动化神器:Shell 脚本能让你实现自动化的奇迹。一行命令,搞定繁琐的重复任务,节省你宝贵的时间,让你更专注于前端代码的优化!
  2. 跨平台大师:无论是 Linux、MacOS 还是 Windows,Shell 脚本都能为你所用。只要你掌握了这门技能,随时随地解决问题不再是梦想。
  3. 与后端无缝衔接:与后端同学进行项目合作时,Shell 脚本能让你更加自信。一起交流技术,一起成长,轻松搞定团队协作!
  4. 强化简历:在招聘市场竞争激烈的今天,多一项技能,就多一份竞争优势。学会 Shell 脚本,让你的简历更加出彩!