什么是脚手架
从使用角度理解什么是脚手架
CLI,全称是
command-line interface,也就是命令行界面。
脚手架本质上就是一个操作系统的客户端,它通过命令行执行
其中大家最熟悉的就是 create-react-app 和 vue-cli,还有自研的tccli
比如 vue-cli
vue create vue-test
上面这条命令由 3 个部分组成:
- 主命令:
vue - command(子命令):
create - command 的 param:
vue-test
它表示创建一个 vue 项目,项目名称为 vue-test,以上是最简单的脚手架命令,但实际场景往往更加复杂,比如: 当前项目已经有文件,我们需要覆盖当前目录下的文件,强制进行安装vue项目,此时我们就可以输入
vue create vue-test --force
这里的--force 叫做 option,用来辅助脚手架确认在特定场景下用户的选择(可以理解为配置)。还有一种场景:通过vue create创建项目时,会自动执行npm install帮助用户安装依赖,如果我们希望使用淘宝源来安装,可以输入命令:
vue create vue-test --force -r [https://registry.npm.taobao.org](https://registry.npm.taobao.org)
这里的 -r 也叫做 option,它与--force不同的是它使用 -,并且使用简写,这里的-r也可以替换成-- registry,我们可以通过帮助命令看到vue create支持的所有 options:
vue create --help
开发脚手架的必要性
往常项目开发时,如果新启一个项目,你需要从头配置很多东西,api,路由,权限,基础UI库,埋点等等初始化操作,为了简化和提高效率,才有了脚手架存在的意义
开发脚手架的核心目标是:提升前端的研发效能
脚手架核心价值
整体来说就是将研发过程自动化,标准化
- 减少重复性工作
- 规范项目开发目录结构
- 统一团队统一开发风格,便于跨团队合作,以及后期维护,降低新人上手成本
- 提供一键前端项目的创建、配置、本地开发、插件扩展等功能,让开发者更多时间专注于业务
脚手架实现原理
首先抛出来三个问题
- 为什么全局安装
@vue/cli后为添加命令为vue? - 全局安装
@vue/cli时发生了什么 ? - 执行
vue命令的时候发生了什么?为什么vue指向一个js文件,我们却可以直接通过vue命令去执行它?
首先思考一下 当我们在终端输入vue create vue-test-app的时候,这个命令背后做了什么事情
简化版的思维导图
脚手架执行原理如下
-
在终端输入 指令
vue create vue-test-app -
终端解析出
vue命令- which 命令可以查看执行命令所在位置
-
在环境变量中找到vue命令
-
终端根据vue命令链接到实际vue.js文件
-
终端利用node执行vue.js
-
vue.js解析command/options
-
vue.js执行command
-
执行完毕,退出执行
第一个问题通过打开源码可以看到
配置了
bin字段
许多软件包都具有一个或多个要安装到 PATH 中的可执行文件。
bin 字段是命令名到本地文件名的映射。在安装时,npm 会将文件符号链接到 prefix/bin 以进行全局安装或./node_modules/.bin/本地安装。 当我们使用 npm 或者 yarn 命令安装包时,如果该包的 package.json 文件有 bin 字段,就会在 node_modules 文件夹下面的 .bin 目录中复制了 bin 字段链接的执行文件。我们在调用执行文件时,可以不带路径,直接使用命令名来执行相对应的执行文件。
第二个问题
答案是: 下载依赖,并配置 bin 命令
#!/usr/bin/env node
#!/usr/bin/node
// 第一种是环境变量中查找node
// 第二种直接执行/usr/bin/目录下的node
为什么这么说 脚手架本质是一个操作系统的客户端
是因为node 就是客户端,查看安装目录会发现 node是个.exe可执行文件, 执行vue命令 等价于 执行node vue , 可以看到vue是当作一个参数传入到node中的,然后执行预设程序. 这里脚手架可以理解为在客户端执行的可执行文件
实现一个自己的脚手架
脚手架的目的是为了在统一的标准下快速建设系统框架,把系统开发过程中需要的配置、组件、服务、测试,一并通过配置引入到系统开发中。
开发脚手架之前,我们要先自己理一下需求,要满足什么功能,有了方向和规划,才能更高效的去实现
在这里简单的理一下需求:
对用户而言(简化版):
对于CLI而言
开发流程
-
创建
npm项目 -
创建脚手架入口文件,最上方添加:
#!/usr/bin/env node -
配置
package.json,添加bin属性 -
编写脚手架代码
-
将脚手架发布到 npm
npm包本地调试的两个办法
- 在当前包的根目录下 npm install -g xxx 全局安装脚手架,系统会将命令软连接到当前文件
- 使用 npm link 命令,会根据package.json上的配置,被链接到全局
npm发布的时候注意点
-
name不能重复,可以通过
npm view 包名查看是否已经有了,没有的话该命令会返回404 -
解决重名烦恼也可以使用新建组织的方式, 但发布的时候需要
npm publish —access=publish当然 你是付费建立的那就不用了 常规的npm publish就可以- 或者在package.json中添加配置
"publishConfig": {"access": "publish"}
npm包本地调试的方法,链接本地库文件
// 进入你的本地库文件夹
cd your-lib-dir
//执行
npm link
// 到你使用这个库的项目内
cd your-cli-dir
// 执行
npm link you-lib-dir
取消链接本地库
// 进入你的本地库文件夹
cd your-lib-dir
//执行
npm unlink
// 到你使用这个库的项目内
cd your-cli-dir
// 执行
npm unlink you-lib-dir
原生脚手架开发痛点分析
-
重复操作
- 主要体现在多package方面,当一个脚手架包含多个package的时候, 多个包之间的本地link, 依赖安装,本地测试,代码提交与发布,都会产生大量的重复性操作.
-
版本一致性问题
- 发布的时候版本一致性
- 发布的时候互相依赖包的版本升级,比如说a是公共工具包,它被b,c,d所使用,当a生版本后, bcd都需要更新版本时
开发中常用的依赖
- babel-cli/babel-env:语法转换工具,有了它我们在开发脚手架的时候就可以使用 ES6 语法了
- commander:命令行工具,有了它我们就可以读取命令行命令,知道用户想要做什么了
- inquirer: 交互式命令行工具,给用户提供一个漂亮的界面和提出问题流的方式
- download-git-repo:下载远程模板工具,负责下载远程仓库的模板项目
- chalk:颜色插件,用来修改命令行输出样式,通过颜色区分 info、error 日志,清晰直观
- ora:用于显示加载中的效果,类似于前端页面的 loading 效果,像下载模板这种耗时的操作,有了 loading 效果可以提示用户正在进行中,请耐心等待
- log-symbols:日志彩色符号,用来显示√ 或 × 等的图标
此文章只是先讲了一下脚手架的概念,让大家对脚手架有个基本认知, 下一篇中,开始代码编写