NutUI 是一款京东风格的移动端组件库。NutUI 目前支持 Vue 和 React技术栈,支持Taro多端适配。本次架构升级主要介绍NutUI-React在npm到pnpm的升级迁移、巧用Shell脚本和构建工具Vite2升级到Vite4的过程中所经历的踩坑之旅。作为此系列的第二篇文章,希望大家可以学会并熟练使用Shell脚本。
一、前言
首先在介绍Shell脚本之前,我们一定要先了解清楚Shell是什么,在开发平时的项目中引用Shell可以帮助我们解决什么问题,是否可以给我们带来开发效率的提升,以及作为前端工程师要学习并学会使用Shell是否具有价值?
好,带着这些疑问,我会在后面的文章内容中逐一给大家解惑。废话不多说,发车啦~
二、Shell基本概念
1.Shell是什么?
我们先看一个比较官方的介绍:
-
Shell 可以是一个程序,提供一个与用户对话的环境。是计算机提供给用户与其他程序 进行交互的接口
-
Shell 是一个命令解释器,当你输入命令后,由 Shell 进行解释后交给操作系统内核(OS Kernel)进行处理
刚接触shell的家人们估计看完后虎躯一震,这是啥意思啊?没关系,我来把它说的通俗一点:大家就可以把Shell 当做是一个壳,或者可以理解成一个"核桃壳 ",里面包裹的"核桃仁 "就是操作系统内核。
Shell本质上就可以理解为是操作系统内核提供的一个接口,比如咱平时用的控制台就是一个命令行的Shell。说白了,Shell就是人机互动的一种方式,使用操作系统的用户和计算机硬件交互的一种方式。
我们再来看一张图,很清晰的表示了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)完全相反的方案:通过纯文本的控制台进行控制,它的主要交互方式通过键盘输入文本,文字反馈来实现人机交互。
很多人估计会说了,界面这么丑,是不是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 :
bash
#!/bin/bash
# 执行的命令主体
echo "hello world"
#!/bin/bash 就是指定脚本要使用的 Shell 类型为 Bash ,echo就可以理解为前端控制台中的console.log。
怎么样,easy不,我们也可以定义一个变量再输出,像下面这样:
bash
#!/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 来了解项目的新特性和功能,以及已知的问题和待解决的问题。
这些迭代的新特性和功能的文案,难道需要我们根据提交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脚本文件
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文件中:
markdown
# 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.提取某个时间之后的提交信息
代码如下:
bash
# 提取某个时间之后的提交信息
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这个变量
好滴,我们来看第二行,就可以理解成如下的输出方式:
bash
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"
2.Feat 和 Fix 转小写,句号转空
代码如下:
bash
## 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 ,忽略大小写
这个时候再回头看我们的语句:
bash
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/。//:从输入文本中删除所有的"。"字符。这个表达式用于去除全角句号。
总结一下就是:这条命令的作用是将 <math xmlns="http://www.w3.org/1998/Math/MathML"> l o g 变量中的文本进行处理,将 " f e a t " 和 " f i x " 统一为小写,并删除所有的全角句号 " 。 " ,然后将处理后的文本重新赋值给 log变量中的文本进行处理,将"feat"和"fix"统一为小写,并删除所有的全角句号"。",然后将处理后的文本重新赋值给 </math>log变量中的文本进行处理,将"feat"和"fix"统一为小写,并删除所有的全角句号"。",然后将处理后的文本重新赋值给log变量。
3.提交信息进行不区分大小写的排序
代码如下:
bash
# 提交信息进行不区分大小写的排序
log=$(echo "$log" | sort -f)
sort就很好理解啦,就是排序嘛,-f
选项表示"忽略大小写"。
这里再补充一个知识点:
|
: 管道符号,它表示将前一个命令的输出作为下一个命令的输入。在这个例子中,我们将echo "$log"
的输出传递给sort -f
命令。
我们再把log这个变量输出一下,会发现此时已经把之前的输出结果进行了一个排序。
4.增加emoji
代码如下:
bash
log=$(echo "$log" | sed 's/^feat/* :sparkles: feat/i;s/^fix/* :bug: fix/i;s/^chore/* 🔨 chore/i;s/^docs/* 📖 docs/i')
大家现在再来看这句命令,是不是一下就清晰多咯~简单理解就是通过sed流将输出文本进行一个文案emoji替换
替换结果详见下图:
5.获取当前日期和迭代版本
代码如下:
bash
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 输出则会换行
bash
todayChangeLog=$(echo -e "# v1.5.1\n\`2023-04-21\`\n\n$log")
这个时候我们再来看一下todayChangeLog变量输出的结果:
6.输出结果追加到CHANGELOG.md文件顶部
代码如下:
bash
oldChangeLog=$(cat ./CHANGELOG.md)
echo -e "$todayChangeLog\n\n\n$oldChangeLog" > ./CHANGELOG.md
cat很好理解就是读取./CHANGELOG.md文件内容赋值给oldChangeLog变量嘛,然后todayChangeLog变量和oldChangeLog变量进行拼接整合,最后一起追加到./CHANGELOG.md文件中,最后我们在./CHANGELOG.md就可以看到我们的输出结果。
最后我们就可以将本地CHANGELOG.md文件的输出结果,直接整体粘贴到我们的github的releases中发布就好啦~方便又高效
五、小结
通过本文,我们了解了Shell脚本如何在前端工程组件库中的应用,并且通过Shell脚本提高了我们的开发效率。
这个时候再回到文章一开始提出的疑问,作为前端工程师需要学习Shell么,学习Shell的意义与价值又在哪里呢?
👉想象一下,你在开发一个网页项目,突然遇到了一个棘手的问题。你如鱼得水地使用各种前端技术,但却被一些重复性和繁琐的任务拖延。这时候,掌握Shell脚本编写技能,就能轻松帮你解决问题!
🌟那前端工程师学习Shell脚本的意义与价值又在哪里呢?
- 自动化神器:Shell脚本能让你实现自动化的奇迹。一行命令,搞定繁琐的重复任务,节省你宝贵的时间,让你更专注于前端代码的优化!
- 跨平台大师:无论是Linux、macOS还是Windows,Shell脚本都能为你所用。只要你掌握了这门技能,随时随地解决问题不再是梦想。
- 与后端无缝衔接:与后端同学进行项目合作时,Shell脚本能让你更加自信。一起交流技术,一起成长,轻松搞定团队协作!
- 强化简历:在招聘市场竞争激烈的今天,多一项技能,就多一份竞争优势。学会Shell脚本,让你的简历更加出彩!
六、加入我们
再次期待您早日成为我们共建大军中的一员!一起共建,一起使用!做站内最优秀的开源组件库!
期待您早日成为我们共建大军中的一员!
GitHub:NutUI-Vue、NutUI-React
欢迎共建、使用!