首页 > 其他分享 >【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!

时间:2022-10-19 14:03:52浏览次数:49  
标签:Vue 06 cli -- 命令 开源 组件 脚手架 type

脚手架是为了保证各施工过程顺利进行而搭设的工作平台。按搭设的位置分为外脚手架、里脚手架;按材料不同可分为木脚手架、竹脚手架、钢管脚手架;按构造形式分为立杆式脚手架、桥式脚手架、门式脚手架、悬吊式脚手架、挂式脚手架、挑式脚手架、爬式脚手架。 ——百度百科

本质上就是一个便利工具,为一些比较特殊或繁琐的工作提供辅助,我们这里需要开发的是一个基于命令行的工具,后文以 ​​cli​​ 代替。

前言

本文作者是vue devui核心代码贡献者之一的小雷同学,感谢他的无私分享!

视频教程

本期配套视频,欢迎观看+三连+分享!




【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行



为什么需要开发一个脚手架?

以下为初期组件库协同开发时遇到的问题:

  • 组件目录结构不一致
  • 扁平化目录
  • ​src​​ 类型目录
  • 组件产出命名不一致
  • 前缀 ​​D​​ 命名

  • 无前缀 ​​D​​ 命名

  • 小写驼峰命名

  • 大写驼峰命名

  • ​xxxService​​ 命名

  • ​useXxxService​​ 命名

  • 组件入口文件经常冲突

为了解决上述问题,本着为开源社区做贡献,发光发热的时候到了,和项目组织人 ​​kagol​​​ 沟通了脚手架方案顺利通过,​​Prefect​​ !

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_02

TODO

  • [x] 创建统一组件结构
  • [x] 创建组件库入口文件

技术选型

脚手架 = 命令 + 交互 + 逻辑处理

  • 命令
  • ​commander​​ 插件提供命令注册、参数解析、执行回调
  • 交互
  • ​inquirer​​ 插件用于命令行的交互(问答)

  • 逻辑处理

  • ​fs-extra​​ 插件是对 ​​nodejs​​ 文件 ​​Api​​ 的进一步封装,便于使用

  • ​kolorist​​ 插件用于输出颜色信息进行友好提示

初始化 cli

step1 创建 cli 目录

mkdir devui-cli // 创建脚手架目录
cd devui-cli // 进入脚手架目录
// 初始化一个 node 项目
npm init
// or
yarn init

第一步先创建一个目录来存放我们即将开发的脚手架,作为一个 ​​nodejs​​​ 包,需要我们通过 ​​npm​​​ 或者 ​​yarn​​ 初始化包的信息,一律回车即可通过,生成后的目录结构如下图。

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_03image.png

step2 创建入口文件

mkdir src
echo 'console.log("hello devui-cli")' > src/index.js

step3 安装所需依赖

npm i -D commander inquirer fs-extra kolorist
// or
yarn add -D commander inquirer fs-extra kolorist

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_加载_04image.png

开发命令脚本

这里先给大家梳理下 ​​cli​​​ 的执行流程:命令行输入 ​​devui-cli​​ --> 命令行交互 --> 根据不同参数进行不同操作。

这里大家可能要问了,命令行如何识别 ​​devui-cli​​ 的?又是如何执行交互操作的?

这里简单给大家解答一下,命令行里面输入 ​​devui-cli​​​ 本质上是执行某一个可执行脚本,那么对应我们 ​​node​​​ 包来说就是入口文件 ​​src/index.js​​​ 了,所以可以看成是 ​​node src/index.js​​​ ,效果是一样的,只不过第一种更为方便与友好一点。那么我们直接执行是否就可以了呢?答案肯定不是的,需要在 ​​package.json​​​ 里面配置 ​​bin​​ 属性来标明脚本的一个入口。

准备工作结束,接下来开始正式的 ​​cli​​ 脚本编写。

配置环境解释器

#!/usr/bin/env node

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_05image.png

部分看官可能会疑惑这句话有什么用呢?

