项目创建
npm i lerna
lerna init
- 创建主目录:commands、cli(core)、modles、utils
- 创建主包:@xx/commands、@xx/core、@xx/modles、@xx/utils
- 修改主包:各包主入口改为index.js
- 移动主包 至 主目录
- 创建README.md
- 创建 .gitignore
// cli(core)> package.json
// 配置环境变量中的名词,执行命令名称
"bin": {
"lhtt": "lib/index.js"
},
// .gitignore 文件
.vscode
.idea
node_modules
core/**/node_modules
utils/**/node_modules
models/**/node_modules
commands/**/node_modules
packages/**/node_modules
core/**/package-lock.json
utils/**/package-lock.json
models/**/package-lock.json
commands/**/package-lock.json
packages/**/package-lock.json
lerna-debug.log
// core/cli/lib/index.js
#! /usr/bin/env node
const commands = require('@lhtt/commands')
console.log('Welcome to lhtt!')
发布上线
- 提交:
git add .
git commit -m 'init'
- 登录:
git
- 登录:
npm login
- 仓库:
git remote add origin https://gitee.com/dragonliuhu/lhtt.git
git remote add origin https://gitee.com/dragonliuhu/lhtt.git
git push -u origin "master"
git push
- 发布:
lerna publish
链接本地脚手架
链接本地库文件
cd self-lib-dir
npm link
cd self-cli-dir
npm link self-lib
取消链接本地库文件
cd self-lib-dir
npm unlink
cd self-cli-dir
npm unlink self-lib
1、core 核心模块
1.1、命令执行流程
// core/cli/bin/index.js
#! /usr/bin/env node
const log = require('@lhtt/log')
const importLocal = require('import-local')
if (importLocal(__filename)) {
log('info', 'lhtt', '正在使用lhtt-cli 本地版本')
} else {
require('../lib')(process.argv.slice(2))
}
1.1.1、命令准备阶段
1.1.1.1. 检查版本号
// 在cli/lib/index.js
const pkg = require('../package.json')
function checkVersion() {
log('success', '版本', pkg.version, ' lhtt ')
}
1.1.1.2. 检查node版本
// 在cli/lib/index.js
const CONST = require('./const')
function checkNodeVersion() {
let c_v = process.version // 当前版本
let l_v = CONST.LOWER_NODE_VERSION // 最低版本
if (!semver.gte(c_v, l_v)) {
throw new Error(colors.red(`${Object.keys(pkg.bin)[0]} 需要安装 v${CONST.LOWER_NODE_VERSION} 以上版本node.`))
}
}
1.1.1.3. 检查root启动
// 在cli/lib/index.js
function checkRoot() {
// v1.0.0
const rootCheck = require('root-check')
rootCheck()
}
1.1.1.4. 检查用户目录
// 在cli/lib/index.js
function checkUserHome() {
if (!userHome || !pathExist(userHome)) {
throw new Error(colors.red('当前登录用户主目录不存在'))
}
}
1.1.1.5. 检查入参
// 在cli/lib/index.js
function checkParams() {
let argv = minimist(process.argv.slice(2))
process.env.LOG_LEVEL = argv.debug ? 'verbose' : 'info'
log.setLevel(process.env.LOG_LEVEL) // 这里是自己封装的log
}
// 基于npmlog封装的log
module.exports = log;
const npmlog = require('npmlog')
/**
* @param {string} level = // 看上面 // 日志类型
* @param {string} title = '' // 日志标题
* @param {string} color = '' // 日志内容
* @param {string} content = '' // 日志颜色
*/
npmlog.level = process.env.LOG_LEVLE || 'info'
function log(level, title, content, appName='') {
npmlog.heading = appName
npmlog.headingStyle = { fg: 'black', bg: 'white'}
npmlog[level](title, content)
}
log.setLevel = (level) => {
npmlog.level= level
}
npmlog.addLevel('silly', -Infinity, { inverse: true }, '全部')
npmlog.addLevel('verbose', 1000, { fg: 'cyan', bg: '' }, '测试')
npmlog.addLevel('info', 2000, { fg: 'blue' }, '消息')
npmlog.addLevel('timing', 2500, { fg: 'green', bg: '' }, '运行')
npmlog.addLevel('http', 3000, { fg: 'green', bg: '' }, '请求')
npmlog.addLevel('notice', 3500, { fg: 'cyan', bg: '' }, '通知')
npmlog.addLevel('warn', 4000, { fg: 'yellow', bg: '' }, '警告')
npmlog.addLevel('error', 5000, { fg: 'red', bg: '' }, '错误')
npmlog.addLevel('silent', Infinity)
npmlog.addLevel('success', 2000, { fg: 'green', bg: '' }, '成功')
1.1.1.6. 检查环境变量
const path = require('path')
// 检查环境变量
function checkEnv() {
const dotenv = require('dotenv')
const dotenvPath = path.resolve(userHome, '.env')
// 用户主目录下存在则用
if (pathExist(dotenvPath)) {
dotenv.config({
path: dotenvPath
})
}
createDefaultConfig()
log('verbose', '脚手架路径', process.env.LHTT_CLI_HOME_PATH)
}
// cli配置路径
function createDefaultConfig() {
let cliHome = ''
if (process.env.CLI_HOME) {
cliHome = path.join(userHome, process.env.CLI_HOME)
} else {
cliHome = path.join(userHome, CONST.DEFAULT_CLI_HOME)
}
process.env.LHTT_CLI_HOME_PATH = cliHome
}
1.1.1.7. 检查是否最新版本
async function checkUpdate() {
const version = pkg.version
const npmName = pkg.name
const axios = require('axios')
const urlJoin = require('url-join')
const argv = minimist(process.argv.slice(2))
const registryUrl = argv.taobaoNpm ? 'https://registry.npm.taobao.org' : 'https://registry.npmjs.org'
const npmInfoUrl = urlJoin(registryUrl, npmName)
await axios.get(npmInfoUrl).then(res => {
// 如果成功执行下面,则比较,否则不用比较
try {
if (Object.keys(res.data.versions).length > 1) {
// 满足条件的不版本号
const satisfiesVersion = Object.keys(res.data.versions).filter(v => semver.gt(v, version)).sort((a, b) => semver.gt(b, a))
if (satisfiesVersion.length > 0) {
log('warn', '更新提示', colors.yellow(`当前版本:v${version},最新版本:v${satisfiesVersion.reverse()[0]}`))
}
} else {
// 抛出异常,线上找不到发布过的脚手架
// throw new Error('')
}
} catch (e) {
log('warn', '', '线上版本不存在!')
}
}).catch(err => {
log('error', '', '检查版本不成功!')
})
}
1.1.2、命令注册阶段
1.1.2.1. 注册init
1.1.2.2. 注册publish
1.1.2.3. 注册clean
1.1.2.4. 支持debug
1.1.3、命令执行阶段