使用 lerna 开发一个脚手架
git规范
master
仓库、dev
开发、release
上线
- 开始开发创建分支
dev/0.0.1
- 上线
push
并marge
分支dev/0.0.1
到master
分支 - 打上标签
release/0.0.1
- 删掉
dev/0.0.1
分支 - 开发的时候自动创建
dev/0.0.2
分支
git repo
—fork—>own git repo
—clone—>loal repo
(本地创建分支开发,一般由脚手架统一管理比较好)
开发完成后loal repo
—push—>own git repo
—pull requests—code review(代码检查/评审)—合并—>git repo
—>打个tag
,删掉开发分支
脚手架开发流程
脚手架项目初始化
npm init -y
# 初始化 npm 项目cnpm install --global lerna
# 安装 lerna(如果 cnpm 不好使可以用 yarn)cnpm i -D lerna
# 安装 lernalerna init
# 初始化项目1
2
3
4
5
6
7
8# .gitignore
.vscode
.idea
node_modules
packages/**/node_modules
lerna-debug.log
# 创建一个 Organizations
[Organizations](https://www.npmjs.com/settings/cxvhweb/packages)
创建 package
lerna create core
lerna create utils
lerna add axios package/core
安装axios
时需要指定路径1
2
3
4
5
6
7
8
9
10
11
12info cli using local version of lerna
lerna notice cli v3.22.1
lerna WARN ENOREMOTE No git remote found, skipping repository property
package name: (core) @cxvh-cli/core # @cxvh-cli 是组织,core是组织下面的包名,这样防止core名称冲突
version: (0.0.0)
description: cxvh-cli core
keywords:
homepage:
license: (ISC)
entry point: (lib/core.js)
git repository:
About to write to E:\learn\cxvh-cli\packages\core\package.json:
发布包
- docs
- 发布流程说明:
- 根目录创建
LICENSE.md
package.json
添加"publishConfig":{"access":"public"}
(所有的package.json
都要加)git commit
后不要push
lerna publish
完成发布
- 根目录创建
lerna 命令
lerna init
初始化项目lerna create core
创建package
lerna add @cxvh-cli
安装依赖(到所有的包)lerna add @cxvh-cli ./commands/init
添加依赖到指定包lerna link
链接依赖(在项目根目录执行)——>相当于npm link @cxvh-cli/utils
(先手动配置要连接的依赖/packages/core/package.json
,会在node_modules
下面生成软连接)lerna clean
清空依赖(需要手动删除 package 里面的依赖名称)lerna bootstrap
重新安装依赖(相当于npm i
)- 执行
shell
脚本- 在所有
package
里面执行shell
脚本:lerna exec -- rm -rf node_modules
- 在指定
package
里面执行shell
脚本(这里注意是包名不是路径):lerna exec --scope @cxvh-cli/core -- rm -rf node_modules
- 在所有
- 执行
package.json
的scripts
- 在所有
scripts
里面执行脚本:lerna run test
- 在指定
package
里面执行scripts
:lerna run --scope @cxvh-cli/core build
- 在所有
lerna version
更新版本号(代码需要先git commit
)lerna changed
查看上版本以来的所有变更lerna diff
查看diff
lerna publish
项目发布
core模块技术方案—>命令执行流程
准备阶段
检查版本号—>检查node版本(高版本api低版本不支持)—>检查root启动(root启动创建的文件后期无法维护删除,要降级)—>检查用户主目录(拿到主目录,写入缓存要用)—>检查入参—>检查环境变量—>检查是否为最新版本—否—>提示更新
自定义日志样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19;
const log=require('npmlog')
log.level=process.env.LOG_LEVEL?process.env.LOG_LEVEL:'info'; // 判断 debug 模式
log.heading="cxvh"; // 修改前缀
log.headingStyle={fg:"red",bg:"black"}; // 修改前缀样式
log.addLevel('success',2000,{fg:'green',bold:true}); // 添加自定义命令
module.exports = log;
/*
log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
log.addLevel('verbose', 1000, { fg: 'blue', bg: 'black' }, 'verb')
log.addLevel('info', 2000, { fg: 'green' })
log.addLevel('timing', 2500, { fg: 'green', bg: 'black' })
log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
log.addLevel('notice', 3500, { fg: 'blue', bg: 'black' })
log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
log.addLevel('silent', Infinity)
使用方法==>log.notice("提示:","提示内容")
*/检查版本号
1
2
3
4
5const pkg=require('../package.json')
const log=require('@cxvh-cli/log')
function checkPkgVersion(){
log.notice("版本号",pkg.version);
}检查版本号
1
2
3
4
5const currentVersion=process.version;
const lowestVersion="13.0.0";
if(!semver.gte(currentVersion,lowestVersion)){
throw new Error(colors.red(`cxvh-cli 需要安装 v${lowestVersion} 以上版本的 Node.js`));
}root账号启动检查和自动降级功能
1
使用依赖包--->`root-check`
用户主目录检查功能
1
2
3
4
5const userHome = require('user-home');
const pathExists = require('path-exists').sync;
if(!userHome || !pathExists(userHome)){
throw new Error(colors.red('当前主目录不存在!'));
}入参检查和debug模式开发
1
2
3
4
5
6
7
8
9
10
11
12function checkInputArgs(){
args = require('minimist')(process.argv.slice(2));
checkArgs();
}
function checkArgs(){
if(args.debug){
process.env.LOG_LEVEL="verbpse"
}else{
process.env.LOG_LEVEL="info"
}
log.level=process.env.LOG_LEVEL
}环境变量检查功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function checkEnv(){
const dotenvPath=path.resolve(userHome,'.env')
if(pathExists(dotenvPath)){
let config=require('dotenv').config({
path:dotenvPath
})
}
createDefaultConfig()
log.verbose("环境变量",process.env.CLI_HOME_PATH)
}
function createDefaultConfig(){
const cliConfig={
home:userHome
}
if(process.env.CLI_HOME){
cliConfig['cliHome']=path.join(userHome,process.env.CLI_HOME)
}else{
cliConfig['cliHome']=path.join(userHome,constant.DEFAULT_CLI_HOME)
}
process.env.CLI_HOME_PATH=cliConfig.cliHome;
}通用npm API模块封装
核心库
import-local
优先执行本地命令commander
命令注册
工具库
npmlog
打印日志,在它基础上封装fs-extra
文件操作,基于fs
封装了许多操作文件的方法semver
脚手架版本是否最新,用这个来实现判断colors
打印的日志等信息加上颜色user-home
拿到用户主目录dotenv
获取环境变量root-check
判断当前是否为管理员用户- ``
拆包策略
根据模块的功能拆分
- 核心流程模块:
core
- 命令模块:
commands
- 初始化
- 发布
- 清除缓存
- 模型层模块:
models
command
命令project
项目component
组件npm
模块git
仓库
- 工具模块(支撑模块):
utils
git
操作- 云构建
- 工具方法
api
请求git api
改造多进程
1 | ; |
相关依赖
- yargs通过解析参数并生成优雅的用户界面来帮助您构建交互式命令行工具
小技巧
npm link
时删掉node_modules
和package-lock.json
,会自动生成package-lock.json
并安装依赖lerna add
不指定路径就是安装到所有模块,一般会指定如:lerna add axios packages/core
- 操作没问题的情况下报错==>
coannot find module '@cxvh-cli/log'
如何解决?重新lerna link
lerna add colors core/cli
相当于在core/cli
文件夹下执行npm i -S colors
npm unlink test
其它路径执行需要指定包名node
的require
支持加载:1.绝对路径;2.相对路径;3.内置模块;4.加载node_modules
的模块node
支持字符串代码,如:node -e "require('./core/cli/bin/index.js')"
相关知识点、拓展手册
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 BARAN的小站🔥🔥🔥!