一、开篇:为什么别人的命令能直接用?
日常开发中,你可能会有这样的疑问:为什么输入 vue create 就能快速创建项目,而自己写的 JavaScript 脚本,每次都要敲长长的 node ./xxx/xxx.js 才能运行?其实,这背后藏着 package.json 里 bin 命令的 "小秘密"。
这篇文章就用最直白的方式,带你搞清楚 bin 命令、shebang 以及 npm link 的作用和用法,看完之后,你也能让自己的脚本像那些常用工具一样,一键就能运行。
二、package.json 的 bin 命令:让脚本 "一键启动"
1. 什么是 bin 命令?
简单来说,bin 命令就是给你的 JavaScript 脚本起一个 "简短别名"。有了这个别名,你不用再输入完整的脚本路径,直接喊出 "别名",就能运行对应的脚本。
比如原本需要输入 node ./bin/my-script.js 才能执行的脚本,配置 bin 命令后,可能只需要输入 my-script 就能运行,大大减少了重复输入的麻烦。
2. 如何配置 bin 命令?
bin 命令的配置很灵活,主要分两种情况,根据你的脚本数量来选择即可:
情况一:只有一个脚本(简单写法)
如果你的项目里只有一个需要便捷运行的脚本,直接在 package.json 中写脚本的相对路径就行。这时,脚本的 "别名" 会默认和你项目的 "name" 字段一致(也就是 package.json 里 "name": "xxx" 中的 xxx)。
举个例子:
json
{
  "name": "my-tool",
  "version": "1.0.0",
  "bin": "./bin/my-script.js"
}
上面的配置中,脚本 ./bin/my-script.js 的别名就是 my-tool,后续直接输入 my-tool 就能运行这个脚本。
情况二:多个脚本(对象写法)
如果项目里有多个需要便捷运行的脚本,就用对象的形式配置,键是你想给脚本起的 "别名",值是脚本的相对路径。
举个例子:
json
{
  "name": "my-tool",
  "version": "1.0.0",
  "bin": {
  "script-one": "./bin/1.js",
  "script-two": "./bin/2.js"
  }
}
这样配置后,输入 script-one 就能运行 ./bin/1.js,输入 script-two 就能运行 ./bin/2.js,清晰又好记。
需要注意的是,脚本路径要从 package.json 所在的文件夹开始计算,比如 package.json 在项目根目录,脚本在根目录下的 bin 文件夹里,路径就写 ./bin/xxx.js,别写错了路径导致脚本找不到。
3. 配置完 bin 还不够,必须加 "shebang"
很多人配置完 bin 命令后,运行时会遇到 "命令未找到" 或 "无法执行脚本" 的错误,这大概率是因为没加 "shebang"。
为什么需要 shebang?
简单来说,shebang 是告诉系统 "用什么程序来运行这个脚本"。如果没有它,系统不知道该用 Node.js 还是其他程序来执行你的 JavaScript 脚本,自然会报错。
什么是 shebang?怎么加?
shebang 就是在你的 JavaScript 脚本文件的第一行,加上 #!/usr/bin/env node 这行代码。不用纠结这行代码的具体含义,直接复制粘贴到脚本第一行就行,它能兼容不同的电脑系统。
举个例子,你的脚本文件 ./bin/my-script.js 应该长这样:
javascript
\#!/usr/bin/env node
// 下面是你的脚本逻辑
console.log("脚本运行成功!");
为什么不能写死路径?
有些资料里可能会写 #!/usr/bin/node,但这种写法有个坑:它假设 Node.js 一定安装在 /usr/bin 这个路径下。但实际中,很多人会用 nvm(Node.js 版本管理器)来管理 Node.js,这时 Node.js 的安装路径可能是 ~/.nvm/versions/node/xxx/bin,或者 Windows 系统里的 C:\Program Files\nodejs。写死路径的话,换一台电脑可能就无法运行了,而 #!/usr/bin/env node 会让系统自动寻找 Node.js 的安装路径,避免这个问题。
4. 动手实操:3 步跑通自己的命令
看完理论,咱们来动手试一次,3 步就能让你的脚本实现 "一键运行":
第一步:建文件夹和文件
先建一个项目文件夹,比如叫 my-first-cli,在里面新建两个东西:
-
一个
package.json文件(可以用npm init -y快速生成); -
一个
bin文件夹,在bin文件夹里新建cli.js文件(这就是你的脚本文件)。
此时项目结构应该是这样:
go
my-first-cli/
├── bin/
│ └── cli.js
└── package.json
第二步:写脚本内容
打开 bin/cli.js,在第一行加上 shebang,再写点简单的逻辑,比如:
javascript
\#!/usr/bin/env node
console.log("我的第一个便捷脚本,运行成功啦!");
第三步:配置 package.json 的 bin 命令
打开 package.json,加上 bin 配置,比如:
json
{
  "name": "my-first-cli",
  "version": "1.0.0",
  "bin": {
  "my-test": "./bin/cli.js"
  }
}
这里我们给脚本起的别名是 my-test,后续输入这个别名就能运行脚本。
三、shebang 详解:脚本的 "运行说明书"
1. 再深入理解:shebang 到底是什么?
前面我们知道了 shebang 是 #!/usr/bin/env node,但它本质上是 Unix/Linux 系统的一个通用规则 ------ 只要脚本文件的第一行以 #! 开头,这行就是 shebang,用来指定执行这个脚本的程序。
对 JavaScript 脚本来说,shebang 就是告诉系统 "用 Node.js 来运行我",相当于给脚本加了一份 "运行说明书"。需要注意的是,它不是注释,而是给系统看的指令,别把它删掉或放到其他行。
2. 为什么 #!/usr/bin/env node 能兼容所有系统?
这里拆解一下 #!/usr/bin/env node 的作用:
-
#!/usr/bin/env:env是系统自带的一个工具,它能读取系统的 PATH 环境变量(PATH 里包含了系统所有可执行程序的安装目录); -
node:env会在 PATH 包含的目录里,找第一个名叫node的可执行文件,找到后就用这个 Node.js 来运行脚本。
不管你的 Node.js 装在 ~/.nvm、C盘 还是其他路径,env 都能找到它,所以这行代码能兼容 Windows、macOS、Linux 等不同系统。
3. Windows 用户不用慌,shebang 兼容问题已解决
很多 Windows 用户会担心:Windows 系统不认识 shebang,会不会影响脚本运行?其实不用怕,npm 和 npx 已经帮我们处理了这个问题。
当你在 Windows 上运行通过 bin 命令配置的脚本时,npm 会自动忽略 shebang,直接用你电脑里当前的 Node.js 来执行脚本,所以不用额外做任何配置,和其他系统一样正常使用。
4. 不止 Node.js,其他脚本也用 shebang
shebang 不是 Node.js 专属的,其他类型的脚本也会用它来指定运行程序。比如:
-
Shell 脚本(.sh 文件):第一行通常是
#!/bin/bash,表示用 bash 程序来运行; -
Python 脚本(.py 文件):第一行通常是
#!/usr/bin/env python3,表示用 Python3 来运行; -
Perl 脚本(.pl 文件):第一行通常是
#!/usr/bin/perl,表示用 Perl 来运行。
了解这个知识点,以后看到其他类型的脚本,也能明白第一行代码的作用。
四、npm link:本地测试的 "神器",不用反复装包
1. 为什么需要 npm link?
当你写完脚本并配置好 bin 命令后,肯定想测试一下能不能正常运行。如果每次修改代码后,都要先把项目发布到 npm 仓库,再用 npm install -g 安装到全局来测试,那也太麻烦了 ------ 这时候,npm link 就能派上用场。
2. 什么是 npm link?
简单来说,npm link 是给你本地的项目创建一个 "快捷方式",并把这个快捷方式链接到系统的全局 npm 目录里。这样一来,你不用发布项目,也不用反复安装,就能像使用 "已发布到 npm 仓库的工具" 一样,在任何目录下运行你的脚本,而且修改代码后,效果会实时生效,不用重新配置。
3. 动手实操:2 步用 npm link 测试命令
还是用前面的 my-first-cli 项目举例,2 步就能完成测试:
第一步:把项目链接到全局
打开终端,进入 my-first-cli 文件夹(也就是 package.json 所在的目录),输入命令:
bash
npm link
执行完后,系统会提示 "链接成功",此时你的 my-test 命令已经被添加到全局了。
第二步:测试命令
不用停留在 my-first-cli 文件夹,随便找一个其他目录(比如你的桌面),在终端输入:
perl
my-test
如果看到输出 "我的第一个便捷脚本,运行成功啦!",就说明测试成功了。
如果后续修改了 bin/cli.js 里的代码,比如把输出改成 "脚本更新啦!",不用重新执行 npm link,直接在终端再次输入 my-test,就能看到更新后的效果,非常方便。
4. npm link 不止能测命令,还有 2 个常用场景
npm link 不止用来测试 bin 命令,在本地开发中还有两个非常实用的场景:
场景一:本地两个项目互相依赖
比如你有两个项目:
-
项目 A:是一个工具包(比如叫
utils-package),里面有一些常用的工具函数; -
项目 B:是一个业务项目,需要用到项目 A 里的工具函数。
如果直接在项目 B 里用 npm install ../utils-package 安装项目 A,每次项目 A 的代码修改后,都要重新安装才能在项目 B 里看到更新,很麻烦。这时候用 npm link 就能解决:
-
进入项目 A 的文件夹,执行
npm link,把项目 A 链接到全局; -
进入项目 B 的文件夹,执行
npm link utils-package(utils-package是项目 A 的package.json里的 "name" 字段);
这样一来,项目 B 里就能像使用普通 npm 包一样,用 require('utils-package') 引入项目 A 的代码,而且项目 A 的代码修改后,项目 B 里能实时看到更新,不用反复安装。
场景二:调试已安装的依赖包
有时候你在项目里使用某个 npm 包(比如 lodash),发现某个功能有问题,想修改这个包的源码来调试(当然pnpm有更优雅的解决方案)。这时候也能用到 npm link:
-
先从 GitHub 上下载这个包的源码(比如 lodash 的源码),解压后进入源码文件夹,执行
npm link,把修改后的源码链接到全局; -
进入你的项目文件夹,执行
npm link lodash,把项目里的 lodash 替换成你本地修改后的源码; -
调试完成后,再执行
npm unlink lodash,并重新执行npm install lodash,恢复成官方的包即可。
5. 用完记得 "取消链接",避免影响后续使用
当你测试完或者不再需要本地链接时,记得取消链接,避免本地的测试版本影响后续使用官方版本。
取消链接分两步:
-
进入你之前执行
npm link的项目文件夹(比如my-first-cli),执行npm unlink,取消项目到全局的链接; -
如果其他项目链接过这个项目(比如前面的项目 B 链接过项目 A),还要进入这些项目文件夹,执行
npm unlink 包名(比如npm unlink utils-package),取消项目间的链接。
比如取消 my-first-cli 的链接:
bash
\# 进入 my-first-cli 文件夹
cd my-first-cli
\# 取消全局链接
npm unlink
五、总结:3 个核心知识点要记牢
-
bin 命令:给 JavaScript 脚本起 "简短别名",配置后不用输完整路径,直接喊别名就能运行脚本,配置时注意路径别写错;
-
shebang :脚本第一行的
#!/usr/bin/env node,告诉系统用 Node.js 运行脚本,别写死路径,兼容所有系统; -
npm link:本地测试和开发的 "神器",能创建项目快捷方式,实现代码实时更新,不用反复安装,用完记得取消链接。
六、结尾:动手试试,一次就会
看完这篇文章,建议你动手实操一次:建一个简单的项目,配置 bin 命令、加 shebang、用 npm link 测试。过程中如果遇到报错,先检查三个地方:脚本路径对不对、shebang 加没加、link 有没有成功。
其实这些知识点都不复杂,关键是多动手,试一次就能完全掌握,以后开发脚本或工具时,就能像那些常用的 npm 包一样,实现 "一键运行",大大提升开发效率。