答案在这里,若是有使用过 ​​Linux​​​ 或者 ​​Unix​​​ 的小伙伴们,对于 ​​Shebang​​​ 应该不陌生,它是一个符号的名称 ​​#!​​​ 。这个符号通常在 ​​Unix​​​ 系统的基本中第一行开头中出现,用于指明这个脚本文件的解释程序, ​​#!/usr/bin/env node​​​ 目的就是告诉操作系统执行这个脚本的时候,在 ​​/usr/bin​​​ 的环配置里找到 ​​node​​ 解释器并执行。

注册命令

配置好环境解释器之后就可以编写我们的命令逻辑了。

首先,先注册下我们需要执行的一些命令以及一些命令参数。

#!/usr/bin/env node
import { Command } from 'commander'
import { onCreate } from './commands/create'

// 创建命令对象
const program = new Command()

// 注册命令、参数、回调
program
// 注册 create 命令
.command('create')
// 添加命令描述
.description('创建一个组件模板或配置文件')
// 添加命令参数 -t | --type <type> ,<type> 表示该参数必填,[type] 表示选填
.option('-t --type <type>', `创建类型,可选值:component, lib-entry`)
// 注册命令回调
.action(onCreate)

// 执行命令行参数解析
program.parse()

创建具体命令目录,方便统一管理。

mkdir src/commands // 命令存放目录
echo 'export function onCreate() { }' > src/commands/create.js // 创建 create 命令文件并导出回调函数

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_加载_06image.png【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_加载_07image.png

测试脚本命令

我们可以先在 ​​onCreate​​ 里面打印一下我们接受到的参数。

export function onCreate (cmd) {
console.log(cmd)
}

执行一下脚本。

node src/index.js

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_08image.png

报错了!!!我们才刚开始就报错了,是否已经开始崩溃?

稳住别慌,一切在我们的意料之中。这是因为我们编写的是 ​​node​​​ 程序,本应该使用 ​​commonjs​​​ 简称 ​​CJS​​​ 格式,也就是用 ​​require​​​ 和 ​​exports​​​ 等语法才能正常使用 ​​node xxx.js​​​ 进行启动,但是我们使用了新一代的 ​​esmodule​​​ 简称 ​​ESM​​​ 格式,所以 ​​node​​ 脸盲了!那么有什么办法呢?

解决办法一:将 ​​.js​​​ 改成 ​​.mjs​​​ 。why? 很明显因为 ​​ESM​​​ 和 CJS 的加载方式不同,为了更好区分这两种不同的加载方式,所以创建了 ​​.mjs​​​ 的文件类型,旨在 ​​Module javascript​​​。​​.mjs​​​ 就是表示当前文件用 ​​ESM​​​ 的方式进行加载,如果是普通的 ​​.js​​​ 文件,则采用 ​​CJS​​ 的方式加载。

解决办法二:通过一些模块打包器进行转换为 ​​node​​​ 熟悉的 ​​cjs​​ 格式,然后再进行开发。

这里选择第二种方式,原因是采用打包器我们可以对代码进行其他操作,例如:压缩、转换等。

模块打包器的话这里采用 ​​esbuild​​ ,理由就是:快捷、方便。

npm i -D esbuild
// or
yarn add -D esbuild

安装好后先看下命令行帮助文档。

npx esbuild -h
// or
yarn esbuild -h

执行完后会看到以下帮助信息。

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_09image.png

看过帮助信息后我们加入如下命令:

{
// --bundle 标识打包的入口文件
// --format 转换为目标格式代码
// --platform 目标平台,默认 browser
// --outdir 输出目录
// 开发时实时编译
"dev": "esbuild --bundle ./src/index.js --format=cjs --platform=node --outdir=./lib --watch",
// 打包命令
"build": "esbuild --bundle ./src/index.js --format=cjs --platform=node --outdir=./lib",
// 执行 create 命令,如果有多个命令,可以去掉 create ,使用时再传入
"cli": "node ./lib/index.js create"
}

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_10image.png

