环境搭建
工欲善其事必先利其器,使用Rollup搭建Typescript开发环境。毕竟Typescript是大势所趋并且Rollup相比较webpack对于node模块来说比较优化。
创建项目目录并初始化
mkdir <projectName> && cd <projectName> && yarn init -y
创建基础目录结构
├── bin #可执行文件目录
│ └── index.js
├── lib #编译后产物
└── package.json
bin/index.js
#!/usr/bin/env node
console.log('hello cli')
package.json
{
"name": "wz-jenkins",
"version": "1.0.0",
"description": "terminal call jenkins",
"main": "lib/index.js",
"bin": "bin/index.js",
"repository": "git@github.com:a20070322/wz-jenkins.git",
"author": "ZhaoZhongYang <z1031839775@gmail.com>",
"license": "MIT"
}
测试
# 将npm模块链接至全局
npm link
# 执行命令 package.json中的name
wz-jenkins
# 输出 hello cli
搭建rollup环境
为了方便解释包的作用,此处分开下载依赖
# rollup打包工具
yarn add rollup -D
# rollup文件夹清除插件
yarn add rollup-plugin-cleandir -D
# rollup解析及编译TS插件
yarn add @rollup/plugin-typescript -D
# 将json转换为ES6模块
yarn add @rollup/plugin-json -D
# 解析代码中依赖的node_modules
yarn add @rollup/plugin-node-resolve -D
#
yarn add @rollup/plugin-commonjs
# 下载ts模块
yarn add typescript -D
# 下载eslist
yarn add eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
.eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:@typescript-eslint/recommended'
],
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
ecmaVersion: 2020,
sourceType: 'module',
createDefaultProgram: true,
},
rules: {
}
}
tsconfig.json
{
"compilerOptions": {
"rootDir": "./",
"types": ["node"],
"target": "ESNext",
"module": "CommonJS",
"declaration": true,
"outDir": "lib",
"strict": true,
"esModuleInterop": true,
"pretty": true,
"resolveJsonModule": true,
"typeRoots": ["./node_modules/@types/", "./src/typings/"]
},
"include": ["src", "types.d.ts"],
"exclude": ["lib"]
}
rollup.config.js
/** 将json转换为ES6模块 */
const json = require("@rollup/plugin-json");
/** rollup解析及编译TS插件 */
const typescript = require("@rollup/plugin-typescript");
/** 解析代码中依赖的node_modules */
const resolve = require("@rollup/plugin-node-resolve");
/** 将 CommonJS 模块转换为 ES6 的 Rollup 插件 */
const commonjs = require("@rollup/plugin-commonjs");
/** rollup文件夹清除插件 */
const { cleandir } = require("rollup-plugin-cleandir");
module.exports = {
/** 打包入口文件 */
input: ["./src/index.ts", "./src/cli.ts"],
/** 输出配置 */
output: {
/** 输出目录 */
dir: "./lib",
/** 输出文件为 CommonJS格式 */
format: "cjs",
},
plugins: [
/** 配置插件 - 每次打包清除目标文件 */
cleandir("./lib"),
/** 配置插件 - 将json转换为ES6模块 */
json(),
/** 配置插件 - 将json转换为ES6模块 */
typescript({
module: "esnext",
exclude: ["./node_modules/**"],
}),
resolve.default({
extensions: [".js", ".ts", ".json"],
modulesOnly: true,
preferredBuiltins: false,
}),
commonjs({ extensions: [".js", ".ts", ".json"] }),
],
};
package.json
增加了scripts命令
{
"name": "wz-jenkins",
"version": "1.0.0",
"description": "terminal call jenkins",
"main": "lib/index.js",
"bin": "bin/index.js",
"scripts": {
"lint": "eslint 'src/**/*.{js,ts}' --fix",
"dev": "rollup -w -c",
"build": "rollup -c"
},
"repository": "git@github.com:a20070322/wz-jenkins.git",
"author": "ZhaoZhongYang <z1031839775@gmail.com>",
"license": "MIT",
"devDependencies": {
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.7.0",
"rollup": "^2.64.0",
"rollup-plugin-cleandir": "^2.0.0",
"typescript": "^4.5.4"
},
"dependencies": {
"cac": "^6.7.12"
}
}
目前工程目录如下
├── LICENSE
├── README.md
├── bin # 可执行文件目录
│ └── index.js
├── lib # 编译后产物
│ ├── cli.js
│ └── index.js
├── package.json
├── rollup.config.js # rollup配置文件
├── src # 源代码
│ ├── cli.ts # cli相关函数通过此文件暴露
│ └── index.ts # 暴露方法,其他项目通过包引用
├── tsconfig.json # typescript配置文件
└── yarn.lock
代码示例01
命令行工具
下载 cac 包
yarn add cac
cac 基础使用
src/cli.ts
import cac from "cac";
import { name, version } from "../package.json";
const cli = cac(name);
/** cli命令数组 */
cli.commands = [
/** 命令行 命令name , 命令描述 , 命令配置 */
cli.command("", "执行jenkins脚本").action(() => {
console.log("hello cli");
}),
];
/** cli-帮助 */
cli.help();
/** cli-版本*/
cli.version(version);
/** 解析命令行参数 */
cli.parse();
/** 异常处理函数 */
const one rror = (err: Error): void => {
console.error(`错误异常: ${err.message}`);
console.log(err.stack);
process.exit(1);
};
/** 监听 uncaughtException 异常 */
process.on("uncaughtException", one rror);
/** 监听 unhandledRejection 异常 */
process.on("unhandledRejection", one rror);
本地监听编译输出 yarn dev
检验成果(终端执行如下命令)
wz-jenkins
# 输出 hello cli
wz-jenkins -v
# 输出 wz-jenkins/1.0.0 darwin-x64 node-v14.15.1
wz-jenkins -h
# 输出
# wz-jenkins/1.0.0
# Usage:
# $ wz-jenkins
# Commands:
# 执行jenkins脚本
# For more info, run any command with the `--help` flag:
# $ wz-jenkins --help
# Options:
# -h, --help Display this message
# -v, --version Display version number
chalk (命令行色彩)
# 下载 chalk
yarn add chalk@4.*
目前只能用4.x版本,更高的版本使用的时候会报错。有更好的解决办法可以评论或私信
src/cli.ts
// 伪代码
// 引入chalk
import chalk from "chalk";
/** cli命令数组 */
cli.commands = [
/** 增加一个 command */
cli.command("chalk", "test console color").action(() => {
console.log(chalk.blue("Hello cli!"));
console.log(chalk.blue("Hello") + " World" + chalk.red("!"));
console.log(chalk.blue.bgRed.bold("Hello world!"));
console.log(chalk.blue("Hello", "World!", "Foo", "bar", "biz", "baz"));
console.log(chalk.red("Hello", chalk.underline.bgBlue("world") + "!"));
console.log(
chalk.green(
"I am a green line " +
chalk.blue.underline.bold("https://github.com/") +
" that becomes green again!"
)
);
console.log(`
CPU: ${chalk.red("90%")}
RAM: ${chalk.green("40%")}
DISK: ${chalk.yellow("70%")}
`);
console.log(chalk.rgb(123, 45, 67).underline("Underlined reddish color"));
console.log(chalk.hex("#DEADED").bold("Bold gray!"));
const error = chalk.bold.red;
const warning = chalk.hex("#FFA500");
console.log(error("Error!"));
console.log(warning("Warning!"));
const name = "Sindre";
console.log(chalk.green("Hello %s"), name);
}),
];
终端执行命令 wz-jenkins chalk
ora (命令行loading)
# 下载 ora
yarn add ora@5.*
# 下载 logSymbols
yarn add logSymbols
目前只能用5.x版本,更高的版本编译时候会报错,有更好的解决办法可以评论或私信
src/cli.ts
// 伪代码
// 引入ora
import ora from "ora";
// 引入logSymbols
import logSymbols from "log-symbols";
/** cli命令数组 */
cli.commands = [
cli.command("ora", "test console color").action(async () => {
/**
* 模拟耗时任务
* @param timer 定时器参数
* @returns
*/
const sleep = (timer = 1000) =>
new Promise<void>((resolve) => {
setTimeout(() => resolve(), timer);
});
/** 开启任务1 loading状态 */
const spinnerTask1 = ora("run mock task one").start();
await sleep();
/** 结束任务1 并且保留内容且改为成功标识 */
spinnerTask1.stopAndPersist({
prefixText: logSymbols.success,
});
/** 开启任务2 loading状态 */
const spinnerTask2 = ora("run mock task two").start();
await sleep();
/** 结束任务2 并且保留内容且改为错误标识 */
spinnerTask2.stopAndPersist({
prefixText: logSymbols.error,
});
/** 开启任务3 loading状态 */
const spinnerTask3 = ora("run mock task three").start();
await sleep();
/** 结束任务3 清除浏览器输出 */
spinnerTask3.stop();
}),
];
终端执行命令 wz-jenkins ora
cac传送门 | chalk传送门 |
ora传送门 |
logSymbols传送门 | 代码传送门
控制台输出函数封装
src/utils/log.ts
import chalk from "chalk";
import logSymbols from "log-symbols";
import ora from "ora";
/** 获取堆栈信息 */
const getStackTrace = function () {
const obj: Error = { name: "", message: "" };
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Error.captureStackTrace(obj, getStackTrace);
return obj.stack || "";
};
/** 控制台输出封装 */
export const Log = {
/** info */
info(...args: unknown[]) {
console.log(chalk.cyan("Info:"), chalk.cyan(...args));
},
/** warn */
warn(...args: unknown[]) {
console.log(chalk.yellow("Warn:"), chalk.yellow(...args));
},
/** error */
error(...args: unknown[]) {
console.log(chalk.red("Error:"), chalk.red(...args));
const stack = getStackTrace() || "";
const matchResult = stack.match(/\(.*?\)/g) || [];
const line = matchResult[1] || "";
console.log(`${chalk.gray("Error stack:")} ${chalk.gray(line)}`);
},
/**
* loadingPromise
* @param msg 值
* @param fn 异步函数
* @returns
*/
async loadingPromise<T>(msg: string, fn: () => Promise<T>) {
const spinner = ora(chalk.cyan(`Loading ${msg}`)).start();
try {
const result = await fn();
spinner.stopAndPersist({
prefixText: logSymbols.success,
text: chalk.green(`Success ${msg}`),
});
return result;
} catch (error) {
spinner.color = "red";
spinner.stopAndPersist({
prefixText: logSymbols.error,
text: chalk.red(`Error ${msg}`),
});
throw error;
}
},
};
效果如下