脚手架架构设计和框架搭建
将收获什么
- 脚手架的实现原理
Lerna
的常用方法- 架构设计技巧和架构图绘制方法
主要内容
- 学习如何以架构师的角度思考基础架构问题
- 多
Package
项目管理痛点和解决方案,基于Lerna
脚手架框架搭建 - 脚手架需求分析和架构设计,架构设计图
- 脚手架调试技巧
Lerna
源码分析node
的module
模块分析yargs
使用方法- 剖析
Lerna
架构设计
开发脚手架的必要性
开发脚手架的核心目标是:提升前端研发效能
以下内容如果全靠脚手架进行自动化处理,可以提高相当大的研发效率了。
创建项目 通用代码
- 埋点
http
请求- 工具方法
- 组件库
git 操作
- 创建仓库
- 代码冲突
- 远程代码同步
- 创建版本
- 发布打
tag
构建 发布上线
- 依赖安装和构建
- 资源上传
cdn
- 域名绑定
- 测试/正式服务器
脚手架核心价值
将研发过程
- 自动化:项目重复代码拷贝、
git
操作、发布上线操作 - 标准化:项目创建、git flow、发布流程、回滚流程
- 数据化:研发过程系统化、数据化、使得研发过程可量化
和自动化构建工具的区别
问题:jenkins
,travis
等自动化构建工具已经很成熟了,为什么还要自研脚手架?
- 不满足需求:
jenkins
,travis
通常在git hooks
中触发,需要在服务端执行,无法覆盖研发人员本地的功能,如:创建项目自动化,本地git
操作自动化等。 - 定制复杂:
jenkins
,travis
定制过程需要开发插件,其过程较为复杂,需要使用java
语言,对前端同学不太友好。
什么是脚手架
脚手架本质是一个操作系统的客户端,他通过命令行执行,比如
代码语言:javascript复制vue create vue-test-app
上面这条命令由 3 个部分组成:
- 主命令:
vue
- command:
create
- command 的 param:
vue-test-app
他表示创建一个 vue
项目,项目的名称为 vue-test-app
,这是一个比较简单的脚手架命令,但实际场景往往更加复杂,比如:
当前目录已经有文件了,我们需要覆盖当前目录的文件,强制进行安装 vue
项目,此时我们就可以输入
vue create vue-test-app --force
这里的 --force
叫做 option
,用来辅助脚手架确认在特定场景下用户的选择(可以理解为配置)。还有一种场景:
通过 vue create
创建项目时,会自动执行 npm install
帮助用户安装依赖,如果我们希望使用淘宝源来安装,可以输入命令
vue create vue-test-app --force -r https://registry.npm.taobao.org
这里的 -r
也叫做 option
,它与 --force
不同的是它使用 -
,并且使用简写,这里的 -r
也可以替换成 --registry
,输入下面的命令就可以看到 vue create
支持的所有 options
。
vue create --helps
-r
后面的 https://registry.npm.taobao.org
成为 option
的 param
,其实 --force
可以理解为:--force true
,简写为 --force
或 -f
。
脚手架的执行原理
脚手架执行原理如下
- 在终端输入
vue create project
- 终端解析出
vue
- 在环境变量中通过
which vue
找到vue
命令, 目录所在/node/bin/vue
,所以我们执行的vue
,实际上运行的是/node/bin/vue
的这个vue
- 这个
vue
只是一个链接,终端根据vue
命令链接到实际文件/node/lib/node_modules/@vue/cli/bin/vue.js
- 终端利用
node
执行vue.js
vue.js
解析command
以及param
vue.js
执行command
- 执行完毕,退出执行
如何开发一个脚手架
以 vue-cli 为例
- 开发一个
npm
项目,该项目中应包含一个bin/vue.js
文件,并将这个项目发布到npm
; - 将这个项目发布到
npm
- 将
npm
项目上的项目全局安装到node
的lib/node_modules
- 在
node
的bin
目录下配置vue
软链接指向lib/node_modules/@vue/cli/bin/vue.js
这样我们在执行 vue
命令的时候就可以找到 vue.js
进行相关操作。
脚手架实现原理问题
为什么全局安装 @vue/cli 后会添加一个 vue 的命令呢?
代码语言:javascript复制npm i -g @vue/cli
运行 vue
命令时,实际走的是 node/bin/vue
,而这个文件只是一个软连接,指向lib/node_modules/@vue/cli/bin/vue.js
。
回到上级目录 lib/node_modules/@vue/cli
,打开 package.json
文件,里面的 bin
字段定义了这样的绑定关系。
// lib/node_modules/@vue/cli/package.json
{
"bin": {
"vue": "bin/vue.js"
},
}
总结:执行 vue
命令的时候,启动的是 bin/vue
这个文件,而这个文件指向lib/node_modules/@vue/cli/bin/vue.js
,所以最终启动的是 lib/node_modules/@vue/cli/bin/vue.js
全局安装 @vue/cli 的时候发生了什么?
- 把
@vue/cli
的包通过npm
安装到node/lib/node_modules
这个目录下。 - 解析
package.json
文件 ,根据文件中的bin
字段,在/node/bin
目录下创建软连接,软连接指向bin
字段中规定的文件,也就是lib/node_modules/@vue/cli/bin/vue.js
。
执行 vue
命令时发生了什么?
- 根据
which vue
这条指令(在环境变量中查找),找到vue
命令所在文件 - 运行这个文件,执行
vue
和执行node/bin/vue
的结果是一样的 - 根据软连接,执行真实的
lib/node_modules/@vue/cli/bin/vue.js
文件
为什么 vue
指向一个 js
文件,我们却可以直接通过 vue
命令去执行它?
查看 lib/node_modules/@vue/cli/bin/vue.js
文件的源码,会发现第一行代码是这样的
#!/usr/bin/env node
它的意思就是在环境变量中查找使用 node
命令来运行此文件。
为什么说脚手架本质是操作系统的客户端?
因为 node
本身是一个客户端,在 windows
系统下,可以看到 node
的安装目录中,node
是以 node.exe
的形式出现的。
而我们编写的脚手架文件,如 vue.js
只是 node
运行时的一个参数。
node vue.js
如何为 node 脚手架创建别名?
软连接是可以嵌套的,只需让别名指向原来的名字即可。
脚手架执行的全过程
脚手架开发流程
开发流程
- 创建
npm
项目 - 创建脚手架入口文件,最上方添加
#!/usr/bin/env node
- 配置
package.json
文件,添加bin
属性,指定脚手架名称和入口文件地址 - 编写脚手架代码
- 将脚手架发布到
npm
使用流程
- 安装脚手架
npm i -g @vue/cli
- 使用脚手架
vue create project
脚手架开发难点
- 分包:将复杂的系统拆分成多个模块
- 命令注册
- 参数解析
- 帮助文档
- 命令行交互
- 日志打印
- 命令行文字变色
- 网络通信:
HTTP/WebSocket
- 文件处理
- ... ...
开发一个简单的脚手架
- 新建文件夹
test-cli
mkdir test-cli
- 进入到
test-cli
,- 初始化npm
包,通过code .
可以快速使用vscode
打开当前文件夹。
cd test-cli
npm init -y
code .
- 添加
bin/index.js
文件,内容如下
// bin/index.js
#!/usr/bin/env node
console.log('