npm-cli-造轮子初体验

我亲手造了一个 npm CLI 命令,然后发现 vite、eslint 全是这么来的

实习第一天,我连「npm 包怎么变成一个命令行命令」都没认真想过。直到今天,我和一个 AI 搭子从零搓了一个 hello 命令------然后突然意识到,我每天在用的那些工具,背后藏的是同一套小秘密。


一、先建一个 npm 项目

bash

bash 复制代码
mkdir hello-cli
cd hello-cli
npm init -y

跑完之后,目录里多了一个 package.json:

go 复制代码
hello-cli/
└── package.json

这一步的意义其实就一句话:

告诉 npm:「这里是一个 Node.js 包项目。」


二、在 package.json 里声明一个命令

我们往 package.json 里加了一行关键的东西:

json

json 复制代码
{
  "name": "hello-cli",
  "version": "1.0.0",
  "bin": {
    "hello": "./cli.js"
  }
}

重点就是这段:

json

json 复制代码
"bin": {
  "hello": "./cli.js"
}

它的意思是:

如果用户在终端输入 hello,就去执行 ./cli.js。

bin 本质上是一张「命令名 → 文件」的地图 🗺️。


三、写真正干活的代码

然后我们创建了 cli.js:

javascript

javascript 复制代码
#!/usr/bin/env node

console.log("🎉 Hello! 我的第一个 npm CLI 包!");

开头这行:

javascript

javascript 复制代码
#!/usr/bin/env node

是告诉系统:

用 Node.js 来运行这个文件。

下面那行 console.log,就是这个命令真正要做的事。


四、把它装到全局

接下来执行:

bash

erlang 复制代码
npm install -g .

这里两个细节:

  • . 表示「当前目录这个包」
  • -g 表示「全局安装」

npm 做了一件很关键的事------它读了 package.json,发现了 bin,然后在系统里注册了 hello 这个命令。


五、终于可以直接运行了

以前要这样跑:

bash

复制代码
node cli.js

现在只要:

bash

复制代码
hello

终端立刻输出:

objectivec 复制代码
🎉 Hello! 我的第一个 npm CLI 包!

🎉 你的电脑刚刚「认识」了一个你自己创造的新命令。


整个流程串起来

go 复制代码
创建项目
   │
   ↓
package.json
   │
   ↓
定义 bin:hello → cli.js
   │
   ↓
npm install -g .
   │
   ↓
系统注册 hello 命令
   │
   ↓
终端输入 hello
   │
   ↓
Node 执行 cli.js
   │
   ↓
看到输出

我们真正搞懂的,其实就这几样东西:

东西 作用
package.json 描述 npm 包的信息
bin 暴露命令入口(命令名 → 文件)
cli.js 命令实际执行的代码
#!/usr/bin/env node 指定用 Node 执行(主要给 Unix 看)
npm install -g 全局安装命令
CLI Command Line Interface,命令行工具

让我「哦!」一下的三个彩蛋

这个实验做完,我又追问了几个问题,结果挖出三个挺反直觉的点:

1. 在 Windows 上,那行 shebang 其实「没生效」

我写的 #!/usr/bin/env node,是 Unix / Mac 的规矩。Windows 根本不看这行。

那我的 hello 为什么还能跑?因为 npm install -g 在 Windows 上不是建软链接,而是生成了几个包装文件:

objectivec 复制代码
hello        ← 给 Git Bash 用
hello.cmd    ← 给 CMD 用
hello.ps1    ← 给 PowerShell 用

真正找到 node 去执行 cli.js 的,是这几个 .cmd / .ps1。shebang 只是「跨平台留个后手」,让同一份代码在 Mac 上也能跑。很多人以为删了 shebang Windows 就坏了------其实没关系。

install -g . 是「复制一份装进全局」。你每改一次 cli.js,都得重装,很烦。

开发阶段应该这样:

bash

bash 复制代码
npm link      # 在包目录里执行一次

它会做一个软链接 指向你的项目。之后你改代码,hello 命令立刻是最新的,不用重装。用完 npm unlink 解绑即可。

3. 命令还分「全局」和「本地」

你装的是全局命令 (-g)。但真实项目里,90% 的命令其实是本地的,躺在:

bash 复制代码
node_modules/.bin/

比如你 npm install 之后,vite 其实装在 node_modules/.bin/vite,并没进全局。你能在 package.json 的 scripts 里直接写 "dev": "vite",是因为 npm 跑 script 时会自动把 node_modules/.bin 加进 PATH。


结尾:你刚打开的是一扇门

最有意思的一点是------你刚刚做的事,和很多大型工具本质一样:

markdown 复制代码
你的 hello
      ↓
npm 包
      ↓
bin
      ↓
终端命令

和:

markdown 复制代码
vite
      ↓
npm 包
      ↓
bin
      ↓
vite 命令

是同一套机制。

只是 Vite 里面不是打印一句 Hello,而是启动开发服务器、构建项目 😂

所以你刚刚其实不是「玩了个小例子」,而是亲手拆开了 npm 生态的一扇门 🚪✨ 以后看到 vite、eslint、tsc 这些命令,你会知道它们背后都藏着一个类似的 bin 小秘密。

一句话钉进脑子:

bin 定义命令、scripts 编排命令、.bin 存放本地命令、npm link 用于开发、shebang 是给 Unix 看的。


本文所有示例均为脱敏后的通用技术演示,不涉及任何公司项目细节。

相关推荐
hasty20 小时前
不上传新包,也能改变用户拿到的版本:npm dist-tag 的 OIDC 权限治理
前端·npm·node.js
玖石书2 天前
HiSH 通过 apk 安装 Node.js、npm 与 pnpm
npm·node.js·鸿蒙·hish
FACELESS VOID2 天前
wsl下使用npm,错误识别到了windows下的npm
linux·windows·npm
搬砖的小码农_Sky4 天前
AI Agent:Windows上Node.js安装后 npm -v报错
前端·npm·node.js·人机交互
梅孔立6 天前
Codex 完整教程(Node.js安装 + npm安装Codex + DeepSeek配置 + 快捷键 + 设置)
前端·npm·node.js
AlfredZhao13 天前
npm 源切换:一条命令搞定
npm
@tangguo12314 天前
npm 和 yarn 配置说明
前端·javascript·npm·node.js·yarn
钝挫力PROGRAMER18 天前
npx 与 npm 全局安装/更新/卸载
npm·npx·mcp·dsh
天若有情67320 天前
开源轻量双语工具|一键批量查询 NPM 包历史下载量,支持按作者批量统计
javascript·npm·github pages·开源工具·netlify·前端开源·npm克隆量
柚稚姐姐24 天前
npm install pnpm -g npm error code EACCES npm error syscall symlink
前端·npm·node.js