npm run 的原理

我想本地模仿vue-cli-service 的调用方式,如何创建自己的 执行脚本,必须要node_modules吗{

"name": "commander",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo "Error: no test specified" && exit 1",

"gyk":"gyk"

},

"bin": {

"gyk": "bin/gyk.js"

},

"keywords": [],

"author": "",

"license": "ISC"

}

这是一个非常硬核且有趣的实验!你正在尝试制作一个属于自己的 CLI 工具。

要实现 npm run gyk 并且让系统识别到 gyk 这个命令(而不需要写 node bin/gyk.js),你需要理解 软链接(Symlink) 的机制。

在本地开发环境中,不需要 把包发布到 npm 仓库,也不一定非要装在 node_modules 里,但你需要模拟 npm install 的过程。

以下是实现你目标的三种方法,从最简单到最规范:


这是最标准的方式。npm link 会在全局或项目中创建一个软链接,欺骗系统以为这个包被"安装"了。

步骤:
  1. 准备文件结构

    确保你的目录结构如下:

    text 复制代码
    my-project/
    ├── package.json  (你贴的那段代码)
    └── bin/
        └── gyk.js    (你的执行脚本)
  2. 编写脚本 (bin/gyk.js)
    非常重要 :文件的第一行必须是 Shebang (#!/usr/bin/env node),告诉系统用 Node 来执行它。

    javascript 复制代码
    #!/usr/bin/env node
    
    console.log('🎉 恭喜!你成功调用了本地的 gyk 命令!');
    console.log('参数列表:', process.argv);
  3. 赋予执行权限 (Mac/Linux 必需)

    bash 复制代码
    chmod +x bin/gyk.js
  4. 创建链接 (核心步骤)

    package.json 所在的目录下运行:

    bash 复制代码
    npm link

    这一步发生了什么?

    npm 会读取你的 package.json 中的 bin 字段,并在你的全局 npm 目录(通常是 /usr/local/bin 或 AppData)下创建一个名为 gyk 的快捷方式,指向你本地的 bin/gyk.js

  5. 验证

    现在,你在终端的任何位置 直接输入 gyk,或者在项目中运行 npm run gyk,应该都能成功了。


方法二:本地依赖安装 (File Protocol)

如果你不想污染全局环境,只想在当前项目里用。

  1. 准备两个目录

    • my-cli-tool/ (存放你的 gyk 工具代码,有 bin 字段的 package.json)
    • my-app/ (你要使用这个工具的项目)
  2. my-app 中安装 my-cli-tool

    my-app 目录下运行:

    bash 复制代码
    npm install ../my-cli-tool

    (路径根据实际情况调整)

  3. 结果

    npm 会把 my-cli-tool 安装到 my-app/node_modules 下,并且自动检测�� bin 字段,把 gyk 命令链接到 my-app/node_modules/.bin/gyk

    此时在 my-apppackage.json 里写 "scripts": { "test": "gyk" } 即可正常工作。


方法三:自我引用 (Self-Referencing, 仅限 yarn/pnpm 或较新 npm)

如果你只有一个项目,既是工具本身,又是使用者(就像你现在的结构)。

在标准的 npm 安装流程发生之前,.bin 目录是不会自动生成的。所以直接运行 npm run gyk (其中 "gyk": "gyk") 通常会报错 command not found,因为 npm 还没根据 bin 字段创建链接。

解决方法:

你需要手动告诉 npm 把自己链接一下。

  1. 确保 package.json 如你所示

  2. 确保 bin/gyk.js#!/usr/bin/env node 头部

  3. 执行安装

    bash 复制代码
    npm install

    npm 某些版本在 install 自己时,会尝试处理 bin 链接。

如果 npm installnpm run gyk 依然报错,请回到 方法一 (npm link),这是开发本地 CLI 工具最稳健的方法。


常见坑点排查

  1. 报错 #!\/usr\/bin\/env: No such file or directory (Windows):

    这通常是因为你的文件换行符是 CRLF(Windows 风格)。CLI 工具的头部 Shebang 必须要是 LF(Unix 风格)。

    • 解决 :在编辑器里把 bin/gyk.js 的换行符格式改为 LF
  2. 报错 Permission denied

    • 解决chmod +x bin/gyk.js
  3. 修改代码后不生效

    如果你用了 npm link,修改代码是即时生效的,不需要重启或重新安装。

总结

要实现你的需求,最简单快捷的命令是:

  1. 添加 #!/usr/bin/env node 到 js 文件头。
  2. 在项目根目录执行 npm link
  3. 尽情享受你的 gyk 命令吧!

npm run gyk 发生了什么 ,我还如何写gyk 对应的执行程序

这是一个很好的切入点,能帮你彻底理解 npm scripts 的运行机制。

当你输入 npm run gyk 时,并不是 npm 自己在执行什么黑魔法,它本质上是一个命令行的"快捷方式"运行器

以下是详细的发生过程,以及你可以通过哪几种方式编写 gyk 的对应程序。


一、 npm run gyk 到底发生了什么?

当你按下回车时,npm 按顺序做了这三件大事:

1. 查找配方 (Lookup)

npm 去当前目录下的 package.json 文件里找 scripts 对象,看里面有没有一个叫 "gyk" 的 key。

  • 如果找不到,报错 Missing script: "gyk"
  • 如果找到了,比如 "gyk": "node scripts/my-task.js",它提取出后面的命令字符串。
2. 魔法路径增强 (Magic PATH) ------ 最关键的一步

npm 会临时把当前项目的 ./node_modules/.bin 目录加入到系统的环境变量 PATH最前面

  • 这意味着什么? 这意味着你可以在脚本里直接运行 webpackvue-cli-serviceeslint,而不需要写出完整的长路径(比如 ./node_modules/.bin/webpack)。
  • 注意:这个 PATH 修改只在脚本运行期间有效,运行完就恢复原样。
3. 启动 Shell 执行 (Spawn Shell)

npm 启动一个系统 Shell(Windows 上通常是 cmd.exe,Mac/Linux 上是 sh),然后把那个命令字符串扔给 Shell 去执行。


二、 你如何编写 gyk 对应的程序?

你有三种主要的方式来编写这个"执行程序",从简单到复杂:

方式 1:直接写 Shell 命令 (最简单)

如果逻辑很简单,直接写在 package.json 里。

json 复制代码
// package.json
{
  "scripts": {
    // 运行 gyk 时,直接在控制台打印一句话
    "gyk": "echo '我是 GYK,我正在运行!' && mkdir new-folder"
  }
}
方式 2:编写自定义 Node.js 脚本 (最推荐)

这是前端工程化中最常用的方式。你可以利用 Node.js 的强大能力做任何事(读写文件、网络请求、编译代码)。

步骤:

  1. 新建文件 :在项目根目录创建一个 my-gyk-script.js

    javascript 复制代码
    // my-gyk-script.js
    console.log('--- GYK 程序启动 ---');
    
    // 这里的代码是在 Node 环境运行的
    const fs = require('fs');
    const path = require('path');
    
    // 比如:创建一个叫 demo.txt 的文件
    fs.writeFileSync('demo.txt', '这是 gyk 创建的文件');
    
    console.log('文件创建成功!');
  2. 配置 package.json

    json 复制代码
    {
      "scripts": {
        "gyk": "node my-gyk-script.js"
      }
    }
  3. 运行npm run gyk

方式 3:使用 Shell 脚本 (Mac/Linux 常用)

如果你在 Mac 或 Linux 下,可以写 .sh 文件。

  1. 新建 script.sh

    bash 复制代码
    #!/bin/bash
    echo "正在清理缓存..."
    rm -rf ./dist
    echo "完成"
  2. 配置:"gyk": "bash script.sh" (注意 Windows 默认没有 bash,可能报错)。


三、 进阶:如何接收参数?

假设你想运行 npm run gyk test,然后在你的脚本里拿到 test 这个参数。

在你的 my-gyk-script.js 中:

javascript 复制代码
// process.argv 是一个数组,包含了启动 Node 进程时的所有参数
// [0]: node 的绝对路径
// [1]: 当前脚本文件的绝对路径
// [2]: 用户传进来的第一个参数

const args = process.argv.slice(2); // 去掉前两个固定的
console.log('接收到的参数:', args);

if (args[0] === 'fast') {
  console.log('执行快速模式...');
} else {
  console.log('执行普通模式...');
}

运行命令(注意中间的 --):

你需要用 -- 把 npm 的参数和传给你脚本的参数隔开:
npm run gyk -- fast


四、 底层揭秘:别人家的库(如 vue-cli-service)是怎么做到的?

你可能会问:"我自己写的脚本要用 node xxx.js 来运行,为什么 vue-cli-service 可以直接当命令用?"

这是因为 Vue CLI 的库在发布时,在其 package.json 里定义了 bin 字段:

json 复制代码
// @vue/cli-service 的 package.json (位于 node_modules 下)
{
  "name": "@vue/cli-service",
  "bin": {
    "vue-cli-service": "bin/vue-cli-service.js"
  }
}

当你 npm install @vue/cli-service 时,npm 会自动读取这个 bin 字段,并创建一个软链接(快捷方式) 到你的 ./node_modules/.bin/ 目录下。

所以,当你在 scripts 里写 "build": "vue-cli-service build" 时:

  1. npm 把 ./node_modules/.bin 加入 PATH。
  2. Shell 找到了 vue-cli-service 这个可执行文件(实际上指向了那个 JS 文件)。
  3. 脚本开始执行。

总结

你想写 gyk 程序,最实用的路径是:写一个 Node.js 脚本文件,然后在 package.json 的 scripts 中用 node your-script.js 来调用它。

相关推荐
木斯佳1 小时前
前端八股文面经大全:2026-01-13MiniMax前端实习二面面经深度解析
前端·状态模式
远离UE41 小时前
Blender模型正常导入UE5 FBX 轴向匹配
前端
谭光志1 小时前
OpenClaw 安装与运行教程
前端·后端·ai编程
0思必得02 小时前
[Web自动化] Selenium浏览器复用
前端·python·selenium·自动化
之歆2 小时前
Linux 系统安装、故障排除、sudo、加密、DNS 与 Web 服务整理
linux·运维·前端
OpenTiny社区3 小时前
TinyEngine 2.10 版本发布:零代码 CRUD、云端协作,开发效率再升级!
前端·vue.js·低代码
哟哟-3 小时前
Nginx配置:静态文件访问时动态添加时间戳
运维·前端·javascript·nginx
码云数智-园园3 小时前
自助建站哪个好?三款主流自助建站对比评测
前端
肆忆_3 小时前
C++ 汇编层面与语法语义层面总结:this指针 模板 块级作用域 引用
前端