执行下 ​​dev​​​ 命令,然后重新开一个 ​​shell​​​ 再执行 ​​cli​​ 命令。

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_11image.png

yarn cli
// or
npm run cli

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_12image.png

输出了一个 ​​{}​​​ ,这是我们打印的 ​​cmd​​​ 入参,我们并没有填入任何参数,所以解析后是一个空对象,接下来传入 ​​type​​ 参数再看看。

yarn cli -t component // -t 是 --type 的别名
// or
npm run cli -- -t component // -- 是 npm run 脚本传参时需要加的,类似于参数透传给脚本

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_13image.png【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_命令行_14image.png

现在已经能够正常获取到命令参数了,证明命令注册成功,后面可以继续实现我们的交互逻辑。

完善 create 命令

接下来就是进一步完善我们的命令交互了,以 ​​component​​ 为例,代码如下:

import inquirer from 'inquirer'
import { red } from 'kolorist'

// create type 支持项
const CREATE_TYPES = ['component', 'lib-entry']
// 文档分类
const DOCS_CATEGORIES = ['通用', '导航', '反馈', '数据录入', '数据展示', '布局']

export async function onCreate(cmd = {}) {
let { type } = cmd

// 如果没有在命令参数里带入 type 那么就询问一次
if (!type) {
const result = await inquirer.prompt([
{
// 用于获取后的属性名
name: 'type',
// 交互方式为列表单选
type: 'list',
// 提示信息
message: '(必填)请选择创建类型:',
// 选项列表
choices: CREATE_TYPES,
// 默认值,这里是索引下标
default: 0
}
])
// 赋值 type
type = result.type
}

// 如果获取的类型不在我们支持范围内,那么输出错误提示并重新选择
if (CREATE_TYPES.every((t) => type !== t)) {
console.log(
red(`当前类型仅支持:${CREATE_TYPES.join(', ')},收到不在支持范围内的 "${type}",请重新选择!`)
)
return onCreate()
}

try {
switch (type) {
case 'component':
// 如果是组件,我们还需要收集一些信息
const info = await inquirer.prompt([
{
name: 'name',
type: 'input',
message: '(必填)请输入组件 name ,将用作目录及文件名:',
validate: (value) => {
if (value.trim() === '') {
return '组件 name 是必填项!'
}
return true
}
},
{
name: 'title',
type: 'input',
message: '(必填)请输入组件中文名称,将用作文档列表显示:',
validate: (value) => {
if (value.trim() === '') {
return '组件名称是必填项!'
}
return true
}
},
{
name: 'category',
type: 'list',
message: '(必填)请选择组件分类,将用作文档列表分类:',
choices: DOCS_CATEGORIES,
default: 0
}
])

createComponent(info)
break
case 'lib-entry':
createLibEntry()
break
default:
break
}
} catch (e) {
console.log(red('✖') + e.toString())
process.exit(1)
}
}

function createComponent(info) {
// 输出收集到的组件信息
console.log(info)
}

function createLibEntry() {
console.log('create lib-entry file.')
}

ok,接下来尝试运行一下我们的脚本。

先尝试错误的类型:

yarn cli -t error
// or
npm run cli -- -t error

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_15image.png

按照我们的预想提示了错误信息并让我们重新选择类型。

接下来尝试正确的类型:

yarn cli -t component
// or
npm run cli -- -t component

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_16image.png

因为指定了类型为组件,所以现在需要收集一下即将创建的组件信息。

【我要做开源】Vue DevUI开源指南06:开源组件库中的CLI脚手架建设,再也不用担心重复工作和代码风格混乱了!_初始化_17image.png

按照提示信息一步一步完成输入最终获取到了我们需要的数据,接下来就是模板的生成了。



标签:Vue,06,cli,--,命令,开源,组件,脚手架,type
From: https://blog.51cto.com/u_15680963/5769770

相关文章