【笔记】Node.js 开发 CLI 工具
文章目录
- [【笔记】Node.js 开发 CLI 工具](#【笔记】Node.js 开发 CLI 工具)
- 一、简介
- 二、案例:generate-web-component
一、简介
1.Node.js
Node.js 是一种让你可以再服务器运行 JavaScript 的运行环境。它不是编程语言,也不是框架,而是一个基于浏览器引擎的工具
核心概念
- 本质:运行 JavaScript 的环境(类似浏览器,但在服务器上运行)
- 基础:基于 Chrome V8 Engine(谷歌浏览器的 JS 引擎)
- 用途:开发后端服务、API、工具脚本等
解决了什么问题
在 Node.js 出现之前:
- JavaScript 只能在浏览器中运行
- 后端通常用 Java、Python、PHP 等
Node.js 出现后:
- 前后端都可以用 JavaScript
- 开发效率更高(统一语言)
核心特点
- 非阻塞 I/O(异步)
- 单线程但高性能
2.CLI
CLI(Command-Line interface),中文叫命令行界面,是一种通过输入文本命令来操作计算机的方式,与图形界面(GUI)相对。
CLI 能做什么
- 文件管理(创建、删除、移动)
- 网络操作(下载、请求 API)
- 开发工具(运行代码、构建项目)
- 包管理(安装依赖)
优点
- 更快(无需鼠标操作)
- 可脚本化(自动化任务)
- 更强控制能力
- 资源占用低
3.create-node-cli
create-node-cli 是一个脚手架工具,用来快速创建一个 Node.js 的 CLI 项目模板。一条命令,帮你生成一个完整的命令行工具项目结构。
官方文档:https://www.npmjs.com/package/create-node-cli
使用方法:
bash
#Recommended.自动下载最新版本,只执行,不安装
npx create-node-cli
#OR an alternative global install.全局安装占空间,版本可能过时
npm install -g create-node-cli
二、案例:generate-web-component
用于自动生成前端 web 组件代码模板
1.执行 create-node-cli

2.配置项

3.npm link

npm 中的 npm link 是一个用于本地开发调试包的命令。核心作用是把你本地写的包,像 "全局安装" 一样,在其他项目中直接使用。
正常流程:
- 写一个 npm 包
- 发布到 npm
- 在另一个项目中安装
问题:
- 发布流程慢
- 每改一次都要重新发布
- 调试效率很低
npm link 可以实现本地实时调试
基本使用步骤
- my-lib:你写的包
- my-app:需要使用这个包的项目
第一步:在 my-lib 中执行
bash
cd my-lib
npm link
把 my-lib 注册成一个全局可用的包
第二步:在使用项目里执行
bash
cd my-app
npm link my-lib
把 my-lib 链接到当前项目的 node_modules
如何取消 link
bash
npm unlink my-lib
#或者在全局
npm unlink -g my-lib
4.编写模板代码

javascript
export default class ExampleComponent extends HTMLElement {
static get observedAttributes() {
return []
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
}
disconnectedCallback() {
}
attributeChangedCallback() {
}
}
customElements.define('example-component', ExampleComponent);
5.CLI 入参配置

6.编写 generateWebComponent 工具

javascript
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
function includesUppercase(str) {
return /[A-Z]/.test(str);
}
function includesDashOrUnderscore(str) {
return /[-_]/.test(str);
}
function convertToTagReadyString(str) {
// 1.假如输入的名称是 mycomponent
if (!includesUppercase(str) && !includesDashOrUnderscore(str)) {
console.log('输入的名称的格式不正确,请使用大驼峰、短横线或蛇形命名法。');
process.exit(1);
}
// 2.假如输入的名称包含_或者-
if (includesDashOrUnderscore(str)) {
return str.split('_').join('-').toLowerCase();
}
// 3.其他格式 MyComponent / myComponent / MyShinyComponent
str = str.replace(/[A-Z]/g, (match) => {
return "-" + match;
});
if (str.startsWith('-')) {
str = str.substring(1);
}
return str.toLowerCase();
}
export default async function (name, destination) {
fs.readFile(
path.join(__dirname, '../templates', 'ExampleComponent.js'),
'utf-8',
(err, data) => {
if (err) {
throw err;
}
// 2.创建目录(放这里也更安全)
if (!fs.existsSync(destination)) {
fs.mkdirSync(destination, { recursive: true });
console.log(`创建了一个文件夹${destination}`);
}
// 3.处理文件名
let filename;
if (name.includes('.')) {
filename = name.split('.')[0];
} else {
filename = name;
}
const tagName = convertToTagReadyString(filename);
const componentName = filename.includes('-')
? filename.replace('-', '_')
: filename;
// 4.替换模板内容
const newData = data
.replace(/ExampleComponent/g, componentName)
.replace(/example-component/g, tagName);
destination = destination.endsWith('/')
? destination.slice(0, -1)
: destination;
name = name.includes('.') ? name : (name + '.js');
// 5.写入文件
fs.writeFile(`${destination}/${name}`, newData, (err) => {
if (err) {
throw err;
}
console.log(`已经在${destination}文件夹中创建了一个文件${name}`);
});
}
);
}
7.index.js 引入 generateWebComponent

index.js 是整个命令行工具的可执行入口:用户安装本包后,通过 package.json 里的 bin 配置的 generate-web-component 或 gwc 命令运行的就是这份脚本。
8.验证

