要查找 npm 脚本在 Mac 上使用的目录,请查看该脚本属于哪个包,然后从该脚本内部打印出该目录。即使您在其他位置启动 npm run,npm 也会从其包文件夹运行脚本。在工作区项目中,所选的工作区包可能就是相关的文件夹。以下步骤可帮助您确定确切路径,并将其与您键入命令的文件夹区分开来。

1. 查找您正在运行的包和脚本

打开“终端”并进入您通常运行 npm 的项目文件夹。macOS 终端中默认使用 zsh,不过您的 shell 是可以更改的。使用 pwd 显示当前目录,然后列出文件以查看该文件夹是否包含 package.json 文件。Apple 的终端指南解释了如何在终端中输入命令以及使用诸如 ls 等工具。

pwd
ls

如果您不确定是哪个包定义了该脚本,请检查当前文件夹中的 package.json。您可以使用 cat package.json 显示它,或者在文本编辑器中打开它。在 scripts 对象下找到脚本名称。例如,在 "scripts": { "build": "node build.js" } 中,要运行的脚本名称是 build。如果这是一个工作区代码仓,请不要假定顶层项目文件夹就一定拥有该脚本。

2. 检查 npm 的预期目录

对于当前的 npm 版本,无论您从哪个目录调用 npm run,脚本都会从包文件夹的根目录运行。在标准项目中,这就是包含该包的 package.json 的文件夹。在工作区项目中,npm 可以在选定工作区的上下文中运行脚本;此时该工作区对应的包才是需要检查的对象。请参阅 npm 关于脚本工作目录和在工作区中运行脚本的文档。

文档记录的这种行为是一个很好的初步参考,但如果脚本内部更改了目录,或者您需要确认某个特定命令看到的内容,请在执行期间打印出路径。脚本内部诸如 cd 之类的 shell 命令可以更改其后命令的目录,因此单看包文件夹可能无法反映完整情况。

3. 从脚本内部打印目录

最明确的检查方法是在 package.json 中的脚本命令开头临时添加 pwd。例如,将:

"build": "node build.js"

更改为:

"build": "pwd && node build.js"

然后照常运行该脚本:

npm run build

在构建命令之前打印出的路径就是当时 shell 的工作目录。该诊断使用了 &&,因此仅在 pwd 成功时才会运行 node build.js。检查完毕后,删除用于诊断的前缀并恢复原始命令。如果原始脚本已经使用了 shell 运算符、引号或包装命令,请在保存前检查文件;保留其预期的顺序和语法。

如果该脚本是一个 Node.js 文件并且您可以对其进行编辑,另一种直接的检查方法是在其开头附近临时添加 console.log(process.cwd())。Node 将 process.cwd() 记录为 Node.js 进程的当前工作目录。这会报告该行代码执行时 Node 所看到的目录;如果程序稍后更改了其工作目录,该值可能会发生变化。

4. 查看结果并考虑工作区因素

将打印出的路径与运行 npm 之前 pwd 显示的路径进行比较。它们可能会有所不同:npm 的脚本目录是包的根目录,而您的终端目录是您启动命令的位置。例如,如果您的终端从代码仓根目录启动,但您运行的是由 packages/site 下的包定义的脚本,则该脚本的包上下文可以是该工作区。npm 文档记录了使用 --workspace 选择一个工作区;您也可以从工作区目录内部运行脚本。

npm run build --workspace=site

请使用与项目的 workspaces 配置匹配的工作区名称或路径。如果输出不符合预期,请确认您选择了正确的脚本和工作区,然后检查脚本本身是否包含 cd 或调用了其他会更改目录的工具。子进程也可能有其自己的工作目录设置;如果子进程的行为与父脚本不同,请检查该工具的配置。

INIT_CWD 能告诉您什么

npm 为您调用 npm run 时所在的目录提供了 INIT_CWD。当脚本需要知道调用者从何处启动时,该值会有所帮助,但它不是脚本的当前工作目录。在 shell 脚本中使用 pwd 或在 Node.js 中使用 process.cwd() 可以检查正在运行的进程所看到的目录。当相对文件路径在一个调用位置有效而在另一个位置无效时,这种区分尤为有用。

若要快速排查,请首先依据 npm 的包根目录规则,根据需要选择目标工作区,并在脚本内部打印 pwd 以确认其运行时的实际路径。

参考来源