一、认识脚手架
1. 为什么要开发脚手架
前端开发现状
- 创建项目 & 通用代码:埋点、HTTP 请求、工具方法、组件库
- git 操作:创建仓库、代码冲突、远程代码同步、创建版本、发布打 tag
- 发布上线:依赖安装和构建、资源上传CDN、域名绑定、测试/正式服务器
核心价值:
- 自动化:项目重复代码拷贝/git操作/发布上线操作
- 标准化:项目创建/git flow/发布流程/回滚流程
- 数据化:研发过程系统化、数据化、使得研发过程可量化
jenkins、travis等自动化构建工具已经比较成熟了,为什么还需要自研脚手架?
- 不满足需求: 通常在 git hooks 中触发,需要在服务端执行,无法覆盖研发人员本地的功能,比如:创建项目自动化、本地 git 操作自动化等
- 定制复杂: 定制过程需要开发插件,过程较为复杂;需要使用java语言,对前端同学不够友好
2. 从使用的角度理解什么是脚手架
创建项目
- 标准模版创建
- 自定义规则创建
- 创建组件库
- 自动安装和启动
发布项目
- Git 自动化
- 云构建
- 项目自动发布
- 组件自动发布
3. 脚手架的执行原理 - 以 vue 为例
- 在终端输入 vue create vue-test-app
- 终端解析出 vue 命令
- 终端在环境变量中找到 vue 命令
- 终端根据 vue 命令链接到实际文件 vue.js
- 终端利用 node 执行 vue.js
- vue.js 解析 command / options
- vue.js 执行 command
- 执行完毕,退出执行
4. 从应用的角度看如何开发一个脚手架(以 vue-cli 为例):
- 开发 npm 项目,项目中要包含一个 bin/vue.js 文件,并将这个项目发布到 npm
- 将 npm 项目安装到 node 的 lib/node_modules
- 在 node 的 bin 目录下配置 vue 软链接指向 lib/node_modules/@vue/cli/bin/vue.js
这样在执行 vue 命令的时候就可以找到 vue.js 并执行
疑问:
- 为什么全局安装 @vue/cli 后会添加的命令为 vue ? vue cli 下面的 package.jspn 里面的 bin 指定了软链接 vue: 'bin/vue.js'
- 全局安装 @vue/cli 时发生了什么?
- 把依赖下载到指定 node_module 目录下面
- 配置一个 bin 的软链接
- 执行 vue 命令的时候发生了什么?为什么 vue 指向一个 js 文件,我们却可以直接通过 vue 命令直接去执行它?
- 在环境变量当中找 vue 命令有没有被注册
- js 文件需要通过一个解释器进行执行 ---- node
- vue.js 有一行 #!/usr/bin/env node -> 告诉操作系统,在直接调用这个文件的时候去环境变量中找 node 这个命令,通过 node 命令去执行
可以通过 echo $PATH 看到当前环境所有的环境变量
5. 脚手架原理进阶
- 为什么说脚手架本质是操作系统的客户端?它和我们在PC上安装的应用/软件有什么区别?
- 因为 node 本身是一个客户端,用 node 来执行,本质没有区别
- 如何为 node 脚手架命令创建别名?
- 在 bin 目录下创建软链接:ln -s /Users/fanzhang/Desktop/vue-test/test.js ice
- 可以嵌套
- 描述脚手架命令执行的全过程
- 输入 vue create vue-test-app
- 在环境变量 $PATH 中查询 vue 命令 --- 相当于 which vue
- 查询实际链接文件
- 通过 /usr/bin/env node 执行文件
6. 脚手架开发流程和难点解析
开发流程
- 创建 npm 项目
- 创建脚手架入口文件,最上方添加 #!/usr/bin/env node
- 配置 package.json ,添加 bin 属性
- 编写脚手架代码
- 将脚手架发布到 npm
使用流程
- 安装脚手架:npm install -g your-own-cli
- 使用脚手架:your-own-cli
难点解析
- 分包:将复杂的系统拆分成若干个模块
- 命令注册:create add
- 参数解析:vue command [options]
- options 全称 和 简写
- 带 params 的 options:--path /users/Desktop/vue-test
- 帮助文档
- global help
- Usage Options Commands
- command help
- Usage options
- global help
- 其他
- 命令行交互
- 日志打印
- 网络通信:HTTP/webSocket
- ...
二、开发第一个脚手架
1. 新建脚手架
$ mkdir ice
$ cd ice
$ npm init
$ touch bin/index.js
bin/index.js
#!/usr/bin/env node
package.json 新增 bin 属性
ice: bin/index.js
$ npm login
$ npm publish
2. 本地安装脚手架
$ npm install -g ice
3. 本地调试
- npm link ice --- (常用)
- 在存在 ice 的文件夹下 npm install
- 在环境变量中创建短链: ln -s 本地链接 ice
4. 脚手架本地 link 标准流程、分包
链接本地脚手架
$ cd your-link-dir
$ npm link
链接本地库文件
$ cd your-lib-dir
$ npm link
$ cd your-cli-dir
$ # link 存在
$ npm link your-lib-dir
$ # link 不存在
$ rm -rf node_modules
$ npm install
取消链接本地库文件
$ cd your-lib-dir
$ npm unlink
$ cd your-cli-dir
$ npm unlink your-lib-dir
- 理解 npm link
- npm link your-lib: 将当前项目中 node_modules 下指定的库文件链接到全局 node_modules 下的库文件
- npm link:将当前项目链接到 node 全局 node_modules 中作为一个库文件,并解析 bin 配置创建可执行文件
- 理解 npm unlink
- npm unlink:将当前项目从 node 全局 node_modules 中移除
- npm unlink your-lib:将当前项目中的库文件依赖移除
5. 脚手架命令注册和参数解析
6. 原生脚手架开发痛点分析
- 痛点一:重复操作
- 多 package 本地 link
- 多 package 依赖安装
- 多 package 单元测试
- 多 package 代码提交
- 多 package 代码发布
- 痛点二:版本一致性
- 发布后版本一致性
- 发布后相互依赖版本升级
三、lerna
1. 认识 lerna
lerna 是一个优化基于 git+npm 的多 package 项目的管理工具
优势:
- 大幅减少重复操作
- 提升操作的标准化
lerna 是架构优化的产物,它揭示了一个架构真理:项目复杂度提升后,就需要对项目进行架构优化。 架构优化的主要目标往往都是以效能为核心的。
使用 Lerna 管理的大型项目:
- babel
- vue-cli
- create-react-app
2. 基于lerna搭建脚手架框架
lerna 开发脚手架流程
- 脚手架项目初始化
- 初始化 npm 项目
- 安装 lerna
- lerna init 初始化项目
- 创建 package --- 子项目
- lerna create 创建 package
- lerna add 安装依赖
- lerna link 链接依赖
- 脚手架开发和测试
- lerna exec 执行 shell 脚本
- lerna run 执行 npm 命令
- lerna clean 清空依赖
- lerna bootstrap 重装依赖
- 脚手架发布上线
- lerna version bump version
- lerna changed 查看上版本以来的所有变更
- lerna diff 查看diff
- lerna publish 项目发布